Spring MVC 核心 DispatcherServlet

九大组件

SpringMVC 中所有请求都会由 DispatcherServlet 处理和响应。DispatcherServlet 这个类中九个重要的属性,每个属性有不同的作用,如下:

/** 文件上传解析器 */
@Nullable
private MultipartResolver multipartResolver;

/** 国际化解析器(根据 accept-language 来判断,比如 zh-CN 就是中国,基本用不着) */
@Nullable
private LocaleResolver localeResolver;

/** 主题解析器(官方都标注为弃用了,因为前后分离,现在都是前端来控制主题切换了) */
@Deprecated
@Nullable
private ThemeResolver themeResolver;

/** 处理器映射器 */
@Nullable
private List<HandlerMapping> handlerMappings;

/** 处理器适配器 */
@Nullable
private List<HandlerAdapter> handlerAdapters;

/** 异常解析器 */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;

/** 请求自动转视图名翻译器(handler 有时候不返回具体的视图名称,比如返回一个 null,可以通过 RequestToViewNameTranslator 来讲这种 url 映射到某个具体的视图) */
@Nullable
private RequestToViewNameTranslator viewNameTranslator;

/** 闪存管理器(临时存放数据,一个页面携带一些数据跳转到另一个页面,因为前后分离,也基本不用了) */
@Nullable
private FlashMapManager flashMapManager;

/** 视图解析器(根据视图名确定出具体的视图,比如 handler 返回 /home 最终响应给浏览器的是 /WEB-INF/views/home.jsp) */
@Nullable
private List<ViewResolver> viewResolvers;

MultipartResolver:文件上传解析器。作用是处理文件上传

HandlerMapping:处理器映射器。作用是根据 url 确定出 handler

HandlerAdapter:处理器适配器。作用是执行 handler,并把结果返回给 DispatcherServlet

HandlerExceptionResolver:异常解析器。

文件解析器 MultipartResolver

MultipartResolver 是 Spring 框架中的一个接口,主要用于处理文件上传功能。在 Web 应用中,MultipartResolver 用来解析客户端发送的多部分(multipart)请求,这些请求通常包括文件内容和表单数据。

主要功能:

  1. 解析文件上传请求:处理 HTTP 请求中的文件部分,通常是通过表单上传的文件(如图片、文档等)。它支持的请求内容类型是 multipart/form-data
  2. 封装文件数据:通过 MultipartResolver 解析后的请求,可以从中提取文件数据,并将其存放在 MultipartFile 对象中。MultipartFile 是 Spring 提供的接口,用于表示上传的文件。
  3. 支持大文件上传:Spring 提供的 MultipartResolver 可以配置最大文件大小、总上传数据大小等限制,帮助开发者管理文件上传的规模。

工作流程:

  1. 当一个客户端发起文件上传请求时,服务器接收到的请求会被标记为 multipart/form-data 类型。
  2. MultipartResolver 会解析请求,将文件数据提取到 MultipartFile 中,并将它们和其他表单数据一起封装在 MultipartHttpServletRequest 对象中。
  3. 在控制器中,开发者可以通过 @RequestParam 获取上传的文件,或直接通过 MultipartHttpServletRequest 来处理文件上传。

常见实现:

  • CommonsMultipartResolver:基于 Apache Commons FileUpload 的实现。
  • StandardServletMultipartResolver:基于 Servlet 3.0 的 multipart/form-data 规范,通常用于 Servlet 3.0 及以上版本的容器。

示例代码:

@Controller
public class FileUploadController {

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        if (!file.isEmpty()) {
            try {
                // 获取文件名
                String fileName = file.getOriginalFilename();
                // 保存文件
                file.transferTo(new File("upload/" + fileName));
                return "File uploaded successfully!";
            } catch (IOException e) {
                e.printStackTrace();
                return "Failed to upload file!";
            }
        } else {
            return "No file selected!";
        }
    }
}

配置:

在 Spring 配置文件(例如 XML 配置)中,你可以通过定义一个 MultipartResolver 的 bean 来启用文件上传功能:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760" /> <!-- 限制最大上传文件为 10MB -->
</bean>

