RELATEED CONSULTING
相关咨询
选择下列产品马上在线沟通
服务时间:8:30-17:00
你可能遇到了下面的问题
关闭右侧工具栏

新闻中心

这里有您想知道的互联网营销解决方案
Spring中如何获取request的方法汇总及其线程安全性分析-创新互联

前言

在贵池等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站设计、成都网站制作、外贸网站建设 网站设计制作按需定制网站,公司网站建设,企业网站建设,成都品牌网站建设,全网整合营销推广,成都外贸网站制作,贵池网站建设费用合理。

本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性。下面话不多说了,来一起看看详细的介绍吧。

概述

在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端ip地址、请求的url、header中的属性(如cookie、授权信息)、body中的数据等。由于在Spring MVC中,处理请求的Controller、Service等对象都是单例的,因此获取request对象时最需要注意的问题,便是request对象是否是线程安全的:当有大量并发请求时,能否保证不同请求/线程中使用不同的request对象。

这里还有一个问题需要注意:前面所说的“在处理请求时”使用request对象,究竟是在哪里使用呢?考虑到获取request对象的方法有微小的不同,大体可以分为两类:

1)      在Spring的Bean中使用request对象:既包括Controller、Service、Repository等MVC的Bean,也包括了Component等普通的Spring Bean。为了方便说明,后文中Spring中的Bean一律简称为Bean。

2)      在非Bean中使用request对象:如普通的Java对象的方法中使用,或在类的静态方法中使用。

此外,本文讨论是围绕代表请求的request对象展开的,但所用方法同样适用于response对象、InputStream/Reader、OutputStream/ Writer等;其中InputStream/Reader可以读取请求中的数据,OutputStream/ Writer可以向响应写入数据。

最后,获取request对象的方法与Spring及MVC的版本也有关系;本文基于Spring4进行讨论,且所做的实验都是使用4.1.1版本。

如何测试线程安全性

既然request对象的线程安全问题需要特别关注,为了便于后面的讨论,下面先说明如何测试request对象是否是线程安全的。

测试的基本思路,是模拟客户端大量并发请求,然后在服务器判断这些请求是否使用了相同的request对象。

判断request对象是否相同,最直观的方式是打印出request对象的地址,如果相同则说明使用了相同的对象。然而,在几乎所有web服务器的实现中,都使用了线程池,这样就导致先后到达的两个请求,可能由同一个线程处理:在前一个请求处理完成后,线程池收回该线程,并将该线程重新分配给了后面的请求。而在同一线程中,使用的request对象很可能是同一个(地址相同,属性不同)。因此即便是对于线程安全的方法,不同的请求使用的request对象地址也可能相同。

为了避免这个问题,一种方法是在请求处理过程中使线程休眠几秒,这样可以让每个线程工作的时间足够长,从而避免同一个线程分配给不同的请求;另一种方法,是使用request的其他属性(如参数、header、body等)作为request是否线程安全的依据,因为即便不同的请求先后使用了同一个线程(request对象地址也相同),只要使用不同的属性分别构造了两次request对象,那么request对象的使用就是线程安全的。本文使用第二种方法进行测试。

客户端测试代码如下(创建1000个线程分别发送请求):

public class Test {
 public static void main(String[] args) throws Exception {
 String prefix = UUID.randomUUID().toString().replaceAll("-", "") + "::";
 for (int i = 0; i < 1000; i++) {
 final String value = prefix + i;
 new Thread() {
 @Override
 public void run() {
 try {
 CloseableHttpClient httpClient = HttpClients.createDefault();
 HttpGet httpGet = new HttpGet("http://localhost:8080/test?key=" + value);
 httpClient.execute(httpGet);
 httpClient.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }.start();
 }
 }
}

分享题目:Spring中如何获取request的方法汇总及其线程安全性分析-创新互联
文章路径:http://scyingshan.cn/article/dhdeoi.html