没有合适的资源?快使用搜索试试~ 我知道了~
SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现1
需积分: 0 0 下载量 94 浏览量
2022-08-03
20:05:58
上传
评论
收藏 200KB PDF 举报
温馨提示
试读
12页
如果说将Spring上下关联到Servlet容器中,是SpringMVC框架的第个亮点,那么在请求转发流程中,SpringMVC对各种处理环节编程元素的抽象,就
资源推荐
资源详情
资源评论
SpringMVC源码剖析(四)-
DispatcherServlet请求转发的实现 - 相
见欢
SpringMVC完成初始化流程之后,就进⼊Servlet标准⽣命周期的第⼆个阶
段,即“service”阶段。在“service”阶段中,每⼀次Http请求到来,容器都会启
动⼀个请求线程,通过service()⽅法,委派到doGet()或者doPost()这些⽅法,
完成Http请求的处理。
在初始化流程中,SpringMVC巧妙的运⽤依赖注⼊读取参数,并最终建⽴⼀
个与容器上下⽂相关联的Spring⼦上下⽂。这个⼦上下⽂,就像Struts2中
xwork容器⼀样,为接下来的Http处理流程中各种编程元素提供了容⾝之
所。如果说将Spring上下⽂关联到Servlet容器中,是SpringMVC框架的第⼀
个亮点,那么在请求转发流程中,SpringMVC对各种处理环节编程元素的抽
象,就是另外⼀个独具匠⼼的亮点。
Struts2采取的是⼀种完全和Web容器隔离和解耦的事件机制。诸如Action对
象、Result对象、Interceptor对象,这些都是完全脱离Servlet容器的编程元
素。Struts2将数据流和事件处理完全剥离开来,从Http请求中读取数据后,
下⾯的事件处理流程就只依赖于这些数据,⽽完全不知道有Web环境的存
在。
反观SpringMVC,⽆论HandlerMapping对象、HandlerAdapter对象还是View
对象,这些核⼼的接⼜所定义的⽅法中,HttpServletRequest和
HttpServletResponse对象都是直接作为⽅法的参数出现的。这也就意味着,
框架的设计者,直接将SpringMVC框架和容器绑定到了⼀起。或者说,整个
SpringMVC框架,都是依托着Servlet容器元素来设计的。下⾯就来看⼀下,
源码中是如何体现这⼀点的。
1.请求转发的⼊⼜
就像任何⼀个注册在容器中的Servlet⼀样,DispatcherServlet也是通过⾃⼰的
service()⽅法来接收和转发Http请求到具体的doGet()或doPost()这些⽅法的。
以⼀次典型的GET请求为例,经过HttpServlet基类中service()⽅法的委派,请
求会被转发到doGet()⽅法中。doGet()⽅法,在DispatcherServlet的⽗类
FrameworkServlet类中被覆写。
可以看到,这⾥只是简单的转发到processRequest()这个⽅法。
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// Expose current LocaleResolver and request as LocaleContext.
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this
// Expose current RequestAttributes to current thread.
RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = null;
if (previousRequestAttributes == null || previousRequestAttributes.getClass().equals(ServletRequestAttributes.
requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes,
}
if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
}
try {
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
代码有点长,理解的要点是以doService()⽅法为区隔,前⼀部分是将当前请
求的Locale对象和属性,分别设置到LocaleContextHolder和
RequestContextHolder这两个抽象类中的ThreadLocal对象中,也就是分别将
这两个东西和请求线程做了绑定。在doService()处理结束后,再恢复回请求
前的LocaleContextHolder和RequestContextHolder,也即解除线程绑定。每次
请求处理结束后,容器上下⽂都发布了⼀个ServletRequestHandledEvent事
件,你可以注册监听器来监听该事件。
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed"
}
finally {
// Clear request attributes and reset thread-bound context.
LocaleContextHolder.setLocaleContext(previousLocaleContext,
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(previousRequestAttributes,
requestAttributes.requestCompleted();
}
if (logger.isTraceEnabled()) {
logger.trace("Cleared thread-bound request context: "
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request"
}
else {
this.logger.debug("Successfully completed request"
}
}
if (this.publishEvents) {
// Whether or not we succeeded, publish an event.
long processingTime = System.currentTimeMillis() - startTime;
this.webApplicationContext.publishEvent(
new ServletRequestHandledEvent(this
request.getRequestURI(), request.getRemoteAddr(),
request.getMethod(), getServletConfig().getServletName(),
WebUtils.getSessionId(request), getUsernameForRequest(request),
processingTime, failureCause));
}
}
}
剩余11页未读,继续阅读
资源评论
首席程序IT
- 粉丝: 29
- 资源: 305
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功