SpringMVC中RequestContextHolder获取请求信息的方法

RequestContextHolder的作用是:

在Service层获取获取request和response信息

代码示例:

ServletRequestAttributes attrs = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attrs.getRequest();

源码分析:

定义了两个ThreadLocal变量用来存储Request

private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
  private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context");

设置方法

public static void setRequestAttributes(@Nullable RequestAttributes attributes) {
    setRequestAttributes(attributes, false);
  }

  public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
    if (attributes == null) {
      resetRequestAttributes();
    } else if (inheritable) {
      inheritableRequestAttributesHolder.set(attributes);
      requestAttributesHolder.remove();
    } else {
      requestAttributesHolder.set(attributes);
      inheritableRequestAttributesHolder.remove();
    }

  }

是在SpringMVC处理Servlet的类FrameworkServlet的类中,doget/dopost方法,调用processRequest方法进行初始化上下文方法中initContextHolders设置进去的

private void initContextHolders(HttpServletRequest request, @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {
    if (localeContext != null) {
      LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
    }

    if (requestAttributes != null) {
      RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
    }

    if (this.logger.isTraceEnabled()) {
      this.logger.trace("Bound request context to thread: " + request);
    }

  }

再看一下请求信息怎么获取

@Nullable
  public static RequestAttributes getRequestAttributes() {
    RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
    if (attributes == null) {
      attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
    }

    return attributes;
  }

解决疑问

1 request和response怎么和当前请求挂钩?

首先分析RequestContextHolder这个类,里面有两个ThreadLocal保存当前线程下的request,关于ThreadLocal可以参考我的另一篇博文[Java学习记录--ThreadLocal使用案例]

//得到存储进去的request
private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
new NamedThreadLocal<RequestAttributes>("Request attributes");
//可被子线程继承的request
private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
new NamedInheritableThreadLocal<RequestAttributes>("Request context");

再看`getRequestAttributes()`方法,相当于直接获取ThreadLocal里面的值,这样就保证了每一次获取到的Request是该请求的request.

public static RequestAttributes getRequestAttributes() {
    RequestAttributes attributes = requestAttributesHolder.get();
    if (attributes == null) {
      attributes = inheritableRequestAttributesHolder.get();
    }
    return attributes;
  }

2request和response等是什么时候设置进去的?

找这个的话需要对springMVC结构的`DispatcherServlet`的结构有一定了解才能准确的定位该去哪里找相关代码.

在IDEA中会显示如下的继承关系.

左边1这里是Servlet的接口和实现类.

右边2这里是使得SpringMVC具有Spring的一些环境变量和Spring容器.类似的XXXAware接口就是对该类提供Spring感知,简单来说就是如果想使用Spring的XXXX就要实现XXXAware,spring会把需要的东西传送过来.

那么剩下要分析的的就是三个类,简单看下源码

1. HttpServletBean 进行初始化工作

2. FrameworkServlet 初始化 WebApplicationContext,并提供service方法预处理请

3. DispatcherServlet 具体分发处理.

那么就可以在FrameworkServlet查看到该类重写了service(),doGet(),doPost()...等方法,这些实现里面都有一个预处理方法`processRequest(request, response);`,所以定位到了我们要找的位置

查看`processRequest(request, response);`的实现,具体可以分为三步:

  1. 获取上一个请求的参数
  2. 重新建立新的参数
  3. 设置到XXContextHolder
  4. 父类的service()处理请求
  5. 恢复request
  6. 发布事
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//获取上一个请求保存的LocaleContext
  LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//建立新的LocaleContext
  LocaleContext localeContext = buildLocaleContext(request);
//获取上一个请求保存的RequestAttributes
  RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//建立新的RequestAttributes
  ServletRequestAttributes requestAttributes = buildRequestAttributes(request,
response, previousAttributes);
  WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(),
new RequestBindingInterceptor());
//具体设置的方法
  initContextHolders(request, localeContext, requestAttributes);
try {
    doService(request, response);
  }
catch (ServletException ex) {
failureCause = ex;
throw ex;
  }
catch (IOException ex) {
  failureCause = ex;
  throw ex;
  }
catch (Throwable ex) {
  failureCause = ex;
  throw new NestedServletException("Request processing failed", ex);
  }
finally {
//恢复
    resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
    }
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
      }
else {
if (asyncManager.isConcurrentHandlingStarted()) {
          logger.debug("Leaving response open for concurrent processing");
        }
else {
this.logger.debug("Successfully completed request");
        }
      }
    }
//发布事件
    publishRequestHandledEvent(request, response, startTime, failureCause);
  }
}

再看initContextHolders(request, localeContext, requestAttributes)方法,把新的RequestAttributes设置进LocalThread,实际上保存的类型为ServletRequestAttributes,这也是为什么在使用的时候可以把RequestAttributes强转为ServletRequestAttributes.

private void initContextHolders(HttpServletRequest request,
                LocaleContext localeContext,
                RequestAttributes requestAttributes) {
if (localeContext != null) {
    LocaleContextHolder.setLocaleContext(localeContext,
this.threadContextInheritable);
  }
if (requestAttributes != null) {
    RequestContextHolder.setRequestAttributes(requestAttributes,
this.threadContextInheritable);
  }
if (logger.isTraceEnabled()) {
    logger.trace("Bound request context to thread: " + request);
  }
}

因此RequestContextHolder里面最终保存的为ServletRequestAttributes,这个类相比`RequestAttributes`方法是多了很多.

到此这篇关于SpringMVC中RequestContextHolder获取请求信息的方法的文章就介绍到这了,更多相关SpringMVC RequestContextHolder请求信息内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间:2020-04-03

