好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Java spring mvc请求详情介绍

前言:

本文源码基于 spring-framework-5.3.10 。 mvc 是 spring 源码中的一个子模块!

一、源码执行流程

用户发送请求至前端控制器DispatcherServlet。 DispatcherServlet 收到请求调用处理器映射器 HandlerMapping 。处理器映射器根据请求url找到具体的处理器,生成处理器执行链 HandlerExecutionChain (包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。 DispatcherServlet 根据处理器Handler获取处理器适配器 HandlerAdapter ,执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作 执行处理器Handler(Controller,也叫页面控制器)。Handler执行完成返回 ModelAndView 、 HandlerAdapter 将Handler执行结果ModelAndView返回到DispatcherServlet。 DispatcherServlet 将 ModelAndView 传给ViewReslover视图解析器。ViewReslover解析后返回具体View DispatcherServlet 对View进行渲染视图(即将模型数据model填充至视图中)。 DispatcherServlet响应用户。

二、源码执行流程图

三、spring mvc中的一核心组件

DispatcherServlet : 前端调度器 , 负责将请求拦截下来分发到各控制器方法中 HandlerMapping : 负责根据请求的URL和配置@RequestMapping映射去匹配, 匹配到会返回Handler(具体控制器的方法) HandlerAdaper : 负责调用Handler-具体的方法- 返回视图的名字 Handler将它封装到ModelAndView(封装视图名,request域的数据) ViewReslover : 根据ModelAndView里面的视图名地址去找到具体的jsp封装在View对象中 View :进行视图渲染(将jsp转换成html内容 --这是Servlet容器的事情了) 最终response到的客户端

四、源码分析

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

/**

  * 最核心的控制器

  * 源码位置:org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

  */

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

     HttpServletRequest processedRequest = request;

     HandlerExecutionChain mappedHandler = null ;

     boolean multipartRequestParsed = false ;

 

     WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

 

     try {

         ModelAndView mv = null ;

         Exception dispatchException = null ;

 

         try {

             // 验证是不是上传的请求,上传的请求会转化为MultipartHttpServletRequest

             processedRequest = checkMultipart(request);

             multipartRequestParsed = (processedRequest != request);

 

             // 进行映射

             mappedHandler = getHandler(processedRequest);

             if (mappedHandler == null ) {

                 noHandlerFound(processedRequest, response);

                 return ;

             }

 

             // 找到最合适的HandlerAdapter,按照顺序,那个先解析到就是那个

             HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

 

             // Process last-modified header, if supported by the handler.  HTTP缓存相关

             String method = request.getMethod();

             boolean isGet = HttpMethod.GET.matches(method);

             if (isGet || HttpMethod.HEAD.matches(method)) {

                 long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

                 if ( new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

                     return ;

                 }

             }

             // 前置拦截器

             if (!mappedHandler.applyPreHandle(processedRequest, response)) {

                 // 返回false就不进行后续处理了

                 return ;

             }

 

             // Actually invoke the handler.

             // 获取参数,执行方法

             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

 

             if (asyncManager.isConcurrentHandlingStarted()) {

                 return ;

             }

             // 如果mv有  视图没有,给你设置默认视图

             applyDefaultViewName(processedRequest, mv);

             //后置拦截器

             mappedHandler.applyPostHandle(processedRequest, response, mv);

         }

         catch (Exception ex) {

             dispatchException = ex;

         }

         catch (Throwable err) {

             // As of 4.3, we're processing Errors thrown from handler methods as well,

             // making them available for @ExceptionHandler methods and other scenarios.

             dispatchException = new NestedServletException( "Handler dispatch failed" , err);

         }

         // 渲染视图

         processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

     }

     catch (Exception ex) {

         triggerAfterCompletion(processedRequest, response, mappedHandler, ex);

     }

     catch (Throwable err) {

         triggerAfterCompletion(processedRequest, response, mappedHandler,

                 new NestedServletException( "Handler processing failed" , err));

     }

     finally {

         if (asyncManager.isConcurrentHandlingStarted()) {

             // Instead of postHandle and afterCompletion

             if (mappedHandler != null ) {

                 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

             }

         }

         else {

             // Clean up any resources used by a multipart request.

             if (multipartRequestParsed) {

                 cleanupMultipart(processedRequest);

             }

         }

     }

}

五、获取组件相关逻辑:

原理: 谁先解析到就用谁!

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

/**

  * 获取处理器映射器

  * 源码位置:org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest)

  */

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

     if ( this .handlerMappings != null ) {

         /** 拿到所有handlerMappings (容器启动阶段初始化:拿到所有实现了HandlerMapping的Bean)

          * @see DispatcherServlet#initHandlerMappings

          * 测试发现: 不同的HandlerMapping可以有相同path, 谁先解析到就用哪个

          * */

         for (HandlerMapping mapping : this .handlerMappings) {

             HandlerExecutionChain handler = mapping.getHandler(request);

             if (handler != null ) {

                 return handler;

             }

         }

     }

     return null ;

}

 

