本节,我们将通过一个简单的 Java Web 应用来演示下如何创建 Spring MVC 程序。
首先,我们需要使用 Eclipse 创建一个 Java Web 项目,具体步骤如下。
1. 在 Eclipse 中,依次单击 File -> New -> Dynamic Web Project,创建一个 Java Web 项目,如下图所示。
2. 在弹出的 Dynamic Web Project 窗口中,设置 Project Name 为 first-springmvc-demo,然后点击下方的 New Runtime... 按钮,对该项目运行所需的服务器进行设置,如下图。
3. 在弹出的 New Server Runtime Environment 窗口中,选择 Apache 下对应版本的 Tomcat(这里我们以 Tomcat v9.0 为例),然后点击下方的 Next 按钮,如下图。
4. 在 Tomcat Server 窗口中,设置本地 Tomcat 的路径以及 JRE 版本,如下图所示。
5. 返回 Dynamic Web Project 窗口,可以看到 Tomcat 服务器已经设置完成,点击下方的 Next 按钮,如下图所示。
6. 在 Web Module 窗口中将 Content directory 修改为 webapp,并勾选下方的 Gnerate web.xml deployment desciptor,最后点击下方的 Finish 按钮完成项目的创建,如下图所示。
7. Java Web 项目 first-springmvc-demo 创建完成之后,结构如下图所示。
自此,我们就完成了使用 Eclipse 创建 Java Web 项目的全部步骤。
在完成了 Java Web 项目的创建后,接下来,我们需要将 Spring MVC 相关的依赖引入到该项目中。将以下依赖 Jar 包导入到 first-springmvc-demo 项目的 webapp/WEB-INF/lib 目录中。
对于 Web 项目而言,前后端分离可以说是当今最主流的思想,该思想概括成一句话就是“前端只写前端的代码,后端只写后端的代码,前后端互不影响”。
在传统的 Java Web 开发中,通常都是使用 JSP 来进行前台页面的开发。但 JSP 页面中常常会掺杂这一些后端的 Java 代码,其中任何一个简单的 Java 代码问题都有可能导致整个项目无法启动,而这显然不符合“前后端分离”的思想。
因此在现在的 Java Web 开发中,已经很少有人在使用 JSP 了。各互联网公司、组织或个人都陆续使用其他技术来代替 JSP ,而 Thymeleaf 就是其中较为优秀的技术之一。
Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等一样,也可以轻易地与 Spring MVC 等 Web 框架集成。但与其它模板引擎相比,Thymeleaf 最大的特点就是,即使不启动 Web 应用也可以直接在浏览器中打开并正确地显示页面。
想要使用 Thymeleaf 进行前台页面开发,必不可少的一步就是将 Thymeleaf 的相关依赖引入到项目中。
将以下依赖存放到 first-springmvc-demo 项目的 webapp/WEB-INF/lib 目录中,以完成 Thymeleaf 依赖的导入。
注:点击以上依赖,即可下载对应依赖的 Jar 包。
Spring MVC 是基于 Servlet 的,DispatcherServlet 是整个 Spring MVC 框架的核心,主要负责截获请求并将其分派给相应的处理器处理。
跟所有的 Servlet 一样,DispatcherServlet 也需要在 web.xml 中进行配置,它才能够正常工作,示例代码如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- 配置 SpringMVC 的前端控制器,对浏览器发送的请求统一进行处理 --> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!--设置springMVC的核心控制器所能处理的请求的请求路径 /所匹配的请求可以是/login或.html或.js或.css方式的请求路径 但是/不能匹配.jsp请求路径的请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Spring MVC 初始化时,会自动从应用程序的 WEB-INF 目录下查找 Spring MVC 的配置文件。该配置文件的默认命名规则为 {servlet-name}-servlet.xml
,例如 springMVC-servlet.xml。
我们也可以将 Spring MVC 的配置文件存放在应用程序目录中的其他位置,但需要在 <servlet> 元素下通过 <init-param> 元素的 contextConfigLocation 参数,来指定 Spring MVC 配置文件的位置,示例代码如下。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- 配置 SpringMVC 的前端控制器,对浏览器发送的请求统一进行处理 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--配置 DispatcherServlet 的一个初始化参数:spring mvc 配置文件按的位置和名称--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMVC.xml</param-value> </init-param> <!--作为框架的核心组件,在启动过程中有大量的初始化操作要做 而这些操作放在第一次请求时才执行会严重影响访问速度 因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!--设置springMVC的核心控制器所能处理的请求的请求路径 /所匹配的请求可以是/login或.html或.js或.css方式的请求路径 但是/不能匹配.jsp请求路径的请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
默认情况下,所有的 Servlet(包括 DispatcherServlet )都是在第一次调用时才会被加载。这种机制虽然能一定程度上降低项目启动的时间,但却增加了用户第一次访问所需的时间,给用户带来不佳的体验。因此在上面的 web.xml 中,我们通过 <load-on-startup> 标签对 Spring MVC 前端控制器 DispatcherServlet 的初始化时间进行了设置,让它在项目启动时就完成了加载。
load-on-startup 元素取值规则如下:
此外,我们还通过 <servlet-mapping> 将 DispatcherServlet 映射到“/”,表示 DispatcherServlet 需要截获并处理该项目的所有 URL 请求(以 .jsp 为后缀的请求除外)。
在 first-springmvc-demo 项目的 src 目录下,创建一个名为 springMVC.xml 的配置文件,配置内容如下。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--开启组件扫描--> <context:component-scan base-package="net.biancheng.c"></context:component-scan> <!-- 配置 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> </beans>
在上面的配置中,我们定义一个名为 viewResolver,类型为 ThymeleafViewResolver 的 Bean,这其实是 Thymeleaf 的视图解析器。通过它,我们可以对 Thymeleaf 视图的编码、视图前缀、视图后缀等进行配置。
我们知道,DispatcherServlet 会拦截用户发送来的所有请求进行统一处理,但不同的请求有着不同的处理过程,例如登陆请求和注册请求就分别对应着登陆过程和注册过程,因此我们需要 Controller 来对不同的请求进行不同的处理。
在 Spring MVC 中,一个普通的 Java 类只要标注了 @Controller 注解,就会被 Spring MVC 识别成 Controller。Controller 类中的每一个处理请求的方法被称为“控制器方法”。
控制器方法在处理完请求后,通常会返回一个字符串类型的逻辑视图名(ViewName),Spring MVC 需要借助 ViewResolver(视图解析器)将这个逻辑视图名解析为真正的 View 视图,最终响应给客户端展示。
例如,在 first-springmvc-demo 项目的 src 目录下创建一个 net.biancheng.c.controller 包,并在该包下创建一个名为 HelloController 的控制器类,代码如下。
package net.biancheng.c.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping("/") public String sayHello() { //视图名,视图为:视图前缀+index+视图后缀,即 /WEB-INF/template/index.html return "index"; } @RequestMapping("/login") public String welcome() { //视图名,视图为:视图前缀+login+视图后缀,即 /WEB-INF/template/login.html return "login"; } @RequestMapping("/register") public String success() { //视图名,视图为:视图前缀+register+视图后缀,即 /WEB-INF/template/register.html return "register"; } }
在以上代码中,除了 @Controller 注解外,我们还在方法上使用了 @RequestMapping 注解,它的作用就是将请求和处理请求的控制器方法关联映射起来,建立映射关系。Spring MVC 的 DispatcherServelt 在拦截到指定的请求后,就会根据这个映射关系将请求分发给指定的控制器方法进行处理。
根据 Spring MVC 配置文件中关于 Thymeleaf 视图解析器的配置可知,所有的 Thymeleaf 视图文件都应该存放在 /WEB-INFO/temlpates 目录下且文件名必须以 .html 结尾。
1. 在 /WEB-INFO 目录下创建一个 templates 的目录,并在该目录下创建 index.html,代码如下。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>C语言中文网</title> </head> <body> <h1 th:text="欢迎您访问C语言中文网"></h1> 未注册用户,请<a th:href="@{/register}">注册</a><br/> 已注册用于,去<a th:href="@{/login}">登陆</a> </body> </html>
2. 在 /WEB-INFO/templates 下创建 login.html,代码如下。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>C语言中文网</title> </head> <body> <h1 th:text="欢迎来登陆页面"></h1> <a th:href="@{/}">跳转首页</a><br/> <a th:href="@{/register}">跳转到注册页面</a> </body> </html>
3. 在 /WEB-INFO/templates 下创建 register.html,代码如下。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>C语言中文网</title> </head> <body> <h1 th:text="欢迎来到注册页面"></h1> <a th:href="@{/}">跳转首页</a><br/> <a th:href="@{/login}">跳转到登陆页面</a> </body> </html>
1. 将 first-springmvc-demo 部署到 Tomcat 中,启动 Tomcat 服务器,使用浏览器访问“http://localhost:8080/first-springmvc-demo/”,结果如下图。
2. 点击注册,跳转到注册页面,结果如下图。
3. 点击登陆,跳转到登陆页面,结果如下图。
通过这个案例,我们可以总结出 Spring MVC 主要的执行流程: