SpringMVC系列之主要组件

来源:互联网 发布:电脑截图软件下载 编辑:程序博客网 时间:2024/06/03 21:36

一、组件说明

  1. DispatcherServlet:前端控制器,用于请求到达前端控制器,由它调用其他组件处理用户的请求。
  2. HandlerMapping:处理器映射器,负责根据用户请求找到Handler(处理器),springmvc提供了不同的映射器实现方式。
  3. Handler:处理器,对具体的用户请求进行处理。
  4. HandlerAdapter:处理器适配器,通过HandlerAdapter对处理器进行执行。
  5. View Resolver:视图解析器,负责将处理结果生成view视图。View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。

二、前端控制器

  DispatcherServlet是springmvc的中央调度器,DispatcherServlet创建时会默认从DispatcherServlet.properties文件加载springmvc所用的各种组件。

  

   

二、处理器映射器

  处理器映射器负责根据request请求找到对应的Handler处理器以及Interceptor拦截器,将它们封装在HandlerExecutionChain对象中返回给前端控制器。

  下面是两种常用的处理器映射器:

  1、BeanNameURLHandlerMapping:根据请求的url与spring容器中定义的bean的name进行匹配,从而从spring容器中找到bean实例。

  

  2、simpleURLHandlerMapping:它可以将url和处理器bean的id进行统一映射配置。

  

三、处理器适配器

  HandlerAdapter会根据适配器接口对Handler进行包装适配,包装后即可对处理器进行执行(使用了适配器模式)。

  下面是两种常用的处理器适配器:

  1、SimpleControllerHandlerAdapter:简单控制器处理器适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的bean通过此适配器进行适配执行。

  

  2、HttpRequestHandlerAdapter:http请求处理器适配器,所有实现了org.springframework.web.HttpRequestHandler接口的bean通过此适配器进行适配执行。

  

  注:处理器实现HttpRequestHandler接口,实现handleRequest方法,该方法没有返回、ModelAndView,可以通过response修改定义响应内容,比如返回json数据。

  

四、注解处理器映射器和适配器

  

  可以使用组件扫描,而省去在spring容器中配置每个controller类。配置如下:

    <context:component-scan base-package="com.demo.ssm.controller"></context:component-scan>

  1、注解处理器映射器,对类中标记的@RequestMapping的方法进行映射,根据RequestMapping定义的url匹配RequestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。

<!-- 注解映射器 -->    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

  2、注解处理器适配器,对标记的@RequestMapping的方法进行适配。

<!-- 注解适配器 -->    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

  注:还可以使用下面的配置代替上面处理器映射器和适配器的配置:

   <mvc:annotation-driven></mvc:annotation-driven>

五、总结

  springmvc处理流程:

  1、用户发送请求到DispatchServlet前端控制器。

  2、DispatchServlet调用HandlerMapping处理器映射器根据url查找Handler。

/**     * Return the HandlerExecutionChain for this request.     * <p>Tries all handler mappings in order.     * @param request current HTTP request     * @return the HandlerExecutionChain, or {@code null} if no handler could be found     */    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;    }
View Code

  3、DispatchServlet调用HandlerAdapter处理器适配器对HandlerMapping找到的Handler进行包装。

/**     * Return the HandlerAdapter for this handler object.     * @param handler the handler object to find an adapter for     * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.     */    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {        for (HandlerAdapter ha : this.handlerAdapters) {            if (logger.isTraceEnabled()) {                logger.trace("Testing handler adapter [" + ha + "]");            }            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");    }
View Code

  4、执行Handler,并返回一个ModelAndView。

/**     * Determine an error ModelAndView via the registered HandlerExceptionResolvers.     * @param request current HTTP request     * @param response current HTTP response     * @param handler the executed handler, or {@code null} if none chosen at the time of the exception     * (for example, if multipart resolution failed)     * @param ex the exception that got thrown during handler execution     * @return a corresponding ModelAndView to forward to     * @throws Exception if no error ModelAndView found     */    protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,            Object handler, Exception ex) throws Exception {        // Check registered HandlerExceptionResolvers...        ModelAndView exMv = null;        for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {            exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);            if (exMv != null) {                break;            }        }        if (exMv != null) {            if (exMv.isEmpty()) {                request.setAttribute(EXCEPTION_ATTRIBUTE, ex);                return null;            }            // We might still need view name translation for a plain error model...            if (!exMv.hasView()) {                exMv.setViewName(getDefaultViewName(request));            }            if (logger.isDebugEnabled()) {                logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);            }            WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());            return exMv;        }        throw ex;    }
View Code

  5、DispatchServlet调用ViewResolver视图解析器进行视图解析,解析完成后返回一个View,再进行视图渲染并展示。

/**     * Render the given ModelAndView.     * <p>This is the last stage in handling a request. It may involve resolving the view by name.     * @param mv the ModelAndView to render     * @param request current HTTP servlet request     * @param response current HTTP servlet response     * @throws ServletException if view is missing or cannot be resolved     * @throws Exception if there's a problem rendering the view     */    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {        // Determine locale for request and apply it to the response.        Locale locale = this.localeResolver.resolveLocale(request);        response.setLocale(locale);        View view;        if (mv.isReference()) {            // We need to resolve the view name.            view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);            if (view == null) {                throw new ServletException("Could not resolve view with name '" + mv.getViewName() +                        "' in servlet with name '" + getServletName() + "'");            }        }        else {            // No need to lookup: the ModelAndView object contains the actual View object.            view = mv.getView();            if (view == null) {                throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +                        "View object in servlet with name '" + getServletName() + "'");            }        }        // Delegate to the View object for rendering.        if (logger.isDebugEnabled()) {            logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");        }        try {            view.render(mv.getModelInternal(), request, response);        }        catch (Exception ex) {            if (logger.isDebugEnabled()) {                logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +                        getServletName() + "'", ex);            }            throw ex;        }    }
0 0
原创粉丝点击