DispatcherServlet来看spring mvc请求处理过程
架构
官方架构图
可以看到请求处理过程,而DispatcherServlet正是担当front controller的角色。
生命周期
通过源码可以看到,DispatcherServlet继承自FrameworkServlet,FrameworkServlet继承HttpServletBean,HttpServletBean继承HttpServlet。
而Servlet生命周期的三个阶段就是【init-service-destroy】
所以对DispatcherServlet而言,类似最初进行servlet编程。继承HttpServlet,重写doGet、doPost,在方法中跳转到jsp页面,利用注解或者在xml文件中注册Servlet。
初始化
在HttpServletBean中,覆写了HttpServlet类的init()方法。
前面是将web.xml中在DispatcherServlet这个Servlet下面的<init-param>
配置元素利用JavaBean的方式(即通过setter方法)读取到DispatcherServlet中来
值得一提的是其中有一句
initServletBean();
但是在HttpServletBean中是一个空方法,留给子类来实现,这就是模版方法,在父类中定义执行流程,把可变的部分留给子类实现。体现了开闭原则。
initServletBean在FrameworkServlet中关键的一句
this.webApplicationContext = initWebApplicationContext();
所以FrameworkServlet存在的意义也用来抽离出建立 WebApplicationContext 上下文这个过程的。建立一个和Servlet关联的Spring容器上下文,并将其注册到ServletContext中。
因为DispatcherServlet重写了onRefresh,建立上下文后,通过onRefresh(ApplicationContext context)方法的回调,进入到DispatcherServlet类
onRefresh方法中initStrategies()封装了初始化策略
以detectAllHandlerMappings为例,detectAllHandlerMappings默认为true,把上下文中所有HandlerMapping类型的Bean都注册在handlerMappings这个List变量中。
总结:HttpServletBean完成的是<init-param>
配置元素的依赖注入,FrameworkServlet完成的是容器上下文的建立,DispatcherServlet完成的是SpringMVC具体编程元素的初始化策略。
Service
以Get请求为例,经过HttpServlet基类中service()方法的委派,请求会被转发到doGet()方法中。doGet()方法,在DispatcherServlet的父类FrameworkServlet类中被重写。
封装了processRequest方法,关键就是doService(request, response);
前一部分是将当前请求的Locale对象和属性,分别设置到LocaleContextHolder和RequestContextHolder这两个抽象类中的ThreadLocal对象中,也就是分别将这两个东西和请求线程做了绑定。在doService()处理结束后,再恢复回请求前的LocaleContextHolder和RequestContextHolder,也即解除线程绑定。每次请求处理结束后,容器上下文都发布了一个ServletRequestHandledEvent事件,你可以注册监听器来监听该事件。
只是做了一些线程安全的隔离。
doService又是一个抽象方法。子类实现。实现在DispatcherServlet中doDispatch(request, response);
几个requet.setAttribute()方法的调用,将前面在初始化流程中实例化的对象设置到http请求的属性中,供下一步处理使用,其中有容器的上下文对象、本地化解析器等SpringMVC特有的编程元素。
doDispatch中
mappedHandler = getHandler(processedRequest);
获得处理请求的handler,返回HandlerExecutionChainHandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
获得处理请求的handler adaptermappedHandler.applyPreHandle(processedRequest, response
执行interceptor的prehandle方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
实际调用handler,返回ModelAndViewapplyDefaultViewName(processedRequest, mv);
设置view的名字
mappedHandler.applyPostHandle(processedRequest, response, mv);
执行intercepter的postHandle方法,processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
发送结果
数据结构
HandlerMapping、HandlerAdapter、View这些接口的设计。
HandlerAdapter:是一个接口。support方法根据类型来判断该adapter是否支持handler实例,handle方法用给定的handler处理请求;
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
HandlerMapping接口中:
getHandler获取请求的handler和所有interceptors,返回HandlerExecutionChain的对象
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
//...
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
View接口:
主要是render方法 void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
HandlerExecutionChain:主要包含 interceptors的list,和一个handle,这里handler是由Object对象来引用的,没有绑定任何接口,这里说明了任何对象都可以作为最后的处理对象来生成视图
ModelAndView是处理的结果,主要包含Object引用的view,和ModelMap引用的model。view可以是view名(String)或者是一个view的实例。ModelMap继承LinkedHashMap,也就是一个map,放了属性名和属性值。
HandlerInterceptor这个接口,定义了拦截器的实现
preHandle,postHandle,afterCompletion就像刚刚在doDispatch中一样,环绕着hanlder实现,分别在handler执行前,执行后和渲染后执行。
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
}
深入处理流程
mappedHandler
mappedHandler = getHandler(processedRequest);
可以看出getHandler方法就是遍历初始化时已经获取的handlerMappings,如果找到一个HandlerMapping,getHandler方法返回的不为null,那么说明找到了这个mappedHandler,并返回。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
getHandler的实现在AbstractHandlerMapping类中,根据request找到Handler和Interceptor,组合成HandlerExecutionChain类型并返回
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
getHandlerInternal是个接口
AbstractHandlerMethodMapping,AbstractUrlHandlerMapping都实现了它。其中AbstractHandlerMethodMapping更常用,注解@RequestMapping的方式就属于它,它将被注解的Method作为handler。
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
lookupHandlerMethod方法来查找url和对应的方法
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
从mappingRegistry中获取匹配路径的mapping,并排序获取最匹配的handlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<Match>();
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
getHandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
同样也是遍历handlerAdapters中所有的adapter,如果和handler的类型匹配,就返回handlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
applyPreHandle
mappedHandler.applyPreHandle(processedRequest, response
依次执行interceptor的prehandle方法,如果又一个拦截器返回false就停止
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
handle
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
这个方法在handlerAdapter的接口中,有几个实现,AbstractHandlerMethodAdapter,AnnotationMethodHandlerAdapter,,,
SimpleServletHandlerAdapter:handle方法就是调用Servlet的service((Servlet) handler).service(request, response);
。
SimpleControllerHandlerAdapter:handle方法本质是执行Controller.handleRequest方法return ((Controller) handler).handleRequest(request, response);
HttpRequestHandlerAdapter: ((HttpRequestHandler) handler).handleRequest(request, response);
AbstractHandlerMethodAdapter:是一个抽象类,handle方法调用handleInternal,handleInternal是一个接口,在实现类RequestMappingHandlerAdapter中实现。关键的地方在于调用invokeHandlerMethod
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
//...
mav = invokeHandlerMethod(request, response, handlerMethod);
//..
prepareResponse(response);
//..
return mav;
}
invokeHandlerMethod就是在执行传入的handler方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
.........
//执行Controller中的RequestMapping注释的方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
//返回ModelAndView视图
return getModelAndView(mavContainer, modelFactory, webRequest);
}
applyDefaultViewName
applyDefaultViewName(processedRequest, mv);
很简单,就是设置一下view
private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
}
applyPostHandle
同上applyPreHandle,执行拦截器list中的postHandle方法
processDispatchResult
关键就是调用render方法,然后执行拦截器列表中的AfterCompletion方法
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
render方法中,关键的一步view.render(mv.getModelInternal(), request, response);
这个接口在AbstractView这个抽象类中定义了模版方法
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
createMergedOutputModel,关键是这些putAll方法,把静态的attribute和动态值方都放进mergedModel中然后返回,可以看到先put staticAttributes后put model,所以说明动态的值优先级更高可能覆盖静态attribute的值
protected Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) {
...
Map<String, Object> mergedModel = new LinkedHashMap<String, Object>(size);
mergedModel.putAll(this.staticAttributes);
if (pathVars != null) {
mergedModel.putAll(pathVars);
}
if (model != null) {
mergedModel.putAll(model);
}
// Expose RequestContext?
if (this.requestContextAttribute != null) {
mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));
}
return mergedModel;
}
prepareResponse就是设置response头
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
if (generatesDownloadContent()) {
response.setHeader("Pragma", "private");
response.setHeader("Cache-Control", "private, must-revalidate");
}
}
renderMergedOutputModel又是一个接口protected abstract void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
有很多实现,对于jsp,在InternalResourceView类中实现
@Override
protected void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Expose the model object as request attributes.
exposeModelAsRequestAttributes(model, request);
// Expose helpers as request attributes, if any.
exposeHelpers(request);
// Determine the path for the request dispatcher.
String dispatcherPath = prepareForRendering(request, response);
// Obtain a RequestDispatcher for the target resource (typically a JSP).
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
// If already included or response already committed, perform include, else forward.
if (useInclude(request, response)) {
response.setContentType(getContentType());
rd.include(request, response);
}
else {
// Note: The forwarded resource is supposed to determine the content type itself.
rd.forward(request, response);
}
}
exposeModelAsRequestAttributes方法就是把model中的值都填到request中
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
for (Map.Entry<String, Object> entry : model.entrySet()) {
String modelName = entry.getKey();
Object modelValue = entry.getValue();
if (modelValue != null) {
request.setAttribute(modelName, modelValue);
}
else {
request.removeAttribute(modelName);
}
}
}
如果response已经提交了,included,否则就执行forward
到这里,请求处理结束。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。