News/新闻中心

SpringMVC深入理解返回

2017/2/20 17:33:06

核心类与接口

- DispatcherServlet 前置控制器
- HandlerMapping 请求映射(到Controller)
- HandlerAdapter 请求映射(到Controller类的方法上)
- Controller 控制器
- HandlerIntercepter 拦截器
- ViewResolver 视图映射
- View 视图处理

启动过程


Spring MVC启动过程大致分为两个过程:
- ContextLoaderListener初始化,读取context-param中的contextConfigLocation指定的配置文件,创建ROOT Context,通过调用继承自ContextLoader的initWebApplicationContext方法实例化Spring IoC容器,并将此容器实例注册到ServletContext中
- ContextLoaderListener初始化完毕后,开始初始化web.xml中配置的DispatcherServlet,DispatcherServlet的初始化又包括了视图管理器、异常处理器、映射管理等等;

ContextLoaderListener初始化的是 WebApplicationContext, 创建后可以从ServletContext中获取,WebApplicationContext是应用程序内共享的,最多只有一个,如果寻求简单也可以不初始化此容器。与之不同 DispatcherServlet可以有多个,并共享一个WebApplicationContext容器,每一个DispatcherServlet有不同的配置,控制不同的WEB访问。一般将 DAO、Service 层Bean共享的放在ContextLoaderListener配置的容器中,将WEB层的Bean放在特定的DispatcherServlet配置的容器中。

SpringMVC利用Spring的注入特性初始化资源文件,只需要调用setPropertyValues方法就可将contextConfigLocation属性设置到对应实例中,也就是以依赖注入的方式初始化属性。

时序图如下

请求处理流程

官网上的图

涉及到核心类与接口的过程描述:

客户端浏览器发送http请求,被`DispatcherServlet`捕获,调用关键的doDispatch方法,遍历所有注册为`Controller`的bean,为请求寻找关联映射,其中遍历查找的函数getHandler和getHandlerAdapter的源码:


1 /**

 2      * Handle the result of handler selection and handler invocation, which is

 3      * either a ModelAndView or an Exception to be resolved to a ModelAndView.

 4      */

 5     private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,

 6             HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

 7 

 8         boolean errorView = false;

 9 

10         if (exception != null) {

11             if (exception instanceof ModelAndViewDefiningException) {

12                 logger.debug("ModelAndViewDefiningException encountered", exception);

13                 mv = ((ModelAndViewDefiningException) exception).getModelAndView();

14             }

15             else {

16                 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);

17                 mv = processHandlerException(request, response, handler, exception);

18                 errorView = (mv != null);

19             }

20         }

21 

22         // Did the handler return a view to render?

23         if (mv != null && !mv.wasCleared()) {

24             render(mv, request, response);

25             if (errorView) {

26                 WebUtils.clearErrorRequestAttributes(request);

27             }

28         }

29         else {

30             if (logger.isDebugEnabled()) {

31                 logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +

32                         "': assuming HandlerAdapter completed request handling");

33             }

34         }

35 

36         if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

37             // Concurrent handling started during a forward

38             return;

39         }

40 

41         if (mappedHandler != null) {

42             mappedHandler.triggerAfterCompletion(request, response, null);

43         }

44     }

45 

46 

47     /**

48      * Render the given ModelAndView.

49      * <p>This is the last stage in handling a request. It may involve resolving the view by name.

50      * @param mv the ModelAndView to render

51      * @param request current HTTP servlet request

52      * @param response current HTTP servlet response

53      * @throws ServletException if view is missing or cannot be resolved

54      * @throws Exception if there's a problem rendering the view

55      */

56     protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {

57         // Determine locale for request and apply it to the response.

58         Locale locale = this.localeResolver.resolveLocale(request);

59         response.setLocale(locale);

60 

61         View view;

62         if (mv.isReference()) {

63             // We need to resolve the view name.

64             view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);

65             if (view == null) {

66                 throw new ServletException("Could not resolve view with name '" + mv.getViewName() +

67                         "' in servlet with name '" + getServletName() + "'");

68             }

69         }

70         else {

71             // No need to lookup: the ModelAndView object contains the actual View object.

72             view = mv.getView();

73             if (view == null) {

74                 throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +

75                         "View object in servlet with name '" + getServletName() + "'");

76             }

77         }

78 

79         // Delegate to the View object for rendering.

80         if (logger.isDebugEnabled()) {

81             logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");

82         }

83         try {

84             if (mv.getStatus() != null) {

85                 response.setStatus(mv.getStatus().value());

86             }

87             view.render(mv.getModelInternal(), request, response);

88         }

89         catch (Exception ex) {

90             if (logger.isDebugEnabled()) {

91                 logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +

92                         getServletName() + "'", ex);

93             }

94             throw ex;

95         }

96     }

这就是一个完整的处理http请求的过程。盗图一张:

时序图如下



粤ICP备13059215号-2 2013-2014 © Tanyp工作室 Design 版权所有
© 2013-2014 Tanyp DESIGN ALL RIGHTS RESERVED.
<< 线