SpringMVC 坑路2 -> DispatcherServler + Controller

DispatcherServlet 的作用

  DispatcherServlet是前端控制器设计模式的实现,提供 SpringWebMVC 的集中访问点,负责职责的分派,与 SpringIoC 容器可以无缝集成,从而可以获得 Spring 的所有能力。

  DispatcherServlet 主要用作职责调度工作,本身主要用于控制流程,主要职责如下:

1:文件上传解析,如果请求类型是 multipart 将通过 MultipartResolver 进行文件上传解析
2:通过HandlerMapping,将请求映射到处理器(返回一个 HandlerExecutionChain,它包括一个处理器、多个 HandlerInterceptor 拦截器)
3:通过 HandlerAdapter 支持多种类型的处理器(HandlerExecutionChain 中的处理器)
4:通过 ViewResolver 解析逻辑视图名到具体视图实现
5:本地化解析
6:渲染具体的视图
7:如果执行过程中遇到异常将交给 HandlerExceptionResolver 来解析

DispatcherServler 的配置

DispatcherServlet 也可以配置自己的初始化参数,也就是 servlet 配置中可以配置<init-param>

参数 描述
contextClass 实现 WebApplicationContext 接口的类,当前的 servlet 用它来创建上下文。如果这个参数没有指定,默认使用 XmlWebApplicationContext
contextConfigLocation 传给上下文实例(由 contextClass 指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符)来支持多个上下文(在有多个上下文的情况下,如果同一个 bean 被定义两次,后面一个优先)
namespace 命名空间。默认值是 [servlet-name]-servlet

上下文关系

SpringWeb 项目通用上下文配置如下:

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
contextConfigLocation:表示用于加载 Bean 的配置文件路径;
contextClass:表示用于加载 Bean 的 ApplicationContext 实现类,默认 WebApplicationContext

DispatcherServlet 的初始化顺序

1:HttpServletBean 继承 HttpServlet,因此在 Web 容器启动时将调用它的 init 方法
2:FrameworkServlet 继承 HttpServletBean,通过 initServletBean() 进行 Web 上下文初始化
3:DispatcherServlet 继承 FrameworkServlet,并实现了 onRefresh() 方法提供一些前端控制器相关的配置

在 SpringMVC 框架 DispatcherServlet 中的第 470 行左右:

/**
 * This implementation calls {@link #initStrategies}.
 */
@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}

/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

整个 DispatcherServler 初始化的过程具体主要做了两件事情:

  • 初始化 SpringMVC 使用的 Web 上下文,并且可能指定父容器(ContextLoaderListener 加载了根上下文)
  • 初始化 DispatcherServlet 使用的策略,如 HandlerMapping、HandlerAdapter 等

DispatcherServler 的默认配置:

  DispatcherServlet 的默认配置在 DispatcherServlet.properties(和 DispatcherServlet 类在一个包下)中,而且是当 Spring 配置文件中没有指定配置时使用的默认策略;

这里写图片描述
  从配置可以看出 DispatcherServlet 在启动时会自动注册这些特殊的 Bean,无需我们注册,如果我们注册了,默认的将不会注册。

DispatcherServlet 中的特殊 Bean

DispatcherServlet 默认使用 WebApplicationContext 作为上下文,该上下文中有以下的一些 Bean:

Controller

  处理器/页面控制器,做的是 MVC 中的 C 的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

HandlerMapping

  请求到处理器的映射,如果映射成功返回一个 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面处理器)对象、多个 HandlerInterceptor 拦截器);如BeanNameUrlHandlerMapping 将 URL 与 Bean 名字映射,映射成功的 Bean 就是此处的处理器;

HandlerAdapter:

  HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如 SimpleControllerHandlerAdapter 将对实现了 Controller 接口的 Bean 进行适配,并且调用处理器的 handleRequest 方法进行功能处理;

ViewResolver

  ViewResolver 将把逻辑视图名解析为具体的 View,如InternalResourceViewResoulver 将逻辑视图名映射为 jsp 视图;

LocalResolver

  本地化解析,因为 Spring 支持国际化,因此 LocaleResolver 解析客户端的 Locale 信息从而方便进行国际化;

ThemeResolver

  主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

MultipartResolver

  文件上传解析,用于支持文件上传;

HandlerExceptionResolver

  处理器异常解析,可以将异常映射到相应的同意错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

RequestToViewNameTranslator

  当处理器没有返回逻辑视图名等相关信息时,自动将请求 URL 映射为逻辑视图名;

FlashMapManager

  用于管理 FlashMap 的策略接口,FlashMap 用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景。

Controller 简介

  Controller 控制器,是 MVC 中的部分 C,主要负责功能处理部分

1、收集、验证请求参数并绑定到命令对象
2、将命令对象交给业务对象,由业务对象处理并返回模型数据
3、返回 ModelAndView(Model 部分是业务对象返回的模型数据,视图部分为逻辑视图名)

DisaptcherServler + Controller

  DispatcherServlet 负责将请求委托交给 Controller 进行处理,
再根据 Controller 返回的逻辑视图名选择具体的视图进行渲染(并把模型数据传入)

**MVC 中完整的 C(包含逻辑控制和功能处理)由(DispatcherServlet + Controller)组成

Controller注解

  Spring2.5之前,我们都是通过实现 Controller 接口或其实现类来定义我们的处理器类(已不建议使用)。
  Spring2.5 引入注解式处理器支持,通过 @Controller 和 @RequestMapping 注解定义处理器类。并且提供了一组强大的注解:

  • @Controller
  • @RequestMapping
  • @RequestParam
  • @ModelAttribute
  • @SessionAttributes
  • @InitBinder

  Spring3.0 引入了 Restful 架构风格支持(通过 @PathVariable 注解和一些其他的特性支持),且又引入了更多的注解支持

  • @CookieValue
  • @RequestHeader
  • @RequestBody
  • @ResponseStatus
  • @ExceptionHandler
  • @PathVariable

  Spring3.1 使用新的 HandlerMapping 和 HandlerAdapter 来支持 @Controller 和 @RequestMapping 注解处理器,使用处理器映射 RequestMappingHandlerMapping 和处理器适配器 RequestMappingHandlerAdapter 组合来代替 Spring2.5 开始的处理器映射 DefaultAnnotationHandlerMapping 和处理器适配器 AnnotationMethodHandlerAdapter。

注解实现 Controller

HandlerMapping 和 HandlerAdapter 的配置

  • Spring3.1 以前的版本:
    DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter
  • Spring3.1 开始的版本:
    RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter

示例代码:

代码结构参考:
https://blog.csdn.net/qq_33811662/article/details/80658813

修改 spring-mvc.xml 的内容为:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <context:component-scan base-package="mvc1"></context:component-scan>
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

修改 HelloController 的内容为:

package mvc1;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("进入后台控制器");
        ModelAndView mv = new ModelAndView();
        mv.addObject("content", "SpringMVC 初体验");
        mv.setViewName("/WEB-INF/jsp/hello.jsp");
        return mv;
    }
}

运行 Server,进入网址:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_33811662/article/details/80699470