从 SpringBoot 到 SpringMVC

时间:2022-07-27
本文章向大家介绍从 SpringBoot 到 SpringMVC,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

概述

用久了 SpringBoot,深受其约定大于配置的便利性毒害之后,我想回归到 SpringMVC 时代,看看 SpringMVC 开发模式中用户是如何参与的。本文就来体验一下 SpringMVC 时代开发的流程。


SpringMVC 架构模式

一个典型的 SpringMVC 请求流程如图所示,详细分为 12 个步骤:

  1. 用户发起请求,由前端控制器 DispatcherServlet 处理
  2. 前端控制器通过处理器映射器查找 hander,可以根据 XML 或者注解去找
  3. 处理器映射器返回执行链
  4. 前端控制器请求处理器适配器来执行 hander
  5. 处理器适配器来执行 handler
  6. 处理业务完成后,会给处理器适配器返回 ModeAndView 对象,其中有视图名称,模型数据
  7. 处理器适配器将视图名称和模型数据返回到前端控制器
  8. 前端控制器通过视图解析器来对视图进行解析
  9. 视图解析器返回真正的视图给前端控制器
  10. 前端控制器通过返回的视图和数据进行渲染
  11. 返回渲染完成的视图
  12. 将最终的视图返回给用户,产生响应

整个过程清晰明了,下面我们将结合实际实验来理解这整个过程。


SpringMVC 项目搭建

实验环境如下:

  • IntelliJ IDEA 2018.1 (Ultimate Edition)
  • SpringMVC 4.3.9.RELEASE
  • Maven 3.3.9

这里我是用 IDEA 来搭建的基于 Maven 的 SpringMVC 项目,搭建过程不再赘述,各种点击并且下一步,最终创建好的项目架构如下:

添加前端控制器配置

使用了 SpringMVC,则所有的请求都应该交由 SpingMVC 来管理,即要将所有符合条件的请求拦截到 SpringMVC 的专有 Servlet 上。

为此我们需要在 web.xml 中添加 SpringMVC前端控制器 DispatcherServlet:

    <!--springmvc 前端控制器-- 
    <servlet 
        <servlet-name mvc-dispatcher</servlet-name 
        <servlet-class org.springframework.web.servlet.DispatcherServlet</servlet-class 
        <init-param 
            <param-name contextConfigLocation</param-name 
            <param-value classpath:mvc-dispatcher.xml</param-value 
        </init-param 
    </servlet 

    <servlet-mapping 
        <servlet-name mvc-dispatcher</servlet-name 
        <url-pattern *.action</url-pattern 
    </servlet-mapping 

该配置说明所有符合.action 的 url,都交由 mvc-dispatcher 这个 Servlet 来进行处理


编写 SpringMVC 核心 XML 配置文件

从上一步的配置可以看到,我们定义的 mvc-dispatcher Servlet 依赖于配置文件 mvc-dispatcher.xml,在本步骤中我们需要在其中添加三个方面的配置

  • 0x01. 添加处理器映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" / 

SpringMVC 的处理器映射器有多种,这里的使用的 BeanNameUrlHandlerMapping 其映射规则是将 bean 的 name 作为 url 进行处理

  • 0x02. 添加处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" / 

SpringMVC 的处理器适配器也有多种,这里的使用的 SimpleControllerHandlerAdapter 是 Controller 实现类的适配器类,其本质是执行 Controller 中的 handleRequest 方法。

  • 0x03. 添加试图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" / 

这里配置了 InternalResourceViewResolver 视图解析器后,其会根据 controller 方法执行之后返回的 ModelAndView 中的视图的具体位置,来加载对应的界面并绑定数据


编写控制器

这里模拟的是一个打印学生名单的 Service,我们编写的控制器需要将查询到的学生名单数据通过 ModelAndView 渲染到指定的 JSP 页面中

public class TestController implements Controller {

    private StudentService studentService = new StudentService();

    @Override
    public ModelAndView handleRequest( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        List<Student  studentList = studentService.queryStudents();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("studentList",studentList);
        modelAndView.setViewName("/WEB-INF/views/studentList.jsp");
        return modelAndView;
    }
}

class StudentService {
    public List<Student  queryStudents() {
        List<Student  studentList = new ArrayList<Student ();

        Student hansonwang = new Student();
        hansonwang.setName("hansonwang99");
        hansonwang.setID("123456");

        Student codesheep = new Student();
        codesheep.setName("codesheep");
        codesheep.setID("654321");

        studentList.add(hansonwang);
        studentList.add(codesheep);

        return studentList;
    }
}

编写视图文件

这里的视图文件是一个 jsp 文件,路径为:/WEB-INF/views/studentList.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" % 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" % 
<html 
<head 
<title 学生名单</title 
</head 
<body 
<h3 学生列表</h3 
<table width="300px;" border=1 
<tr 
<td 姓名</td 
<td 学号</td 
</tr 
<c:forEach items="${studentList}" var="student"  
<tr 
<td ${student.name}</td 
<td ${student.ID}</td 
</tr 
</c:forEach 
</table 
</body 
</html 

结合本步骤和上一步骤,视图和控制器都已编写完成,由于我们之前配置的处理器映射器为:BeanNameUrlHandlerMapping,因此接下来我们还需要在 mvc-dispatcher.xml 文件中配置一个可被 url 映射的 controller 的 bean,供处理器映射器 BeanNameUrlHandlerMapping 查找:

<bean name="/test.action" class="cn.codesheep.controller.TestController" / 

实验测试

启动 Tomcat 服务器,然后浏览器输入:

http://localhost:8080/test.action

数据渲染 OK。

备注:当然本文所使用的全是非注解的配置方法,即需要在 XML 中进行配置并且需要遵循各种实现原则。而更加通用、主流的基于注解的配置方法将在后续文章中详述。