一次Request请求在Spring中的实现

一次request看spring的细节处理

spring获取处理一次请求的类的方式有两种

1.从配置文件spring-configs.xml中获取

‌2.从注解中获取

1.1从spring-configs.xml配置来看:

客户端:请求资源URL,web.xml中标签匹配请求资源
如果匹配到就调用对应的中对应的servlet 通过创建servlet对象dispatcherservlet
执行初始化方法通过set方法注入初始化属性值
classpath:spring-configs.xml,通过读取这个配置文件,创建出由spring管理的bean对象handlermapping处理映射,通过property标签实现set注入mapping的值,并将处理的结果以map集合的形式返还给dispatcherservlet,map集合中key为请求URL中/请求资源的名字,value对应业务层自己实现的controller对象,与要创建此对象的bean标签中id或name的属性值对应。dispatcherservlet将请求的URL交给业务层处理
问题:不同对象间获取request域中携带的参数是转发还是包含?
controller对象处理过后返回modelandview对象,交给viewresolver解析,视图解析器做的工作是从mv对象解析出要响应的资源,前缀+名字+后缀组成响应资源的地址,最终呈现给客户端,一次请求结束。
思考:在这一次请求中,request只创建一次且一直在整个请求链中存在并共享数据,直到一次请求结束才销毁request和response对象。
.do是个请求,这个站点在web.xml配置文件中配置了.do的请求都转发给一个servlet来处理,不是个文件,系统遇到这个.do的请求
后就会提交给某个servlet来处理,这个servlet会根据具体的配置转发给某个后台的程序进行数据处理,然后给数据传递到页面,最终给页面展现在
用户面前,不一定是struts的,这个请求是可以自己随便配置的,你可以配置成.html,这样就是经常看到假静态

2.1从注解模式理解spring框架:

@concroller是在告诉spring当前类为业务处理类
@service请求服务
@respontiry持久层
@compoent组件类   

---------------------------------------------------------------------

以下内容摘抄自JAVA API中的源代码:

今天来探索SpringMVC一次请求过程的源码,首先需要找到程序运行的类及主要方法:

我们使用StringMVC首先需要在web.xml中设置一个前端控制器来处理请求,这个前端控制器是:org.springframework.web.servlet.DispatcherServlet

那么我们程序运行的入口就在这里。

一次Request请求在Spring中的实现_第1张图片

从这里可以看出前端控制器是一个Servlet,我们寻找他的service方法,在DispatherServlet中并没有找到service方法,在其父类FrameworkServlet中找到service方法。如下:


FrameworkServlet

[java] 源码:
  1. @Override  
  2. protected void service(HttpServletRequest request, HttpServletResponse response)  
  3.         throws ServletException, IOException {  
  4.   
  5.   
  6.     String method = request.getMethod();  
  7.     if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {  
  8.         // 处理请求  
  9.         processRequest(request, response);  
  10.     }  
  11.     else {  
  12.         super.service(request, response);  
  13.     }  

调用本类的processRequest方法
  1. protected final void processRequest(HttpServletRequest request, HttpServletResponse response)  
  2.         throws ServletException, IOException {
  3.  
  4.     long startTime = System.currentTimeMillis();  
  5.     Throwable failureCause = null;  
  6.   
  7.     LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();  
  8.     LocaleContext localeContext = buildLocaleContext(request);  
  9.   
  10.     RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();  
  11.     ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);  
  12.   
  13.     WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  14.     asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());  
  15.   
  16.     initContextHolders(request, localeContext, requestAttributes);  
  17.   
  18.     try {  
  19.         // 调用doService方法处理请求  
  20.         doService(request, response);  
  21.     }  
  22.     ...  
调用本类的doService方法
  1. @Override  
  2. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  3.     ...  
  4.     try {  
  5.         // 调用doDispatch方法处理请求  
  6.         doDispatch(request, response);  
  7.     }  
  8.     ...
