美文网首页
springMvc执行流程

springMvc执行流程

作者: 3517a85fd522 | 来源:发表于2018-12-09 20:43 被阅读0次

springMvc概念
springMvc请求流程
springMvc组件详解
springMvc常用注解
springMvc拦截器
springMvc异常处理


一、springMvc概念

springMvc是基于servlet的web框架,其简化了web程序的开发

二、springMvc请求流程

在阅读时不妨可以带着几个问题阅读:
1.我们通常在浏览器输入的接口怎么由DispatcherServlet调到具体的Handler的(就是我们自己开发的Controller类)
2.编写Controller的形式有哪几种?

springMvc重要组件:
之所以先说这几个组件,是因为只要了解了这几个组件后你便可以对springMvc请求流程有个大致的清晰认识了。(Handler就是我们写的Controller)
      HandlerMapping
      HandlerAdapter
      ViewResolver
      View
      HandlerExceptionResolver
      HandlerInterceptor
DisPatcher作为一个主流程入口,看一下DispatcherServlet结构

DispatcherServlet为了简洁,省去了很多方法跟属性

public class DispatcherServlet extends FrameworkServlet {
//定义了默认策略名字
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
private static final Properties defaultStrategies;
static {
            //从Properties文件中加载默认策略实现
            ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
private List<HandlerMapping> handlerMappings;
private List<HandlerAdapter> handlerAdapters;
private List<HandlerExceptionResolver> handlerExceptionResolvers;
private List<ViewResolver> viewResolvers;
//初始化策略
protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            try {
            ModelAndView mv = null;
            Exception dispatchException = null;
            try {
                                //检查是否文件上传
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);
                //通过HandlerMapping 获取Handler(返回的是HandlerExecutionChain)
               /**public class HandlerExecutionChain {
                       //HandlerExecutionChain封装了Handler(就是我们编写的Controller)跟interceptors
                       private final Object handler;
                       private HandlerInterceptor[] interceptors;
                **/
                HandlerExecutionChain mappedHandler = getHandler(processedRequest);
                //获取的Handler是Object类型,需要通过HandlerAdapter获取Handler真实类型
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                //调用Handlerinterceptor PreHandle(前置拦截器),返回false则停止执行
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // 调用真实handler逻辑并返回ModelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                                //将ModelAndView返回值DispatcherServlet后
                applyDefaultViewName(processedRequest, mv);
                                //调用Handlerinterceptor PostHandle(后置拦截器)    
                    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) {
                                      //调用Handlerinterceptor afterCompletion
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }}

通过上面的DispatcherServlet大概分析可以得知几个组件的作用:
HandlerMapping:
根据请求url地址得到具体Handler(Controller)
HandlerAdapter
根据Handler得到Handler适配器
ViewResolver
试图仓库:根据ViewName得到View
View
具体解析视图
HandlerExceptionResolver
异常捕捕捉器
HandlerInterceptor
拦截器

三、springMvc处理流程图解:(引用他人流程图)

springMvc处理

简略图:


springMvc处理

四、各组件详解:

1.HandlerMapping
HandlerMapping方法:

HandlerMapping方法
HandlerMapping子类:
HandlerMapping

从上图看一看出常用的Mapping有三类:SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping、RequestMappingHandlerMapping。

RequestMappingHandlerMapping就是我们最长使用的方式基于注解@RequestMapping方式的url映射。
SimpleUrlHandlerMapping 基于手动配置 url 与control 映射

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello">helloController</prop>
            </props>
        </property>
    </bean>
    <bean id="helloController" class="com.ckd.controller.HelloController"/>
-----------------------------------------------------------------------------------------------------------------------
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView("index");
        mv.addObject("hello","world");
        return mv;
    }
}

BeanNameUrlHandlerMapping是配置IOC bean时id以"/"开头与Controller的映射

<bean id="/beanname" class="com.ckd.controller.BeanNameController"/>
//需要继承HttpRequestHandler 此时可以把/beanname映射到handleRequest方法上
public class BeanNameControl implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        request.getRequestDispatcher("/WEB-INF/page/userView.jsp").forward(request, response);
    }
}