处理器映射器 HandlerMapping

HandlerMapping 是 Spring 框架中的一个接口,负责将 HTTP 请求 映射到相应的 处理器(Handler) 上,通常是控制器(Controller)中的方法。它是 Spring MVC 请求处理流程中的关键部分,确保请求能够正确地传递到适当的处理方法。

主要功能:

HandlerMapping 的主要作用是根据请求的 URL 或其他请求信息,找到合适的处理器(handler)。通常,处理器是一个控制器方法,它将会根据请求类型(如 GETPOST 等)来处理请求,并返回相应的结果。

工作流程:

  1. 客户端请求:当一个客户端发起 HTTP 请求时,请求会被传递到 Spring MVC 的前端控制器 DispatcherServlet
  2. HandlerMapping 查找处理器DispatcherServlet 使用一个或多个 HandlerMapping 实现来查找合适的处理器(通常是某个 Controller 的方法)。
  3. 请求分发HandlerMapping 根据请求的 URL 或其他信息选择一个处理器,并将请求转发给该处理器。
  4. 执行处理器:找到合适的处理器后,Spring 会调用该处理器处理请求,并返回相应的结果。

常见的 HandlerMapping 实现:

Spring 提供了多种 HandlerMapping 的实现方式,根据不同的映射策略来选择合适的处理器:

  1. RequestMappingHandlerMapping:这是 Spring MVC 中最常用的 HandlerMapping 实现。它基于注解 @RequestMapping(以及 @GetMapping@PostMapping 等注解)来映射 URL 和处理方法。

    例如,@RequestMapping("/hello") 会将 URL /hello 映射到标注了该注解的方法上。

  2. SimpleUrlHandlerMapping:这种实现基于简单的 URL 到处理器的映射关系,它将 URL 与处理器对象的关系配置在 XML 文件或其他配置文件中。

  3. BeanNameUrlHandlerMapping:这个实现根据 Bean 的名称来映射 URL。Spring 会根据 Bean 名称将请求映射到特定的 Bean。

  4. AbstractHandlerMapping:这是 HandlerMapping 的抽象类,RequestMappingHandlerMapping 和其他具体实现类都继承自该类。

示例代码:

  1. 基于注解的 RequestMappingHandlerMapping
@Controller
public class MyController {

    @RequestMapping("/hello")
    public String sayHello() {
        return "Hello, Spring!";
    }
}

在上面的例子中,RequestMappingHandlerMapping 会通过 URL /hello 将请求映射到 sayHello() 方法。

  1. 使用 SimpleUrlHandlerMapping
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="urlMap">
        <map>
            <entry key="/hello" value-ref="helloController" />
        </map>
    </property>
</bean>

<bean id="helloController" class="com.example.HelloController" />

在这个配置中,SimpleUrlHandlerMapping 会将请求 URL /hello 映射到 helloController 这个 Bean。

配置:

你可以通过以下方式配置 HandlerMapping

  • XML 配置:在 Spring 的 XML 配置文件中定义 HandlerMapping 和映射规则。
  • Java 配置(注解):在 Spring Boot 或基于 Java 的 Spring 配置中,使用 @EnableWebMvc 和注解的方式配置 HandlerMapping

总结:

HandlerMapping 是 Spring MVC 的重要组成部分,它负责根据请求的 URL、HTTP 方法、请求参数等信息找到对应的处理器(通常是 Controller 方法)。Spring 提供了多种实现方式,允许开发者根据不同的需求选择最合适的映射策略。

处理器适配器 HandlerAdapter

HandlerAdapter 是 Spring MVC 框架中的一个接口,负责在请求处理过程中,调用已由 HandlerMapping 映射的处理器(handler)并将其返回的结果适配为合适的响应。简而言之,HandlerAdapter 负责执行处理器(通常是 Controller 中的方法),并将结果返回给 DispatcherServlet

主要功能:

HandlerAdapter 主要作用是解耦 DispatcherServlet 与处理器的执行逻辑,它的核心功能是:

  1. 调用处理器HandlerAdapter 根据映射到的处理器来执行实际的业务逻辑。
  2. 支持多种处理器类型:它能够适配不同类型的处理器。例如,支持处理普通的控制器方法、注解控制器方法,甚至支持传统的 Spring Controller 类。
  3. 返回结果处理:执行处理器后,HandlerAdapter 负责将处理器返回的结果转化为响应信息(如视图名或数据)并交给 DispatcherServlet,使其最终向客户端返回响应。

工作流程:

  1. 客户端请求:客户端发送请求到 DispatcherServlet
  2. HandlerMapping 查找处理器DispatcherServlet 根据请求 URL 和 HTTP 方法,通过相应的 HandlerMapping 查找合适的处理器(通常是某个 Controller 的方法)。
  3. HandlerAdapter 调用处理器DispatcherServlet 找到合适的处理器后(handler 的方法会封装成 HandlerMethod 对象,SpringMVC 会遍历每个适配器的 supports(handler) 方法来判断该适配器是否支持当前的 handlerMethod),会委托给 HandlerAdapter 来执行该处理器。
  4. 处理器执行HandlerAdapter 调用处理器的相应方法,执行处理逻辑,并获取返回结果。
  5. 返回响应HandlerAdapter 将处理器的返回值(视图名、数据等)交给 DispatcherServlet,后者进一步将结果渲染成响应并发送回客户端。

常见的 HandlerAdapter 实现:

  1. RequestMappingHandlerAdapter: 这是 Spring MVC 中最常用的 HandlerAdapter 实现,专门处理通过 @RequestMapping(以及相关的注解如 @GetMapping@PostMapping)标记的控制器方法。它支持 Spring MVC 中的注解驱动的 Controller 方法,并可以处理不同的返回类型(如视图名、ModelAndView、对象、ResponseEntity 等)。

    @Controller
    public class MyController {
    
        @RequestMapping("/hello")
        public String sayHello() {
            return "Hello, Spring MVC!";
        }
    }
    
    
  2. SimpleControllerHandlerAdapter: 用于传统的 Controller 接口实现,适用于不使用注解驱动的旧版本 Spring MVC 控制器。例如,使用 Controller 接口的实现类:

    public class HelloController implements Controller {
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
            ModelAndView modelAndView = new ModelAndView("hello");
            modelAndView.addObject("message", "Hello, Spring MVC!");
            return modelAndView;
        }
    }
    
    
  3. AbstractHandlerMethodAdapter: 这是一个抽象类,用于适配 HandlerMethod。它是 RequestMappingHandlerAdapter 和其他处理器适配器的基类,支持将控制器方法封装为 HandlerMethod 对象来进行处理。

示例代码:

假设我们有一个简单的控制器方法,它会返回一个字符串作为视图名:

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String sayHello() {
        return "helloView";  // 返回视图名
    }
}

当客户端访问 /hello 时,HandlerMapping 会将请求映射到 sayHello() 方法,然后由 RequestMappingHandlerAdapter 调用 sayHello() 方法。

  1. DispatcherServlet 会通过 HandlerMapping 查找适合的处理器。
  2. HandlerAdapter(通常是 RequestMappingHandlerAdapter)会调用 sayHello() 方法。
  3. 方法返回一个字符串 "helloView",它作为视图名被返回。
  4. DispatcherServlet 将视图名 "helloView" 渲染成最终的响应页面。

总结:

HandlerAdapter 是 Spring MVC 中请求处理流程的关键组件,它充当了请求和控制器方法之间的桥梁。通过 HandlerAdapter,Spring 能够将不同类型的处理器(如基于注解的控制器方法或传统的 Controller 接口)统一适配为可执行的处理逻辑。

异常解析器 HandlerExceptionResolver

HandlerExceptionResolver 是 Spring MVC 中的一个接口,它用于 统一处理请求处理过程中的异常。当 Spring MVC 在执行处理器方法(比如 Controller 中的方法)时,如果发生了异常,HandlerExceptionResolver 允许你捕获并处理这些异常,从而避免将异常直接抛出到用户或者导致系统崩溃。

主要功能

HandlerExceptionResolver 的核心作用是捕获并处理控制器方法中抛出的异常,并决定如何响应客户端。你可以通过实现该接口或配置已有的异常处理器来定制异常的处理方式。

工作流程

  1. 请求被处理器(Controller)执行时,如果发生了异常,Spring MVC 会尝试通过已配置的 HandlerExceptionResolver 来处理这个异常。
  2. HandlerExceptionResolver 会遍历配置的异常解析器,并根据异常类型匹配相应的处理器。
  3. 异常处理:如果匹配到一个合适的 HandlerExceptionResolver,它将被调用,处理异常并生成响应。异常处理器可以返回一个 ModelAndView,以展示错误页面,或返回一个其他形式的响应(如 JSON、XML 错误信息等)。
  4. 如果没有任何一个 HandlerExceptionResolver 被调用,异常将被传递给默认的异常处理机制,或者最终抛出给用户。

主要接口方法

HandlerExceptionResolver 只有一个方法:

ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

  • request: 当前的 HTTP 请求。
  • response: 当前的 HTTP 响应。
  • handler: 处理该请求的处理器对象。
  • ex: 捕获到的异常对象。

方法的返回值是一个 ModelAndView,如果返回 null,则表示没有处理该异常,Spring 会继续检查其他的异常解析器。

示例:自定义 HandlerExceptionResolver

你可以通过实现 HandlerExceptionResolver 接口,来实现自定义的异常处理逻辑。

例如,假设我们想要处理 NullPointerException 并返回一个自定义的错误页面:

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 只处理 NullPointerException
        if (ex instanceof NullPointerException) {
            // 日志记录、异常处理等
            return new ModelAndView("errorPage", "message", "Null Pointer Exception occurred");
        }
        return null;  // 返回 null 表示没有处理该异常,Spring MVC 会继续查找其他解析器
    }
}

然后,你可以在 Spring 配置中注册该异常解析器:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(new CustomExceptionResolver());
    }
}

使用场景

  • 全局异常处理HandlerExceptionResolver 适合于处理应用程序中的全局异常。比如,统一的 404 错误页面、500 错误页面,或者返回 JSON 格式的错误信息。
  • 特定类型的异常处理:通过自定义的异常解析器,你可以为特定的异常类型(如 NullPointerExceptionIOException)提供不同的处理方式。

Spring 中的内建异常解析器

Spring MVC 提供了一些内建的 HandlerExceptionResolver 实现,你可以直接使用或扩展它们:

  1. SimpleMappingExceptionResolver
    • 用于将异常映射到特定的视图(比如错误页面)。
    • 可以配置异常到视图的映射关系,例如,将 NullPointerException 映射到 nullPointerError 视图。
  2. ResponseStatusExceptionResolver
    • 处理 @ResponseStatus 注解标记的异常,将其转换为 HTTP 响应状态码。
  3. DefaultHandlerExceptionResolver
    • 处理标准的异常类型(如 HttpRequestMethodNotSupportedExceptionNoHandlerFoundException 等)。
  4. ExceptionHandlerExceptionResolver
    • 处理 @ExceptionHandler 注解标记的异常处理方法,通常与 @ControllerAdvice 配合使用,提供更灵活的异常处理机制。

示例:使用 @ExceptionHandler@ControllerAdvice

虽然 HandlerExceptionResolver 提供了强大的功能,但 Spring 还推荐使用 @ExceptionHandler@ControllerAdvice 注解来进行异常处理,它们通常更简单且更灵活。

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    public ModelAndView handleNullPointerException(NullPointerException ex) {
        ModelAndView modelAndView = new ModelAndView("errorPage");
        modelAndView.addObject("message", "A NullPointerException occurred");
        return modelAndView;
    }
}

总结

HandlerExceptionResolver 的作用是 统一处理 Spring MVC 中的异常,避免了异常直接暴露给客户端或造成不必要的系统崩溃。它允许你自定义异常处理逻辑,如返回自定义的错误页面或特定格式的错误响应。你可以通过实现该接口或者使用 Spring 提供的其他机制(如 @ExceptionHandler)来定制异常的处理方式。

posted @   CyrusHuang  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示