分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!点击浏览教程
前言在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端ip地址、请求的url、header中的属性(如cookie、授权信息)、body中的数据等。由于在Spring MVC中,处理请求的Controller、Service等对象都是单例的,因此获取request对象时最需要注意的问题,便是request对象是否是线程安全的:当有大量并发请求时,能否保证不同请求/线程中使用不同的request对象。
1)、在哪里使用request对象呢?第一种:在Spring的Bean中使用request对象:既包括Controller、Service、Repository等MVC的Bean,也包括了Component等普通的Spring Bean。
第二种:在非Bean中使用request对象:如普通的Java对象的方法中使用,或在类的静态方法中使用。
2)常见的Spring获取request对象的方式第一种:最简单的方式,使用注解
@Autowired
private HttpServletRequest request;
第二种:web.xml中配置一个监听器
org.springframework.web.context.request.RequestContextListener
程序中使用:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
第三种:作为请求参数传进来
public String hello(HttpServletRequest request,HttpServletResponse response)
如果使用struts2,可以使用:
HttpServletRequest request = ServletActionContext.getRequest();
4)SpringBoot三种获取Request和Response的方法
第一种:通过静态方法获取,你也可以封装一个静态方法出来
@GetMapping(value = "")
public String center() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
HttpServletResponse response = servletRequestAttributes.getResponse();
//...
}
第二种:通过参数直接获取
@GetMapping(value = "")
public String center(HttpServletRequest request,HttpServletResponse response) {
//...
}
第三种:注入
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
@GetMapping(value = "")
public String center() {
//...
}
一、如何测试线程安全性
既然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
关注
打赏
- Java基础学习总结(175)——分布式ID的9种生成方式总结
- 2016年终总结
- 青春路上,岁月如烟
- Terraform 学习总结(10)—— 阿里云平台 Terraform 代码开发技巧总结
- Terraform 学习总结(9)—— 如何解决存量云资源的管理难题
- Java基础学习总结(197)—— CompletableFuture 异常处理总结
- Kubernetes 学习总结(36)—— Kubernetes 本地运行的四种方法
- Linux 学习总结(90)—— Linux 远程数据同步工具 Rsync(remote synchronize)详解
- Java基础学习总结(196)—— Java、Spring、Dubbo 三种 SPI 机制详解
- Kubernetes 学习总结(35)—— Kubernetes 1.25 正式发布,多方面重大突破