之前写过通过注释的方法解决跨域请求的方法,需要每次都在controll类使用注解,这次通过springmvc的拦截器解决: 继承SpringMVC的类HandlerInterceptor重写preHandle方法,这个方法会在到达 controll之前调用,如下 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

一. 在HTTP 协议里面,四个表示操作方式的动词:GET.POST.PUT.DELETE. 它们分别对应四种基本操作: 1.GET ====== 获 取资源 2.POST ======新建资源 3.PUT======= 更新资源 4.DELETE==== 删除资源 二.REST:即 Representational State Transfer.(资源)表现层状态转化.是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便, 所以正得到越来越多网站的采用. 我们可以通过re

这篇文章主要介绍了SpringMVC post请求中文乱码问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们在页面难免提交一些中文数据给后台处理,但是发现后台拿到的数据乱码,可以在每一个controller中都设置编码,但是太过于麻烦, 正确的解决办法应该是在web.xml中配置解决中文乱码的过滤器: 问题现象:控制台打印中文乱码如下: 解决办法如下: (web.xml中配置解决中文乱码的顾虑器CharacterEncodingFil

这几年都在搞前后端分离.RESTful风格,我们项目中也在这样用.前几天有人遇到了解析JSON格式的请求数据的问题,然后说了一下解析的方式,今天就写篇文章简单的分析一下后台对于JSON格式请求数据是怎么解析的. 先把例子的代码贴出来: 前端 <input type="button" value="测试JSON数据" onclick="testJSON()" /> <script type="text/javascrip

spring接收请求参数: 1,使用HttpServletRequest获取 @RequestMapping("/login.do") public String login(HttpServletRequest request){ String name = request.getParameter("name") String pass = request.getParameter("pass") } 2,Spring会自动将表单参数注入到方

forword跳转页面的三种方式: 1.使用serlvet /** * 使用forward跳转,传递基本类型参数到页面 * 注意: * 1.使用servlet原生API Request作用域 * */ @RequestMapping("/test") public String test(HttpServletRequest request,HttpServletResponse response){ String name = "张小三"; request.set

springmvc 3.2开始就支持servlet3.0的异步请求.平常我们请求一个controller一般都是同步的,如果在代码执行中,遇到耗时的业务操作,那servlet容器线程就会被锁死,当有其他请求进来的时候就会受堵了. springmvc3.2之后支持异步请求,能够在controller中返回一个Callable或者DeferredResult.当返回Callable的时候,大概的执行过程如下: 当controller返回值是Callable的时候,springmvc就会启动一个线程将

axios发送post请求时,出现了参数后台接收不到的情况,分析了下请求,发现是请求头content-type不对,是application/json,正常应该是application/x-www-form-urlencoded. 解决方法有以下三种: 1.设置axios的默认请求头 //设置全局的 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; var instance = a

一 环境搭建 首先是常规的spring mvc环境搭建,不用多说,需要注意的是,这里需要引入jackson相关jar包,然后在spring配置文件"springmvc-servlet.xml"中添加json解析相关配置,我这里的完整代码如下: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schem

上一篇讲了Ajax请求数据text类型,text和html都是处理比较简答的数据,而在编程过程中使用Ajax调用数据的时候,难免要进行逻辑的处理,接受的数据也变的复杂比如数组类型的数据,这时候就需要使用JSON数据类型进行处理,今天就说说,JSON数据请求过程中的一些细节: 我们友情提醒本文所需工具和原料如下: wamp或lamp环境.jquery.js.编辑器 具体方法/步骤请看下面: 1.创建基本的文件结构json_ajax.html和json_ajax.php,下载jquery.js,如图

jquery的ajax异步请求接收返回json数据方法设置简单,一个是服务器处理程序是返回json数据,另一种就是ajax发送设置的datatype设置为jsonp格式数据或json格式都可以. 代码示例如下: 复制代码 代码如下: $('#send').click(function () {     $.ajax({         type : "GET",         url : "a.php",         dataType : "json

废话不多说了,直接给大家贴代码了,具体代码如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta charset="UTF-

AJAX的全称是Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX不是新的编程语言,而是一种使用现有标准的新方法.ajax是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下. ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. ajax是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换.ajax可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分

做前端开发的朋友对于ajax异步更新一定印象深刻,作为刚入坑的小白,今天就和大家一起聊聊关于ajax异步请求的那点事.既然是ajax就少不了jQuery的知识,推荐大家访问www.w3school.com学习,教程完善,适合初学者快速入门. jQuery的引用,可以通过下载js文件导入,或通过外部导入 <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" type="text/javascript"

之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html <a href="javascript:void(0)" onmouseover="testAsync()"> asy.js function testAsync{ var temp; $.ajax({ async: false, type : "GET", url : 'tet.php', complete: functi

ajax可以发送异步请求实现无刷新效果,但是使用javascript比较麻烦,就query提供了一些封装的方法 ,可以使得操作更为简单: $.ajax()方法: function sendRequest() { $.ajax({ url: "Hello", type: "GET", dataType: "txt", data: "name=zhangsan", complete: function(result){ alert

首先,Ajax请求数据,(用的是Jquery的Ajax) 复制代码 代码如下: <script> $(function(){ $('#test').click(function(){ $.ajax({ url:'__APP__/Article/jsonTest', type:'post', success:function(data){ var item; $.each(data,function(i,result){ item = "<tr><td>&quo

本文实例讲述了django通过ajax发起请求返回JSON格式数据的方法.分享给大家供大家参考.具体实现方法如下: 这是后台处理的: def checkemail(request): user = None if request.POST.has_key('email'): useremail = request.POST['email'] result = {} user = User.objects.filter(useremail__iexact = useremail) if user:

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章