/**

  * 获取处理器适配器

  * 源码位置:org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(Object)

  */

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

     if ( this .handlerAdapters != null ) {

         // 按照配置的顺序,谁先解析到就用那个

         for (HandlerAdapter adapter : this .handlerAdapters) {

             if (adapter.supports(handler)) {

                 return adapter;

             }

         }

     }

     throw new ServletException( "No adapter for handler [" + handler +

             "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler" );

}

六、获取参数,执行方法源码分析

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

/**

  * 获取参数,执行方法最外层的调用

  * 源码位置:org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(HttpServletRequest, HttpServletResponse, Object)

  */

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)

         throws Exception {

     // 直接调用这个方法

     return handleInternal(request, response, (HandlerMethod) handler);

}

 

/**

  * 获取参数,执行方法内部的调用逻辑

  * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(HttpServletRequest, HttpServletResponse, HandlerMethod)

  */

protected ModelAndView handleInternal(HttpServletRequest request,

         HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

 

     ModelAndView mav;

     // 检查当前请求的method是否为支持的method(默认Null,可通过继承AbstractController设置supportedMethods)

     // 检查当前请求是否必须session  (默认false,可通过继承AbstractController设置requireSession)

     checkRequest(request);

 

     /**

      * 判断当前是否需要支持在同一个session中只能线性地处理请求:一个session同时只能处理一个线程

      * 因为锁是通过 synchronized 是 JVM 进程级,所以在分布式环境下,

      * 无法达到同步相同 Session 的功能。默认情况下,synchronizeOnSession 为 false

      */

     if ( this .synchronizeOnSession) {

         // 获取当前请求的session对象

         HttpSession session = request.getSession( false );

         if (session != null ) {

             // 为当前session生成一个唯一的可以用于锁定的key

             Object mutex = WebUtils.getSessionMutex(session);

             synchronized (mutex) {

                 // 对HandlerMethod进行参数等的适配处理,并调用目标handler

                 mav = invokeHandlerMethod(request, response, handlerMethod);

             }

         }

         else {

             // 如果当前不存在session,则直接对HandlerMethod进行适配

             mav = invokeHandlerMethod(request, response, handlerMethod);

         }

     }

     else {

         // *如果当前不需要对session进行同步处理,则直接对HandlerMethod进行适配

         mav = invokeHandlerMethod(request, response, handlerMethod);

     }

 

 

     //判断当前请求头中是否包含Cache-Control请求头,如果不包含,则对当前response进行处理

     if (!response.containsHeader(HEADER_CACHE_CONTROL)) {

         // 如果当前SessionAttribute中存在配置的attributes,则为其设置过期时间。

         // 这里SessionAttribute主要是通过@SessionAttribute注解生成的

         if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {

             applyCacheSeconds(response, this .cacheSecondsForSessionAttributeHandlers);

         }

         else {

             // 如果当前不存在SessionAttributes,则判断当前是否存在Cache-Control设置,

             // 如果存在,则按照该设置进行response处理,如果不存在,则设置response中的

             // Cache的过期时间为-1,即立即失效

             prepareResponse(response);

         }

     }

 

     return mav;

}

 

/**

  * 获取参数,执行方法前的准备逻辑

  * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest, HttpServletResponse, HandlerMethod)

  */

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,

         HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

     // 把我们的请求req resp包装成 ServletWebRequest

     ServletWebRequest webRequest = new ServletWebRequest(request, response);

     try {

         // 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中

         // 配置的InitBinder,用于进行参数的绑定

         WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

 

         // 获取容器中全局配置的ModelAttribute和当前HandlerMethod所对应的Controller 中配置的ModelAttribute,

         // 这些配置的方法将会在目标方法调用之前进行调用

         ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

 

         // 封装handlerMethod,会在调用前解析参数、调用后对返回值进行处理

         ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);

         if ( this .argumentResolvers != null ) {

             // 让invocableMethod拥有参数解析能力

             invocableMethod.setHandlerMethodArgumentResolvers( this .argumentResolvers);

         }

         if ( this .returnValueHandlers != null ) {

             // 让invocableMethod拥有返回值处理能力

             invocableMethod.setHandlerMethodReturnValueHandlers( this .returnValueHandlers);

         }

         // 让invocableMethod拥有InitBinder解析能力

         invocableMethod.setDataBinderFactory(binderFactory);

         // 设置ParameterNameDiscoverer,该对象将按照一定的规则获取当前参数的名称

         invocableMethod.setParameterNameDiscoverer( this .parameterNameDiscoverer);

         // ModelAndView处理容器

         ModelAndViewContainer mavContainer = new ModelAndViewContainer();

         // 将request的Attribute复制一份到ModelMap

         mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

         // *调用我们标注了@ModelAttribute的方法,主要是为我们的目标方法预加载

         modelFactory.initModel(webRequest, mavContainer, invocableMethod);

         // 重定向的时候,忽略model中的数据 默认false

         mavContainer.setIgnoreDefaultModelOnRedirect( this .ignoreDefaultModelOnRedirect);

 

         // 获取当前的AsyncWebRequest,这里AsyncWebRequest的主要作用是用于判断目标

         // handler的返回值是否为WebAsyncTask或DeferredResult,如果是这两种中的一种,

         // 则说明当前请求的处理应该是异步的。所谓的异步,指的是当前请求会将Controller中

         // 封装的业务逻辑放到一个线程池中进行调用,待该调用有返回结果之后再返回到response中。

         // 这种处理的优点在于用于请求分发的线程能够解放出来,从而处理更多的请求,提高吞吐。

         // 只有待目标任务完成之后才会回来将该异步任务的结果返回。

         AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);

         asyncWebRequest.setTimeout( this .asyncRequestTimeout);

         // 封装异步任务的线程池、request、interceptors到WebAsyncManager中

         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

         asyncManager.setTaskExecutor( this .taskExecutor);

         asyncManager.setAsyncWebRequest(asyncWebRequest);

         asyncManager.registerCallableInterceptors( this .callableInterceptors);

         asyncManager.registerDeferredResultInterceptors( this .deferredResultInterceptors);

 

         // 这里就是用于判断当前请求是否有异步任务结果的,如果存在,则对异步任务结果进行封装

         if (asyncManager.hasConcurrentResult()) {

             Object result = asyncManager.getConcurrentResult();

             mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[ 0 ];

             asyncManager.clearConcurrentResult();

             LogFormatUtils.traceDebug(logger, traceOn -> {

                 String formatted = LogFormatUtils.formatValue(result, !traceOn);

                 return "Resume with async result [" + formatted + "]" ;

             });

             invocableMethod = invocableMethod.wrapConcurrentResult(result);

         }

         // *对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象

         invocableMethod.invokeAndHandle(webRequest, mavContainer);

         if (asyncManager.isConcurrentHandlingStarted()) {

             return null ;

         }

 

         // 对封装的ModelAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向,

         // 还会判断是否需要将FlashAttributes封装到新的请求中

         return getModelAndView(mavContainer, modelFactory, webRequest);

     }

     finally {

         webRequest.requestCompleted();

     }

}

 

/**

  * 获取参数,执行方法

  * 源码位置:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest, ModelAndViewContainer, Object...)

  */

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,

         Object... providedArgs) throws Exception {

 

     /*真正的调用我们的目标对象 很重要 很重要*/

     Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

     // 设置相关的返回状态

     setResponseStatus(webRequest);

     // 如果请求处理完成,则设置requestHandled属性

     if (returnValue == null ) {

         if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {

             disableContentCachingIfNecessary(webRequest);

             mavContainer.setRequestHandled( true );

             return ;

         }

     }

     // 如果请求失败,但是有错误原因,那么也会设置requestHandled属性

     else if (StringUtils.hasText(getResponseStatusReason())) {

         mavContainer.setRequestHandled( true );

         return ;

     }

 

     mavContainer.setRequestHandled( false );

     Assert.state( this .returnValueHandlers != null , "No return value handlers" );

     try {

         // 遍历当前容器中所有ReturnValueHandler,判断哪种handler支持当前返回值的处理,

         // 如果支持,则使用该handler处理该返回值

         this .returnValueHandlers.handleReturnValue(

                 returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

     }

     catch (Exception ex) {

         if (logger.isTraceEnabled()) {

             logger.trace(formatErrorForReturnValue(returnValue), ex);

         }

         throw ex;

     }

}

七、渲染视图逻辑

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

/**

  * 渲染视图逻辑

  * 源码位置:org.springframework.web.servlet.DispatcherServlet.processDispatchResult(HttpServletRequest, HttpServletResponse, HandlerExecutionChain, ModelAndView, Exception)

  */

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,

         @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,

         @Nullable 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 (errorView) {

             WebUtils.clearErrorRequestAttributes(request);

         }

     }

     else {

         if (logger.isTraceEnabled()) {

             logger.trace( "No view rendering, null ModelAndView returned." );

         }

     }

 

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

         // Concurrent handling started during a forward

         return ;

     }

 

     if (mappedHandler != null ) {

         // Exception (if any) is already handled..   拦截器:AfterCompletion

         mappedHandler.triggerAfterCompletion(request, response, null );

     }

}

到此这篇关于Java spring mvc请求详情介绍的文章就介绍到这了,更多相关spring mvc请求内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://HdhCmsTestcnblogs测试数据/zfcq/p/15995324.html

查看更多关于Java spring mvc请求详情介绍的详细内容...

  阅读:15次