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 的其他内容。感兴趣的小伙伴不妨点个关注。


目录
相关文章
|
30天前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
8月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
454 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
699 0
|
8月前
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
449 0
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestMapping
@RequestMapping 是 Spring MVC 中用于请求地址映射的注解,可作用于类或方法上。类级别定义控制器父路径,方法级别进一步指定处理逻辑。常用属性包括 value(请求地址)、method(请求类型,如 GET/POST 等,默认 GET)和 produces(返回内容类型)。例如:`@RequestMapping(value = &quot;/test&quot;, produces = &quot;application/json; charset=UTF-8&quot;)`。此外,针对不同请求方式还有简化注解,如 @GetMapping、@PostMapping 等。
398 0
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RestController
本文主要介绍 Spring Boot 中 MVC 开发常用的几个注解及其使用方式,包括 `@RestController`、`@RequestMapping`、`@PathVariable`、`@RequestParam` 和 `@RequestBody`。其中重点讲解了 `@RestController` 注解的构成与特点:它是 `@Controller` 和 `@ResponseBody` 的结合体,适用于返回 JSON 数据的场景。文章还指出,在需要模板渲染(如 Thymeleaf)而非前后端分离的情况下,应使用 `@Controller` 而非 `@RestController`
310 0
|
4月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
308 0
|
4月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
147 0
|
4月前
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
247 0
|
10月前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
508 29