通过DisPatcherServlet.getHandler()获得Handler的类型时Object,此时无法调用,因此需要HandlerAdapter根据Handler获取具体的适配器
2.HandlerAdapter
springmvc采用适配器的模式适配调用Handler,根据handler不同调用不同的适配器,Handler与HandlerAdapter对用关系如下:

Handler类别 对应适配器 描述
Controller SimpleControllerHandlerAdapter 标准控制器,返回ModelAndView
HttpRequestHandler HttpRequestHandlerAdapter 业务自行处理 请求,不需要通过modelAndView 转到视图
Servlet SimpleServletHandlerAdapter 基于标准的servlet 处理
HandlerMethod RequestMappingHandlerAdapter 基于@requestMapping对应方法处理
image.png
image.png

基于Servlet演示

<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>
<bean id="/helloservlet" class="com.ckd.controller.HelloServlet"/>
----------------------------------------------------------------------------------------------------------------------------
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("hello Servlet");
    }
}

HelloServlet注册IOC容器中时,会由BeanNameUrlHandlerMapping找到对应的Handler,由SimpleServletHandlerAdapter找到对应的适配器,调用业务逻辑Controller,并返回ModelAndView。
3.ViewResolver View
DispatcherServlet#getHandlerAdapter().handle()后返回ModelAndView,
调用resolveViewName() 去viewResolvers试图列表中查找对应的View并返回View.交由View解析生成html并返回

ViewResolver ViewResolver
View
4.HandlerExceptionResolver
该组件用于指示 当出现异常时 mvc 该如何处理。 dispatcherServlet 会调用org.springframework.web.servlet.DispatcherServlet#processHandlerException() 方法,遍历 handlerExceptionResolvers 处理异常,处理完成之后返回errorView 跳转到异常视图。
- [ ] 演示自定义异常捕捉
<bean class="com.ckd.controller.ExceptionHandlerSample"/>
public class ExceptionHandlerSample implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        return new ModelAndView("error");
    }
}
image.png
5.HandlerInterceptor
  • [ ] 演示HandlerInterceptor
<mvc:interceptors>
        <mvc:interceptor>
            <!-- 拦截所有的请求,这个必须写在前面-->
            <mvc:mapping path="/**" />            
            <bean class="com.ckd.controller.SimpleHandlerInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>
-----------------------------------------------------------------------------------------------------------------------------------------
public class SimpleHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

其实现机制是基于 HandlerExecutionChain 分别在 doDispatch 方法中执行以下方法:

  • preHandle :业务处理前执行
  • postHandle:业务处理后(异常则不执行)
  • afterCompletion:视图处理后

具体逻辑源码参见:org.springframework.web.servlet.DispatcherServlet#doDispatch 方法。

相关文章

  • springMVC详解

    图解SpringMVC执行流程: SpringMVC执行流程:1.用户发送请求至前端控制器DispatcherSe...

  • 「面试高频题」SpringMVC执行流程

    SpringMVC执行流程 SpringMVC概述 Spring MVC属于SpringFrameWork的后续产...

  • Spring - MVC执行流程

    SpringMVC执行源代码 SpringMVC执行流程: 用户发送请求至前端控制器DispatcherServl...

  • springMVC

    springMVC 执行流程: [图片上传中。。。(1)] //springmvc重定向 需要ModelMap的对...

  • SpringMVC执行流程

    SpringMVC工作流程描述 1.用户向服务器发送请求,请求被springMVC前端控制器DIspatcherS...

  • SpringMVC执行流程

    SpringMVC工作流程: 1、用户向服务器发送请求,请求被前段控制器DispatcherServlet捕获。 ...

  • SpringMVC执行流程

    图片有些是百度上面找到的,感觉蛮好的,如果侵权了请告诉我首先说明一下,本章节是不会对SpringMVC里面的具体内...

  • SpringMVC执行流程

    1.用户向服务器发送请求,请求被SpringMVC的前端控制器DispatcherServlet捕获 2.利用Di...

  • springMvc执行流程

    springMvc概念springMvc请求流程springMvc组件详解springMvc常用注解springM...

  • springmvc执行流程

    springmvc时序图:

网友评论

      本文标题:springMvc执行流程

      本文链接:https://www.haomeiwen.com/subject/bgqkhqtx.html