SpringMVC笔记(1)-SpringMVC简介与快速开始

介绍

在前面JavaWeb章节,我们介绍了MVC的软件结构思想。按照这种思想,可以将软件按照模型、视图、控制器来进行划分。用户通过视图层发送请求到服务器,在服务器端,请求被Contorller接收,Controller调用相应的Model层来处理请求,处理完毕后将结果返回到Controller中,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器。

同时我们也介绍了三层架构,这是一种对MVC模式进行实现的方式。其中的表现层包含了MVC中的View和Controller。SpringMVC就是一款表示层的框架。

SpringMVC是Spring的一个后续产品,是Spring的一个子项目。SpringMVC是Spring为表示层开发提供的一整套完备的解决方案。它是Spring家族原生的产品,因此可以与IOC容器等基础设施进行无缝对接;同时它封装了原生的Servler,通过功能强大的前端控制器DispatcherServlet来对请求和响应进行统一处理;此外,还具有其他的优点,包括代码简洁、组件化程度高即插即用、性能优异等等。

快速开始

下面我们进行SpringMVC的快速开始。首先我们需要创建一个Maven Web工程,具体步骤在JavaWeb章节中有说明(JavaWeb笔记(2)-Tomcat的使用 - EverNorif),包括修改packaging属性为war,补齐相关项目结构等。

之后,我们需要引入下面的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--SpringMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>

<!--日志-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>

<!--Servlet-API-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

<!--Spring5与Thymeleaf整合-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>

在依赖中,我们用到了Spring和Thymeleaf的整合。

Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它的模板文件后缀为.html,可以直接被浏览器打开。Thymeleaf使用一些特定的语法标签来表示不同的含义,但是并不会破坏html结构。如果在离线情况下打开,则浏览器会忽略未定义的Thymeleaf标签属性,展示模板的静态页面效果;如果通过Web应用程序访问,则会动态替换掉其中的静态内容,使页面动态显示,达到动静结合的效果。Thymeleaf也是SpringBoot官方推荐的模板引擎。

Thymeleaf的相关内容可以后面的参考内容。

之后,我们需要配置web.xml,在其中注册SpringMVC的前端控制器DispatcherServlet以及相关信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--配置SpringMVC的前端控制器-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--固定为contextConfigLocation-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置能够处理的请求路径-->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

web.xml中,我们首先需要配置SpringMVC的前端控制器,使用servlet标签,对应的类为DispatcherServlet,这是SpringMVC中封装的类,用于对浏览器发送的请求进行统一的处理。然后还需要配置该类能够处理的请求路径,使用servlet-mapping标签,对应路径下的请求都将经过我们配置的控制器来处理。

在配置DispatcherServlet的时候,我们可以通过初始化参数指定Spring配置文件的位置和名称,即这里的init-param标签。由于SpringMVC也是需要使用到IOC容器,因此也会对应到一个Spring的配置文件。如果没有配置,则我们需要将对应的配置文件创建在固定的位置,并且命名也是固定的。创建的位置固定为WEB-INF目录下,名称固定为<servlet-name>-servlet.xml,像这里默认应该创建为SpringMVC-servlet.xml。这里我们通过初始化参数指定的位置,因此不需要按照默认情况。

这里我们还设置了load-on-startup值为1,表示在服务器启动的时候进行Servlet的初始化。默认情况是第一次访问到的时候才初始化,但是由于SpringMVC中DispatcherServlet的初始化涉及到的资源比较丰富,因此推荐它的初始化时机提前。

在配置处理请求路径的时候,我们可以使用//*来代表匹配所有资源,但是还是略有区别。/所匹配的请求可以是目录、后缀等,但是不能匹配.jsp请求路径的请求,.jsp的请求通过的是Tomcat配置中的Servlet处理,而不是DispathcerServlet。而如果是/*,则能够匹配所有请求,包括.jsp的请求路径。

在SpringMVC中,DispathcerServlet对浏览器发送的请求进行了统一的处理,但是这更像是一种所有请求都需要经过的预处理,而对应具体的请求有不同的处理逻辑,因此需要创建处理具体请求的类,即Controller层中的相应类,或者是请求控制器,而请求控制器中的每一个处理请求的方法则称为控制器方法。

创建如下测试类,用注解@Contorller进行标识:

1
2
3
@Controller
public class HelloController {
}

为了将类交由IOC容器管理,我们还需要创建Spring配置文件,也就是前面在配置路径中提到的springMVC.xml,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<context:component-scan base-package="com.syh.mvc"/>

<!--配置Thymeleaf视图解析器-->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!--视图前缀-->
<property name="prefix" value="/WEB-INF/templates/"/>
<!--视图后缀-->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>

在其中配置了基于注解的自动扫描,以及配置了Thymeleaf视图解析器。这里配置了视图前缀和视图后缀,后续我们的Thymeleaf的模板文件都会写在/WEB-INF/templates目录下,且后缀名为.html

之后我们在请求控制器HelloContorller中增加如下的方法:

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/")
public String index() {
// 设置视图名称
return "index";
}

@RequestMapping("/hello")
public String hello() {
return "target";
}

这里利用@RequestMapping注解标识了对应访问路径,即对该路径的访问会经过这个方法,返回值为视图名称。视图名称需要对应到一个html页面,对应方式需要结合前面配置的视图前缀和视图后缀,在视图名称前后分别添加配置的前后缀,就是对应的页面路径。这里即为/WEB-INF/templates/index.html以及/WEB-INF/templates/target.html。那么接下来在WEB-INF/templates目录下分别创建了index.html以及target.html页面,在其中添加了相应的内容。

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index.html</h1>
<a th:href="@{/hello}">HelloWorld</a>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>target</title>
</head>
<body>
<h1>Hello Success</h1>
</body>
</html>

由于这里使用了Thymeleaf的相关标签,所以我们引入对应的约束来辅助我们进行编写。当然不引入也没有关系。

之后我们可以启动服务器Tomcat进行测试。默认情况下,我们是无法通过浏览器链接直接访问到WEB-INF下的资源,但是这里我们可以通过访问//hello看到对应的显示效果。

总结来说,上面的流程大概分为下面的步骤:

  1. 浏览器向服务器发送请求,如果请求地址符合前端控制器配置的url-pattern,则该请求就会被前端控制器DispatcherServlet处理。
  2. 前端控制器会读取SpringMVC的配置文件,扫描IOC容器中的组件并找到控制器,即使用@Controller注解标注的类。
  3. 之后,将请求地址与控制器的方法上@RequestMapping注解的value属性进行匹配,如果匹配成功,则就由该方法来处理请求。
  4. 处理请求的方法需要返回一个视图,这里返回了一个字符串类型的视图名称。
  5. 该视图名称会被视图解析器进行解析,加上视图前缀和后缀组成视图的路径。
  6. 然后Thymeleaf对找到的视图进行渲染,最终返回到视图所对应的页面上。

参考文章

  1. Thymeleaf教程(10分钟入门) (biancheng.net)
  2. Thymeleaf从入门到精通 - 知乎 (zhihu.com)
  3. Documentation - Thymeleaf

SpringMVC笔记(1)-SpringMVC简介与快速开始
http://example.com/2022/10/16/SpringMVC笔记-1-SpringMVC简介与快速开始/
作者
EverNorif
发布于
2022年10月16日
许可协议