调用 DispatherServlet的doDispatch方法处理请求,主要程序在此方法中进行
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.     HttpServletRequest processedRequest = request;  
  3.     HandlerExecutionChain mappedHandler = null;  
  4.     boolean multipartRequestParsed = false;  
  5.   
  6.     WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  7.   
  8.     try {  
  9.         ModelAndView mv = null;  
  10.         Exception dispatchException = null;  
  11.   
  12.         try {  
  13.             processedRequest = checkMultipart(request);  
  14.             multipartRequestParsed = processedRequest != request;  
  15.   
  16.             // Determine handler for the current request.  
  17.             // 通过processedRequest,决定使用哪个handler来处理请求  
  18.             mappedHandler = getHandler(processedRequest);  
  19.             if (mappedHandler == null || mappedHandler.getHandler() == null) {  
  20.                 noHandlerFound(processedRequest, response);  
  21.                 return;  
  22.             }  
  23.   
  24.             // Determine handler adapter for the current request.  
  25.             // 决定使用那个适配器处理请求(适配器模式)  
  26.             HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  27.   
  28.             // Process last-modified header, if supported by the handler.  
  29.             String method = request.getMethod();  
  30.             boolean isGet = "GET".equals(method);  
  31.             if (isGet || "HEAD".equals(method)) {  
  32.                 long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  
  33.                 if (logger.isDebugEnabled()) {  
  34.                     String requestUri = urlPathHelper.getRequestUri(request);  
  35.                     logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
  36.                 }  
  37.                 if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
  38.                     return;  
  39.                 }  
  40.             }  
  41.   
  42.             // 执行预处理方法  
  43.             if (!mappedHandler.applyPreHandle(processedRequest, response)) {  
  44.                 return;  
  45.             }  
  46.   
  47.             try {  
  48.                 // Actually invoke the handler.  
  49.                 // 使用适配器执行目标方法,返回ModleAndView  
  50.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  51.             }  
  52.             finally {  
  53.                 if (asyncManager.isConcurrentHandlingStarted()) {  
  54.                     return;  
  55.                 }  
  56.             }  
  57.   
  58.             applyDefaultViewName(request, mv);  
  59.             mappedHandler.applyPostHandle(processedRequest, response, mv);  
  60.         }  
  61.         catch (Exception ex) {  
  62.             dispatchException = ex;  
  63.         }  
  64.         // 处理业务逻辑执行以后的返回结果,即处理视图  
  65.         processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  
  66.     }  
  67.     catch (Exception ex) {  
  68.         triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  
  69.     }  
  70.     catch (Error err) {  
  71.         triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);  
  72.     }  
  73.     finally {  
  74.         if (asyncManager.isConcurrentHandlingStarted()) {  
  75.             // Instead of postHandle and afterCompletion  
  76.             mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);  
  77.             return;  
  78.         }  
  79.         // Clean up any resources used by a multipart request.  
  80.         if (multipartRequestParsed) {  
  81.             cleanupMultipart(processedRequest);  
  82.         }  
  83.     }  


到这里我们可以看出这个前端控制器主要工作是在 DispatherServletdoDispatch方法中完成。

大致流程如下:


通过processedRequest,决定使用哪个handler来处理请求

  1. HandlerExecutionChain mappedHandler = null;  
  2. // Determine handler for the current request.  
  3. mappedHandler = getHandler(processedRequest);  

决定使用那个适配器处理请求(适配器模式)
  1. // Determine handler adapter for the current request.  
  2. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  

执行预处理方法
  1. if (!mappedHandler.applyPreHandle(processedRequest, response)) {  
  2.     return;  


使用适配器执行目标方法,返回ModleAndView
  1. // Actually invoke the handler.  
  2. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 
执行目标后处理方法
  1. mappedHandler.applyPostHandle(processedRequest, response, mv); 

处理业务逻辑执行以后的返回结果,即处理视图,

调用本类的processDispatchResult方法

  1. private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,  
  2.         HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {  
  3.     ...  
  4.     // Did the handler return a view to render?  
  5.     if (mv != null && !mv.wasCleared()) {  
  6.         render(mv, request, response);//渲染视图  
  7.         if (errorView) {  
  8.             WebUtils.clearErrorRequestAttributes(request);  
  9.         }  
  10.     }     
  11.     ..  

调用本类的render(mv, request, response);渲染视图。是将方法的返回值,最终变为一个View对象。
这个View对象正是我们在xml中配置的InternalResourceView
  1. protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.     ..  
  3.     // Determine locale for request and apply it to the response.  
  4.     Locale locale = this.localeResolver.resolveLocale(request);  
  5.     response.setLocale(locale);  
  6.   
  7.     // View对象  
  8.     View view;  
  9.     if (mv.isReference()) {  
  10.         // We need to resolve the view name.  
  11.         view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);  
  12.         if (view == null) {  
  13.             throw new ServletException(  
  14.                     "Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +  
  15.                             getServletName() + "'");  
  16.         }  
  17.     }  
  18.     else {  
  19.         // No need to lookup: the ModelAndView object contains the actual View object.  
  20.         // 获得真正的view对象  
  21.         view = mv.getView();  
  22.         if (view == null) {  
  23.             throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +  
  24.                     "View object in servlet with name '" + getServletName() + "'");  
  25.         }  
  26.     }  
  27.     // Delegate to the View object for rendering.  
  28.     if (logger.isDebugEnabled()) {  
  29.         logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");  
  30.     }  
  31.     try {  
  32.         // 内部视图解析器继续解析视图:  
  33.         view.render(mv.getModelInternal(), request, response);  
  34.     }  
  35.     catch (Exception ex) {  
  36.         if (logger.isDebugEnabled()) {  
  37.             logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '"  
  38.                     + getServletName() + "'", ex);  
  39.         }  
  40.         throw ex;  
  41.     }  


调用 AbstractView类中的render方法
  1. @Override  
  2. public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  3.     if (logger.isTraceEnabled()) {  
  4.         logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +  
  5.             " and static attributes " + this.staticAttributes);  
  6.     }  
  7.   
  8.   
  9.     Map mergedModel = createMergedOutputModel(model, request, response);  
  10.   
  11.   
  12.     prepareResponse(request, response);  
  13.     // 渲染模型  
  14.     renderMergedOutputModel(mergedModel, request, response);  
  15. }    

调用 InternalResourceView类中的renderMergedOutputModel方法进行渲染模型、转发操作:
  1. //拿到转发器,进行转发  
  2. @Override  
  3. protected void renderMergedOutputModel(  
  4.         Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  5.   
  6.     // Determine which request handle to expose to the RequestDispatcher.  
  7.     HttpServletRequest requestToExpose = getRequestToExpose(request);  
  8.   
  9.     // Expose the model object as request attributes.  
  10.     exposeModelAsRequestAttributes(model, requestToExpose);  
  11.   
  12.     // Expose helpers as request attributes, if any.  
  13.     exposeHelpers(requestToExpose);  
  14.   
  15.     // Determine the path for the request dispatcher.  
  16.     String dispatcherPath = prepareForRendering(requestToExpose, response);  
  17.       
  18.     //获得转发器  
  19.     // Obtain a RequestDispatcher for the target resource (typically a JSP).  
  20.     RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);  
  21.     if (rd == null) {  
  22.         throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +  
  23.                 "]: Check that the corresponding file exists within your web application archive!");  
  24.     }  
  25.   
  26.     // If already included or response already committed, perform include, else forward.  
  27.     if (useInclude(requestToExpose, response)) {  
  28.         response.setContentType(getContentType());  
  29.         if (logger.isDebugEnabled()) {  
  30.             logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");  
  31.         }  
  32.         rd.include(requestToExpose, response);  
  33.     }  
  34.   
  35.     else {  
  36.         // Note: The forwarded resource is supposed to determine the content type itself.  
  37.         if (logger.isDebugEnabled()) {  
  38.             logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");  
  39.         }  
  40.         //进行转发  
  41.         rd.forward(requestToExpose, response);  
  42.     }

