第十章 初识Spring MVC框架
JSP Model2架构模型是一种将页面显示、流程控制和业务逻辑分离的Web应用程序架构模型,采用JSP、Servlet和JavaBean技术实现。但是,它将通用逻辑以硬编码的方式实现,每次开发新的Web应用程序时都需要重新编写Servlet控制器的URL分析代码以及流程控制等Web层通用逻辑代码。为了解决这个问题,一些基于JSP Model2架构模型的Web MVC应用框架应运而生。
10.1 Spring MVC介绍
10.1.1 Spring MVC 概述
在Java EE开发中,通常采用三层架构模型,包括表现层、业务层和持久层。表现层负责接收客户端的请求并向客户端响应结果,业务层负责业务逻辑处理与项目需求相关,持久层负责与数据库交互,对数据库的数据进行增删改查。
Spring MVC是一种基于Servlet API构建的Web框架,是Spring框架的一个模块,通常被称为SpringMVC。它提供了对MVC模式的全面支持,可以将表现层进行解耦,简化了表现层的实现。Spring MVC是一个请求驱动的框架,用于接收客户端的请求并进行响应,作用于三层架构中的表现层。
在三层架构中,Spring MVC的位置如图所示。它包含了控制器和视图,控制器接收客户端的请求后对请求数据进行解析和封装,接着将请求交给业务层处理。业务层会对请求进行处理,最后将处理结果返回给表现层。表现层接收到业务层的处理结果后,再由视图对处理结果进行渲染,渲染完成后响应给客户端。这样,Spring MVC框架可以将表现层、业务层和持久层分别负责不同的任务,使得Web应用程序的开发更加高效和可维护。
10.1.2 Spring MVC特点
Spring MVC能够成为当前主流的MVC框架之一,主要得益于以下几个特点:
-
SpringMVC是Spring框架的后续产品,可以方便地使用Spring框架所提供的其他功能。
-
SpringMVC使用简单,很容易设计出干净简洁的Web层。
-
SpringMVC支持各种请求资源的映射策略。
-
SpringMVC具有非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API。
-
SpringMVC支持国际化,可以根据用户区域显示多国语言。
-
SpringMVC支持多种视图技术,支持JSP、Velocity和FreeMarker等视图技术。
-
SpringMVC灵活性强,易扩展。
除了上述特点外,Spring MVC还具有以下优势:
- 易于集成其他框架,如Spring Security、Spring Boot等。
- 支持AOP功能,可以方便地实现事务管理、日志记录等横向切面的功能。
- 提供拦截器机制,可以在请求处理前或处理后进行拦截器的处理,实现一些通用的业务逻辑,如权限验证、日志记录等。
- 提供全局异常处理机制,可以方便地处理各种异常,避免因异常导致应用程序崩溃。
- 提供可定制的选项,如配置文件的加载位置、视图解析器的选择、异常处理方式等,可以根据实际需求进行灵活配置。
- 易于使用的RESTful支持,可以通过注解的方式实现,使得开发人员可以更加方便地实现RESTful风格的API。
- 提供Mock对象和测试框架,使得开发人员可以方便地对控制器层进行单元测试和集成测试。
综上所述,Spring MVC框架的易用性、可扩展性、灵活性和可定制性,使其成为当前主流的Web框架之一。
10.2 Spring MVC入门程序
1. 创建项目
①创建maven项目
②添加web模块
③添加web.xml
④设置web资源目录
2. 引入Maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- 模型版本 -->
<groupId>com.itheima</groupId> <!-- 项目所属的组织ID -->
<artifactId>chapter10</artifactId> <!-- 项目的名称 -->
<version>1.0-SNAPSHOT</version> <!-- 版本号 -->
<packaging>war</packaging> <!-- 打包方式 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 源文件编码 -->
<maven.compiler.source>1.8</maven.compiler.source> <!-- 源码编译版本 -->
<maven.compiler.target>1.8</maven.compiler.target> <!-- 目标字节码版本 -->
</properties>
<dependencies>
<!-- Spring 核心包的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- Spring MVC 的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- Servlet 的依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP 的依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Tomcat 插件的配置 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port> <!-- Tomcat 端口号 -->
<path>/chapter10</path> <!-- 应用访问路径 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
3. 配置前端控制器
在使用 Spring MVC 框架时,前端控制器是一个必不可少的组件,它负责拦截客户端的请求,并进行转发到相应的处理器(Controller)进行处理。
Spring MVC 的前端控制器实际上就是一个 Servlet,因此我们可以在项目的 web.xml 文件中进行配置。具体来说,我们需要在 web.xml 文件中定义一个 Servlet,将其映射到指定的 URL 地址,并设置相关的初始化参数,比如 Spring MVC 配置文件的位置等。
这样,在客户端发起请求时,Servlet 容器会将请求转发给前端控制器,由前端控制器进行处理,并根据配置将请求转发给相应的处理器进行后续的逻辑处理。
需要注意的是,虽然在 web.xml 文件中进行配置是一种常见的方式,但也可以使用其他方式,比如使用 Java 配置或注解的方式来配置前端控制器。
- web.xml示例
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义 Web 应用的部署描述文件,使用 JavaEE 标准的 XML 格式 -->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- 配置 Spring MVC 的前端控制器 -->
<servlet>
<!-- 定义 Servlet 的名称 -->
<servlet-name>DispatcherServlet</servlet-name>
<!-- 定义 Servlet 的实现类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置初始化参数,用于读取 Spring MVC 的配置文件 -->
<init-param>
<!-- 指定初始化参数的名称 -->
<param-name>contextConfigLocation</param-name>
<!-- 指定初始化参数的值,即 Spring MVC 配置文件的位置 -->
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 应用加载时创建 Servlet 实例 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置 Servlet 的映射 -->
<servlet-mapping>
<!-- 指定 Servlet 的名称,必须与上面定义的名称一致 -->
<servlet-name>DispatcherServlet</servlet-name>
<!-- 指定 Servlet 处理的 URL 映射,这里表示处理所有的请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4. 配置处理器映射信息和视图解析器
在项目的resources文件夹下创建 Spring MVC 的配置文件spring-mvc.xml,用于配置处理器射信息和视图解析器:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置 Spring MVC 要扫描的包 -->
<context:component-scan base-package="com.itheima.controller" />
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" /> <!-- JSP 文件的路径前缀 -->
<property name="suffix" value=".jsp" /> <!-- JSP 文件的后缀 -->
</bean>
</beans>
- beans 标签是 Spring 配置文件的根元素,用于包含所有的配置信息。
- context:component-scan 标签用于配置 Spring MVC 要扫描的包,该配置指定了要扫描的包的基础路径为 “com.itheima.controller”,表示该路径下的所有类都会被 Spring MVC 扫描并注册为控制器。
- InternalResourceViewResolver 是 Spring MVC 的一个视图解析器,用于将逻辑视图名解析为物理视图名(即 JSP 文件的路径)。在该配置中,通过 bean 标签定义了一个名为 “InternalResourceViewResolver” 的视图解析器,其实现类为 “org.springframework.web.servlet.view.InternalResourceViewResolver”。该视图解析器的 prefix 属性被设置为 “/WEB-INF/pages/”,表示 JSP 文件的路径前缀为 “/WEB-INF/pages/”,suffix 属性被设置为 “.jsp”,表示 JSP 文件的后缀为 “.jsp”。
5. 创建处理器
在项目的 src/main/java 目录下创建一个路径为 com.itheima.controller 的包。在包中创建处理器 FirstController类,用于处理客户端的请求并指定响应时转跳的页面。
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 设置当前类为处理器类
@Controller
public class FirstController {
// 设定当前方法的访问映射地址
@RequestMapping("/firstController")
// 设置当前方法返回值类型为 String,用于指定请求完成后跳转的页面
public String sayHello() {
System.out.println("访问到 FirstController!");
// 设定具体跳转的页面
return "success";
}
}
- Controller 注解用于将当前类标识为 Spring MVC 的控制器类。
- RequestMapping 注解用于将 HTTP 请求映射到处理器类或处理器方法上。
- FirstController 类中的 sayHello() 方法使用 RequestMapping 注解将 HTTP 请求映射到 “/firstController” 路径,当客户端访问该路径时,该方法会被调用。
- sayHello() 方法返回一个字符串 “success”,该字符串将被解析为一个视图名,Spring MVC 会将其解析为一个 JSP 文件的路径。在本例中,因为在配置文件中已经设置了视图解析器的前缀和后缀,所以最终返回的视图路径为 “/WEB-INF/pages/success.jsp”。
6. 创建视图(View)页面
在项目的WEB-INF文件夹下创建名称为 pages 的文件夹并在 pages 文件夹下创建名称为 success 的JSP文件,用于对客户端请求进行处理后的视图进行展示。
<html>
<head>
<title>Spring MVC FirstController!</title>
</head>
<body>
<h2>Spring MVC FirstController!</h2>
</body>
</html>
该 JSP 文件使用 HTML 标签和文本来展示处理客户端请求后的视图。在本例中,该 JSP 文件会被视图解析器解析为 “/WEB-INF/pages/success.jsp”,并由 Spring MVC 返回给客户端。
7.启动项目并测试应用
配好tomcat,启动。
在浏览器访问:http://localhost:8080/chapter10/firstController
10.3 Spring MVC工作原理
Spring MVC 的三大组件分别是:
-
HandlerMapping(处理器映射器):负责根据客户端请求的 URL 找到对应的处理器 Handler。它可以理解为一个 Map<URL, Handler>,根据不同的映射方式提供不同的映射器实现。
-
HandlerAdapter(处理器适配器):根据 HandlerMapping 找到的 Handler 信息,去执行相关的 Handler 的业务逻辑。由于不同的处理器映射器映射出来的 Handler 对象是不一样的,因此不同的映射由不同的适配器来负责解析。
-
ViewResolver(视图解析器):进行视图解析时,首先将逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象返回。ViewResolver 的作用是根据视图逻辑名找到对应的视图对象,用于最终将数据渲染到页面上。
-
用户通过浏览器向服务器发送请求,请求会被 Spring MVC 的前端控制器
DispatcherServlet
拦截。 -
DispatcherServlet
拦截到请求后,会调用处理器映射器HandlerMapping
。 -
处理器映射器根据请求 URL 找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)并返回给
DispatcherServlet
。 -
DispatcherServlet
会通过返回信息选择合适的处理器适配器HandlerAdapter
。 -
HandlerAdapter
会调用并执行处理器(也就是Controller
类),完成业务逻辑处理。 -
Controller
执行完成后,会返回一个ModelAndView
对象,该对象中会包含视图名或包含模型和视图名。 -
HandlerAdapter
将ModelAndView
对象返回给DispatcherServlet
。 -
前端控制器请求视图解析器
ViewResolver
根据逻辑视图名解析真正的视图。 -
ViewResolver
解析后,会向DispatcherServlet
中返回具体的视图View
对象。 -
DispatcherServlet
对View
进行渲染,即将模型数据填充至视图中。 -
前端控制器向用户响应结果。
在上述执行过程中,DispatcherServlet
、HandlerMapping
、HandlerAdapter
和 ViewResolver
对象的工作是框架内部执行的,开发人员只需要配置前端控制器 DispatcherServlet
完成 Controller
中的业务处理并在视图中展示相应信息即可。