5 分钟彻底理解 Spring MVC(下)

简介: 处理器配置看到这里,细心的小伙伴可能会有疑问,说好的 DispatcherServlet 将请求分派给 Controller 呢?这里暂时不用着急,Controller 其实是 Spring MVC 的处理器类型之一,这里的 HttpRequestHandler 同样是 Spring MVC 的处理器。

处理器配置


看到这里,细心的小伙伴可能会有疑问,说好的 DispatcherServlet 将请求分派给 Controller 呢?这里暂时不用着急,Controller 其实是 Spring MVC 的处理器类型之一,这里的 HttpRequestHandler 同样是 Spring MVC 的处理器。


Spring 对多种处理器进行了支持,具体则是使用 HandlerAdapter 对处理器进行适配,Spring MVC 内部已经默认了一些适配器,HttpRequestHandler 的适配器是 HttpRequestHandlerAdapter,Controller 的适配器 SimpleControllerHandlerAdapter 也是 Spring MVC 默认支持的。


默认的 HandlerAdapter 已经足够支持日常所需,一般不会自定义 HandlerAdapter。


下面尝试使用 Controller 作为处理器处理请求,定义实现 Controller 接口的 HelloSpringMVCController 类如下。


public class HelloSpringMVCController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("/WEB-INF/view/welcome.jsp");
        modelAndView.addObject("hello", "HelloSpringMVCController");
        return modelAndView;
    }
}


然后在 Spring 配置文件中添加这个类作为 bean。


<bean id="/hellocontroller" class="com.zzuhkp.mvc.handler.HelloSpringMVCController"/>


到了这里,终于可以看到 Controller 了,Controller 处理请求,返回了一个类型为 ModelAndView 的对象。


ModelAndView 包含模型和视图,这里向模型中添加了属性 hello,并且指定了/WEB-INF/view/welcome.jsp 文件作为视图名,这个文件内容如下。


<html>
<body>
<h2>Hello,${requestScope.hello}</h2>
</body>
</html>


启动 Tomcat 访问 /hellocontroller 效果如下。


image.png


ViewResolver 配置


为了支持不同的视图,如 JSP、FreeMarker 等,ModelAndView 中的视图名称被设计成虚拟的,具体的视图由视图解析器 ViewResolver 进行解析,默认情况下使用的视图解析器是 InternalResourceViewResolver ,这个视图解析器基于 URL 解析视图。同时也可以向应用上下文中配置自己的视图解析器。添加自定义的 InternalResourceViewResolver 到 Spring 配置文件。


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view"/>
        <property name="suffix" value=".jsp"/>
    </bean>


然后设置视图名时就可以忽略路径前缀/WEB-INF/view和后缀.jsp,配置前缀后缀后上述示例中 HelloSpringMVCController 就可以将视图名从 /WEB-INF/view/welcome.jsp 简化为 welcome。


DispatcherServlet 组件默认配置


上述示例中使用了不少 DispatcherServlet 使用的组件,Spring MVC 默认情况下已经提供了一些,如果需要自定义,则将自定义的组件添加到上下文配置中接口,十分方便,那么 Spring 默认情况下使用了哪些组件处理请求呢?


spring-webmvc 模块类路径下 org/springframework/web/servlet/DispatcherServlet.properties 文件定义了这些默认的配置,具体如下。


9.png


基于注解的 Spring WebMVC


基于配置文件的 Spring Web MVC 项目在前些年确实比较流行,然而现在注解已经成为 Spring 开发的主流。下面通过纯注解的方式对上面的示例进行改造。

pom 文件不需要进行变化,首先要提供 Spring 配置类。


@ComponentScan("com.zzuhkp.mvc")
public class MvcConfig {
}


这里只添加了组件扫描能力,Spring 会将给定包下标注了 @Component 的类作为 bean 进行处理。然后将将这个类设置为配置类即可,这里可以参见使用上述提供的 DispatcherServlet 第二种声明方式

然后提供基于注解的控制器。


@Controller
public class HelloSpringMVCAnnotationController {
    @GetMapping("/helloAnnotationController")
    public String helloMVC(@RequestParam("hello") String hello, Model model) {
        model.addAttribute("hello", hello);
        return "/WEB-INF/view/welcome.jsp";
    }
}


基于注解的控制器不需要实现特定的接口,直接在类上添加 @Controller 注解即可,这里定义了一个处理 /helloAnnotationController 路径 GET 请求方式的方法,并且接收 hello 参数,存放至 model 中,然后返回了视图名。这里直接复用了上面示例中的视图。最终效果如下。


image.png


基于注解的控制器是 Spring MVC 中设计最为灵活的地方,这里可以先考虑下,Spring 是怎么适配用户自定义的控制器的?控制器方法中的参数如何赋值呢?如何将控制器方法的返回值解析为视图?Spring 如何支持 RESTFUL 风格的接口的?后面会写几篇文章继续分析。


DispatcherServlet 请求处理流程


DispatcherServlet 请求处理流程已经穿插在前面的示例中介绍,直接看前面的描述可能不是很直观,这里总结了一张图来梳理整个流程。


10.png

整个流程串联起来如下。


DispatcherServlet 处理浏览器发起的请求。

DispatcherServlet 根据用户或默认的配置使用 HandlerMapping 查找可处理请求的处理器。

DispatcherServlet 拿到 HandlerMapping 返回的处理器链 HandlerExecutionChain。整个处理器链包含拦截器和处理。

DispatcherServlet 将处理器适配为 HandlerAdapter。

DispatcherServlet 使用拦截器进行请求前置处理。

DispatcherServlet 使用处理器进行请求处理。

DispatcherServlet 使用拦截器进行请求后置处理。

DispatcherServlet 从拦截器或处理器中提取到模型及视图 ModelAndView。

DispatcherServlet 使用视图解析器 ViewResolver 解析视图出视图 View。

DispatcherServlet 渲染视图,响应请求。


结束语

本文先介绍 MVC 架构模式,然后通过示例的方式对 Spring MVC 的使用方式及执行流程进行介绍,最后还使用一个流程图总结。


Spring MVC 中所有的扩展都基于 DispatcherServlet 处理请求的这个流程,可以说理解了这个流程图就理解了 Spring MVC 的原理,后面将会对这个流程进行细化,继续介绍 Spring MVC 的其他内容。感兴趣的小伙伴不妨点个关注。


目录
相关文章
|
25天前
|
JSON 前端开发 Java
解决Spring MVC中No converter found for return value of type异常
在Spring MVC开发中遇到`No converter found for return value of type`异常,通常是因缺少消息转换器、返回值类型不支持或转换器优先级配置错误。解决方案包括:1) 添加对应的消息转换器,如`MappingJackson2HttpMessageConverter`;2) 自定义消息转换器并实现`HttpMessageConverter`接口,设置优先级;3) 修改返回值类型为如`ResponseEntity`的合适类型。通过这些方法可确保返回值正确转换为响应内容。
35 1
|
7天前
|
前端开发 Java 应用服务中间件
Spring MVC常见面试题
Spring MVC常见面试题
6 0
|
21天前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
23 3
|
21天前
|
存储 前端开发 Java
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
14 1
|
21天前
|
前端开发 Java Spring
数据之桥:深入Spring MVC中传递数据给视图的实用指南
数据之桥:深入Spring MVC中传递数据给视图的实用指南
31 3
|
21天前
|
前端开发 Java 容器
家族传承:Spring MVC中父子容器的搭建与管理指南
家族传承:Spring MVC中父子容器的搭建与管理指南
26 3
|
21天前
|
前端开发 Java API
头头是道:揭示Spring MVC如何获取和处理请求头数据
头头是道:揭示Spring MVC如何获取和处理请求头数据
22 1
|
21天前
|
前端开发 Java API
饼干探秘:深入Spring MVC中获取Cookie数据的技术解析
饼干探秘:深入Spring MVC中获取Cookie数据的技术解析
18 3
|
21天前
|
前端开发 Java Spring
转换之术:解析Spring MVC中类型转换器的实际运用
转换之术:解析Spring MVC中类型转换器的实际运用
21 0
|
21天前
|
前端开发 Java Spring
参数解密:揭示Spring MVC请求参数处理的实际应用指南
参数解密:揭示Spring MVC请求参数处理的实际应用指南
26 1