以下内容摘抄自want_water_fish的博客 :

一个请求在spring中的流程  (参与处理的类及主要方法)

DispatcherServlet.doDispatch (请求第一次处理、所有的请求都会执行这个方法。在这个方法中请求会被解析、分发。)-->
WebAsyncUtils.getAsyncManager (request中创建一个属性WebAsyncManager)-->
DispatcherServlet.checkMultipart (request是否是多文件类的请求)-->
DispatcherServlet.getHandler (获得当前requst的处理handler–spring提供了两个RequestMappingHandlerMapping、BeanNameUrlHandlerMapping)-->
AbstractHandlerMapping.getHandler (获得当前requst的处理handler)-->
AbstractHandlerMapping.getHandlerExecutionChain-->
UrlPathHelper.getLookupPathForRequest-->
DispatcherServlet.getHandlerAdapter (获得当前requst的处理handlerAdapter–spring提供了两个RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter)-->
HandlerExecutionChain.applyPreHandle (处理拦截器)-->
AbstractHandlerMethodAdapter.handle (开始处理该请求)-->
RequestMappingHandlerAdapter.handleInternal (跳转至方法)-->
WebContentGenerator.checkRequest (检查方法是否支持、是否有session)-->
RequestMappingHandlerAdapter.invokeHandlerMethod (准备调用具体的执行方法)-->
RequestMappingHandlerAdapter.getDataBinderFactory (获得DataBinderFactory)-->
RequestMappingHandlerAdapter.createDataBinderFactory (创建DataBinderFactory)-->
RequestMappingHandlerAdapter.getModelFactory (获得ModelFactory)-->
ModelFactory.ModelFactory (创建ModelFactory)-->
RequestMappingHandlerAdapter.createInvocableHandlerMethod (创建ServletInvocableHandlerMethod)-->
ModelFactory.initModel (按照参数、初始化ModelFactory)-->
ModelFactory.invokeModelAttributeMethods (调用@ModelAttribute修饰的方法)-->
InvocableHandlerMethod.invokeForRequest (具体的调用执行方法)-->
InvocableHandlerMethod.getMethodArgumentValues (获取方法参数值)-->
HandlerMethodArgumentResolverComposite.resolveArgument (获得参数)-->
RequestResponseBodyMethodProcessor.resolveArgument (获得参数)-->
RequestResponseBodyMethodProcessor.readWithMessageConverters (将request中的参数转化成对象)-->
AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters (将request中的参数转化成对象)-->
AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters (将request中的参数转化成json对象、该系统用的是json数据传输)-->
ServletInvocableHandlerMethod.invokeAndHandle (调用真正的方法)-->
InvocableHandlerMethod.invokeForRequest (执行)-->
InvocableHandlerMethod.doInvoke (执行)-->
-->
自己controller中的方法
-->
InvocableHandlerMethod.doInvoke (执行返回)-->
InvocableHandlerMethod.invokeForRequest (执行返回)-->
ServletInvocableHandlerMethod.invokeAndHandle (执行返回)-->
HandlerMethodReturnValueHandlerComposite.handleReturnValue (处理方法返回的参数)-->
RequestResponseBodyMethodProcessor.handleReturnValue (处理方法返回的参数)-->
AbstractMessageConverterMethodProcessor.writeWithMessageConverters (处理方法返回的参数)-->
RequestMappingHandlerAdapter.invokeHandlerMethod (执行返回)-->
RequestMappingHandlerAdapter.getModelAndView (获得ModelAndView)-->
RequestMappingHandlerAdapter.handleInternal (执行返回)-->
AbstractHandlerMethodAdapter.handle (执行返回)-->
DispatcherServlet.doDispatch (执行返回)-->

你可能感兴趣的:(Spring的框架理解)