【从零开始学习SpringMVC】:生命周期与核心组件全面解析
立即解锁
发布时间: 2024-12-26 11:04:23 阅读量: 70 订阅数: 45 


Spring+SpringMVC+MyBatis可运行工程源码


# 摘要
SpringMVC是一个基于Java实现的轻量级Web框架,作为Spring框架的一部分,它遵循MVC设计模式,将Web层的职责分离。本文首先介绍SpringMVC的基本概念、与Spring框架的关系以及其主要特点。随后深入探讨了SpringMVC的生命周期,包括请求映射、处理器映射与执行、视图解析与响应返回等关键流程。接着对SpringMVC的核心组件,如@Controller、@RequestMapping注解,参数绑定与数据校验,以及异常处理和结果输出机制进行了详细分析。实践章节展示了如何构建SpringMVC应用、实现RESTful服务和集成第三方工具。进阶应用部分讨论了深入配置SpringMVC、创建自定义组件与拦截器,以及安全性控制和测试的策略。通过对SpringMVC的全面解析,本文旨在帮助开发者深入理解并应用这一流行的Web框架。
# 关键字
SpringMVC;MVC设计模式;生命周期;核心组件;RESTful服务;安全性控制
参考资源链接:[HSPICE模拟:深入理解蒙特卡罗分析](https://wenku.csdn.net/doc/4k0w2pz7dh?spm=1055.2635.3001.10343)
# 1. SpringMVC概述
## 1.1 SpringMVC简介
SpringMVC是Spring框架的一部分,用于构建Web应用程序。它提供了一个MVC(Model-View-Controller)架构的实现,用于分离业务逻辑和用户界面。借助SpringMVC,开发者可以更加轻松地处理HTTP请求,并将数据传递给模型和视图以生成响应。
## 1.2 SpringMVC与Spring的关系
SpringMVC与Spring核心框架紧密集成,共享许多相同的编程和配置模型,但它们各自有不同的职责。Spring负责企业级服务和通用的业务逻辑,而SpringMVC专注于Web层的处理,它允许使用Spring的依赖注入等特性,并通过Spring的事务管理来控制业务逻辑。
## 1.3 SpringMVC的主要特点
SpringMVC的主要特点包括清晰的分层结构、灵活的控制反转(IoC)和面向切面编程(AOP)支持,以及广泛的数据绑定、验证、格式化和文件上传功能。其灵活的URL路由、支持RESTful风格的Web服务,以及强大的异常处理机制都是其明显的优势。
接下来的文章将深入探讨SpringMVC的生命周期、核心组件、应用实践以及进阶应用,为IT专业人士提供全面的SpringMVC开发指南。
# 2. SpringMVC的生命周期详解
## 2.1 请求映射过程
### 2.1.1 DispatcherServlet的作用
在SpringMVC框架中,`DispatcherServlet` 是中央处理器的角色,它的主要职责是将用户请求分发给合适的控制器(Controller)进行处理。`DispatcherServlet` 作为前端控制器模式的实现,是SpringMVC架构的核心组件之一。
它主要通过配置文件来确定应用程序中其他组件的位置和角色,包括处理器映射(HandlerMapping)、视图解析器(ViewResolver)和控制器(Controller)等。当一个HTTP请求到达服务器,`DispatcherServlet` 接收到请求后,会根据配置的映射规则以及组件间的协作,将请求转发到正确的处理组件。
```java
// WebConfig.java
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
// 定义视图解析器
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setOrder(2);
return resolver;
}
// 定义静态资源处理
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
```
通过上述配置,我们可以看到如何在`WebConfig`配置类中配置`DispatcherServlet`,以及如何设置视图解析器和静态资源处理器。
### 2.1.2 请求分发机制
SpringMVC的请求分发机制是围绕`DispatcherServlet`展开的。当一个请求到达时,`DispatcherServlet`会使用其内部的处理器映射器(HandlerMapping)来确定请求应该由哪个控制器(Controller)来处理。
这里是一个简化的流程描述:
1. 用户发起请求,请求到达`DispatcherServlet`。
2. `DispatcherServlet`根据请求URL,调用相应的`HandlerMapping`来查找对应的处理器(即Controller中的方法)。
3. `HandlerMapping`返回一个处理器执行链,包括处理器对象、拦截器链等。
4. `DispatcherServlet`通过`HandlerAdapter`执行这个处理器。
5. 控制器处理完成后返回一个模型和视图(Model and View),`DispatcherServlet`调用相应的`ViewResolver`来解析这个视图。
## 2.2 处理器映射与执行
### 2.2.1 HandlerMapping的原理
`HandlerMapping`是SpringMVC中用于解析请求URL和对应控制器之间映射关系的组件。它根据一系列预定义的规则来决定哪个控制器应该处理当前的请求。
`DispatcherServlet`默认配置了多个`HandlerMapping`实现,例如`BeanNameUrlHandlerMapping`、`ControllerClassNameHandlerMapping`以及基于注解的`RequestMappingInfoHandlerMapping`。在处理请求时,`DispatcherServlet`会遍历这些`HandlerMapping`来找到合适的处理器。
```java
// 示例配置HandlerMapping
@Bean
public HandlerMapping handlerMapping() {
MapPathCompositeHandlerMapping mapping = new MapPathCompositeHandlerMapping();
// 配置映射关系,可以使用Java配置或XML配置
mapping.setMappings(Collections.singletonMap("/example/**", exampleController()));
return mapping;
}
```
在此代码中,我们定义了一个`HandlerMapping`,并将其与一个控制器实例关联起来,使得`DispatcherServlet`在处理以`/example/`开头的URL请求时,将它们映射到`exampleController`方法上处理。
### 2.2.2 HandlerAdapter的作用
`HandlerAdapter`是SpringMVC中的一个适配器,它负责调用实际的控制器方法,并将请求结果转换为`ModelAndView`对象。控制器方法可能返回多种类型的结果,比如简单的字符串、视图名称、模型和视图等。`HandlerAdapter`的作用是为`DispatcherServlet`提供一个统一的方式来处理这些不同类型的返回结果。
每个控制器方法都必须经过一个`HandlerAdapter`的适配处理,才能将结果返回给`DispatcherServlet`。`DispatcherServlet`并不直接与控制器方法交互,而是通过`HandlerAdapter`来间接完成交互。
```java
// 示例配置HandlerAdapter
@Bean
public HandlerAdapter handlerAdapter() {
SimpleControllerHandlerAdapter adapter = new SimpleControllerHandlerAdapter();
return adapter;
}
```
此配置创建了一个`SimpleControllerHandlerAdapter`实例,它能够处理实现了`Controller`接口的控制器。
## 2.3 视图解析与响应返回
### 2.3.1 视图解析器的配置和工作
视图解析器(ViewResolver)是SpringMVC中用于解析视图名称并返回视图对象的组件。其核心工作是将控制器返回的视图名称解析成实际的视图对象(如JSP、FreeMarker模板等)。`DispatcherServlet`在收到控制器的响应后,会通过视图解析器来渲染最终的视图,并将渲染结果返回给客户端。
视图解析器通过定义好的视图解析策略来工作。不同的视图解析器有不同的解析方式,例如内部资源视图解析器解析JSP文件,FreeMarker视图解析器解析FreeMarker模板文件。
```java
// 配置视图解析器
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setOrder(2);
return resolver;
}
```
在此代码中,我们配置了一个`InternalResourceViewResolver`,它会将控制器返回的视图名称解析为位于`/WEB-INF/views/`目录下的`.jsp`文件。
### 2.3.2 数据绑定和模型管理
数据绑定是指将HTTP请求中的数据绑定到控制器方法的参数上的过程。在SpringMVC中,数据绑定是自动完成的,开发者不需要手动从请求中提取参数。模型(Model)是存储视图所需数据的容器,通常与视图(View)一起返回,以便渲染出最终的响应。
```java
// 一个简单的控制器方法,展示数据绑定和模型管理
@Controller
public class ExampleController {
@RequestMapping("/example")
public String exampleHandler(Model model) {
// 添加数据到模型
model.addAttribute("message", "Hello World!");
return "example"; // 返回视图名称
}
}
```
在上述`ExampleController`中,我们添加了一个名为`message`的属性到模型中,并返回了一个视图名称。视图解析器将处理这个视图名称并渲染出相应的视图。
SpringMVC提供了强大的数据绑定和模型管理功能,它支持自动类型转换、格式化和数据校验等功能。例如,如果请求参数`id`是一个数字,那么它会自动转换为控制器方法中参数的整型类型。如果需要校验数据,可以使用`@Valid`注解结合`BindingResult`来实现。
通过本章节的介绍,我们了解了SpringMVC的请求映射、处理器映射与执行、视图解析和响应返回的整个生命周期。这些知识点将为深入理解SpringMVC框架打下坚实的基础,并帮助开发者构建高效、结构清晰的Web应用。
# 3. SpringMVC核心组件分析
## 3.1 控制器@Controller和@RequestMapping
在Web开发中,控制器(Controller)是处理用户请求并返回响应的组件。SpringMVC通过@Controller注解标识一个类作为控制器,并通过@RequestMapping注解来映射请求到处理方法上。
### 3.1.1 @Controller的作用和使用场景
@Controller注解是Spring的一个非检查性注解,用于告诉Spring框架该类是一个控制器,并将该类定义为一个Spring管理的bean。它本身并不具备任何业务逻辑,仅作为一个标识,用于与Spring容器中的其他类型(如Service、Repository)区分。
通常在MVC模式中,控制器负责接收请求并将请求转发给后端模型处理,然后将模型处理的结果返回给视图层进行展示。在SpringMVC中,控制器位于架构的最外层,是用户交互的入口点。
```java
@Controller
public class HelloController {
@RequestMapping("/hello")
public String sayHello() {
return "hello";
}
}
```
在上面的代码中,控制器类`HelloController`通过@Controller注解定义,并包含了一个处理方法`sayHello`。该方法通过@RequestMapping注解定义了其映射的URL为`/hello`。当用户访问该URL时,将返回视图名“hello”。
### 3.1.2 @RequestMapping注解的详细解析
@RequestMapping注解用于映射Web请求(例如HTTP GET、POST请求)到特定的处理程序。该注解可以被应用到类或方法级别,并支持使用多个URI模式映射到同一个处理方法。
- 类级别上使用@RequestMapping注解来定义一类请求的共通路径。
- 方法级别上使用@RequestMapping注解来定义特定请求的映射。
@RequestMapping还支持如下属性:
- `method`: 指定请求使用的HTTP方法,例如GET或POST。
- `value`或`path`: 指定映射的URL路径。
- `params`: 用于限制请求参数。
- `headers`: 用于限制请求头信息。
- `consumes`: 用于限定客户端可以发送的内容类型。
- `produces`: 用于指定服务端响应的内容类型。
```java
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/profile", method = RequestMethod.GET)
public String showUserProfile() {
return "user/profile";
}
}
```
在上述代码中,`UserController`类上的@RequestMapping注解定义了该控制器处理以`/user`为前缀的URL。而`showUserProfile`方法上的@RequestMapping注解则定义了一个GET请求的映射,指向`/profile`路径。当用户访问`/user/profile`时,该方法将被调用,并返回`user/profile`视图名称。
通过合理使用@RequestMapping的属性,开发者可以灵活地定义请求的处理逻辑,确保Web应用的可维护性和可扩展性。
### 3.1.3 控制器映射和请求分发的关联
在SpringMVC中,控制器映射和请求分发是紧密相关的。当SpringMVC容器接收到一个Web请求时,它会根据@RequestMapping注解的配置,将请求映射到正确的控制器类和方法上。然后,通过DispatcherServlet的请求分发机制,将请求分发给相应的控制器处理。
### 3.1.4 控制器映射的案例研究
让我们考虑一个具体的例子,其中涉及用户信息的获取和更新。
```java
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public String getUser(@PathVariable String userId, Model model) {
User user = userService.getUserById(userId);
model.addAttribute("user", user);
return "user/show";
}
@RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
@ResponseBody
public ResponseEntity<String> updateUser(@PathVariable String userId, @RequestBody User updatedUser) {
userService.updateUser(userId, updatedUser);
return ResponseEntity.ok("User updated successfully");
}
}
```
在这个例子中,我们有两个@RequestMapping注解的方法,分别处理获取用户信息和更新用户信息的请求。
- 第一个方法`getUser`通过路径变量`userId`获取用户信息,并将其添加到模型中,以便可以被视图层使用。
- 第二个方法`updateUser`接收一个包含更新信息的JSON对象,并更新数据库中相应的用户数据,然后返回一个包含成功消息的响应体。
这两个方法都映射到同一个URL路径`/user/{userId}`,但通过不同的HTTP方法(GET和PUT)区分开来。
通过分析SpringMVC的@RequestMapping和控制器映射机制,开发者可以创建灵活和可维护的Web应用程序。这些机制不仅支持RESTful风格的资源管理,还允许开发者以声明式的方式定义请求和处理逻辑,从而提高代码的清晰度和项目的整体质量。
# 4. SpringMVC应用实践
在这一章节中,我们将深入探讨SpringMVC的实战应用。我们将从基础的环境搭建和配置开始,逐步深入到RESTful服务的实现,以及第三方工具的集成和使用。这一章节是让SpringMVC从理论走向实践的关键步骤,是每个开发者在学习过程中都必须经历的阶段。通过实践,我们可以更好地理解和掌握SpringMVC的应用方式,以及如何将其应用在具体的项目中。
## 4.1 构建简单的SpringMVC应用
在这一节中,我们将从零开始,构建一个简单的SpringMVC应用。这将包括环境搭建、配置以及编写和运行我们的第一个“Hello World”程序。我们也将讨论如何设置开发环境,以便为接下来的开发工作打下坚实的基础。
### 4.1.1 环境搭建和配置
要开始构建SpringMVC应用,首先需要搭建好相应的开发环境。以下是基本的步骤,包括所需的依赖和配置文件设置。
1. **安装Java开发环境**:确保你的开发机器上安装了Java开发工具包(JDK),并配置好环境变量。
2. **配置Maven项目**:使用Maven作为项目管理工具,可以很容易地管理项目依赖。创建一个`pom.xml`文件并添加SpringMVC依赖,例如:
```xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.10</version>
</dependency>
<!-- 其他相关依赖 -->
</dependencies>
```
3. **初始化DispatcherServlet**:在`web.xml`中配置SpringMVC的入口点`DispatcherServlet`,并设置相应的初始化参数:
```xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
4. **SpringMVC配置文件**:创建Spring配置文件`spring-dispatcher-servlet.xml`,配置视图解析器、组件扫描等:
```xml
<beans ...>
<context:component-scan base-package="com.example" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
```
通过以上步骤,我们的开发环境和基础配置就已经搭建好了。接下来,我们就可以开始编写我们的第一个SpringMVC程序。
### 4.1.2 创建第一个Hello World程序
创建一个简单的SpringMVC程序主要涉及编写控制器、视图以及配置映射关系。以下是详细的步骤:
1. **编写控制器Controller**:创建一个名为`HelloController`的控制器类,并使用`@Controller`和`@RequestMapping`注解。例如:
```java
@Controller
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String sayHello(Model model) {
model.addAttribute("message", "Hello World!");
return "hello"; // 返回逻辑视图名
}
}
```
2. **创建JSP视图**:在`/WEB-INF/views/`目录下创建一个名为`hello.jsp`的视图文件,并在文件中展示从控制器传递的消息:
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>${message}</h2>
</body>
</html>
```
3. **配置视图解析器**:如果使用XML配置,需要在`spring-dispatcher-servlet.xml`中配置视图解析器,如前面配置文件示例所示。
通过以上步骤,当用户访问`/hello` URL时,SpringMVC会调用`HelloController`中的`sayHello`方法,并将返回的结果显示在`hello.jsp`视图中。
在本小节中,我们已经了解了如何设置SpringMVC开发环境,以及如何创建一个简单的Hello World程序。这为我们在下一小节中实现RESTful服务打下了基础。
## 4.2 实现RESTful服务
RESTful服务是一种遵循REST架构风格的服务。在本小节中,我们将探讨如何使用SpringMVC来实现RESTful服务。这包括了解RESTful设计原则以及使用SpringMVC的一些最佳实践。
### 4.2.1 RESTful设计原则
RESTful是一种基于HTTP协议的轻量级Web服务架构风格。它依赖于以下几个核心原则:
- **无状态通信**:服务端不保存客户端的状态。
- **统一接口**:通过HTTP协议提供的方法(如GET、POST、PUT、DELETE)来执行CRUD操作。
- **可缓存**:响应数据应是可缓存的。
- **客户端-服务器架构**:清晰地分离用户界面和数据存储。
- **分层系统**:可以通过分层来改进可扩展性和安全性。
### 4.2.2 使用SpringMVC实现RESTful服务
使用SpringMVC实现RESTful服务涉及以下几个关键点:
1. **使用`@RestController`注解**:这个注解用于创建RESTful控制器,它会自动将返回的对象转换为JSON或XML格式。
```java
@RestController
public class ProductRestController {
// ...
}
```
2. **使用HTTP方法注解**:在控制器方法上使用`@GetMapping`、`@PostMapping`等注解来定义不同的HTTP请求映射。
```java
@RestController
public class ProductRestController {
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable("id") Long id) {
// 返回商品信息
}
@PostMapping("/products")
public void addProduct(@RequestBody Product product) {
// 添加商品
}
}
```
3. **使用`@PathVariable`和`@RequestBody`注解**:分别用于绑定URL路径变量和请求体到方法参数。
```java
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable("id") Long id) {
// ...
}
```
在本小节中,我们介绍了RESTful设计原则以及使用SpringMVC实现RESTful服务的具体方法。接下来,我们将探讨如何集成和使用第三方工具来丰富我们的应用功能。
## 4.3 集成和使用第三方工具
在开发过程中,经常需要与各种第三方工具和库集成。在本小节中,我们将学习如何将SpringMVC应用与日志系统Log4j以及MyBatis进行集成。
### 4.3.1 整合日志系统Log4j
Log4j是一个功能强大的日志记录库。要将它与SpringMVC应用集成,我们需要做以下几步:
1. **添加Log4j依赖**:在`pom.xml`文件中添加Log4j的依赖。
```xml
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
```
2. **配置Log4j**:在项目中创建一个`log4j2.xml`文件,用于配置日志记录的行为。
```xml
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.example" level="debug" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<Root level="error">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
```
3. **使用Log4j进行日志记录**:在代码中注入`Logger`对象,并使用它记录日志。
```java
@Controller
public class MyController {
private static final Logger logger = LogManager.getLogger(MyController.class);
@RequestMapping("/test")
public String testLogging() {
logger.info("This is an info message.");
logger.debug("This is a debug message.");
return "view_name";
}
}
```
### 4.3.2 集成MyBatis和数据库交互
MyBatis是一个持久层框架,它提供了一个对象关系映射(ORM)的解决方案。下面是如何在SpringMVC应用中集成MyBatis的步骤:
1. **添加MyBatis依赖**:在`pom.xml`文件中添加MyBatis的依赖以及数据库连接池依赖,如HikariCP。
```xml
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
```
2. **配置数据源和MyBatis**:在Spring配置文件中配置数据源和MyBatis的扫描路径。
```xml
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<!-- 数据库配置 -->
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.example.model"/>
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
</bean>
```
3. **编写Mapper接口和XML文件**:创建Mapper接口和对应的XML文件来定义SQL操作。
```java
public interface UserMapper {
User selectUser(int id);
}
```
```xml
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUser" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
```
4. **在服务层使用Mapper**:在服务层接口中注入Mapper接口,然后在实现类中使用它。
```java
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(int id) {
return userMapper.selectUser(id);
}
}
```
在本小节中,我们了解了如何将SpringMVC与日志系统Log4j以及MyBatis进行集成。通过这些集成,我们可以增强应用的日志记录功能,同时提供与数据库的交互能力。在下一章节,我们将进一步探索SpringMVC的进阶应用。
# 5. SpringMVC进阶应用
随着Web应用的复杂度不断提升,对SpringMVC框架的深入了解变得尤为关键。在本章中,我们将深入探讨SpringMVC配置的细节,如何创建和使用自定义组件及拦截器,以及如何实现应用的安全性和测试。
## 5.1 深入理解SpringMVC的配置
### 5.1.1 配置文件的加载机制
SpringMVC的配置文件加载机制通常遵循标准的Spring Bean配置加载流程。在了解其加载机制之前,首先需要明白配置文件可以在哪里放置,并且它们是如何被识别的。
```xml
<!-- 一个典型的web.xml配置示例 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
```
在`web.xml`中,`ContextLoaderListener`用于加载Spring的根上下文。`contextConfigLocation`指定了Spring配置文件的位置,如果未指定,则默认查找`WEB-INF/applicationContext.xml`。
SpringMVC的配置文件通常是`spring-dispatcher-servlet.xml`,它会在`DispatcherServlet`初始化时加载。
```java
// 在DispatcherServlet初始化时自动加载配置文件
public class DispatcherServlet extends FrameworkServlet {
// ...
@Override
protected void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
} catch (ServletException | RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
(System.currentTimeMillis() - startTime) + " ms");
}
}
// ...
}
```
### 5.1.2 高级配置技巧
在实际开发中,开发者往往需要对SpringMVC进行高级配置以满足特定需求。这包括但不限于:
- 视图解析器的自定义配置
- 静态资源处理
- 异常处理和拦截器配置
下面是一个自定义视图解析器的配置示例:
```xml
<!-- 自定义视图解析器配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="order" value="1"/>
</bean>
```
在上述配置中,我们定义了一个`InternalResourceViewResolver`,指定了JSP文件的存放位置和扩展名。`order`属性定义了该解析器在解析链中的优先级。
## 5.2 自定义组件与拦截器
### 5.2.1 创建自定义的拦截器
拦截器为SpringMVC提供了强大的扩展性。自定义拦截器可以实现`HandlerInterceptor`接口,该接口包含三个方法:`preHandle`, `postHandle`和`afterCompletion`。
```java
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在请求处理之前进行调用(Controller方法调用之前)
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 请求处理之后进行调用,但在视图被渲染之前(Controller方法调用之后)
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要用于进行资源清理工作)
}
}
```
### 5.2.2 拦截器的工作流程
拦截器的工作流程涉及`DispatcherServlet`的处理流程。当一个请求到达时,`DispatcherServlet`会询问`HandlerMapping`应该使用哪个`HandlerInterceptor`链。
上图展示了拦截器在请求处理流程中的位置和作用。拦截器可以在请求到达控制器之前和之后进行预处理和后处理,以及在请求完全结束后进行资源清理。
## 5.3 安全性控制和测试
### 5.3.1 Spring Security简介
Spring Security提供了全面的、可高度定制的安全性解决方案。它是一个功能强大且可高度定制的身份验证和访问控制框架。
### 5.3.2 集成Spring Security进行安全控制
要集成Spring Security,通常需要添加依赖,并配置`spring-security.xml`文件。以下是一个简单的安全配置示例:
```xml
<!-- spring-security.xml配置 -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_ADMIN" />
<user name="user" password="user" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
```
### 5.3.3 单元测试和Mock测试方法
在进行单元测试时,我们通常使用Mock对象来模拟依赖的部分,比如数据库操作或外部服务调用。Spring提供了`@RunWith(SpringJUnit4ClassRunner.class)`注解来集成Spring的测试环境。
```java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring-dispatcher-servlet.xml"})
@WebAppConfiguration
public class SampleControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void testSomething() throws Exception {
this.mockMvc.perform(get("/somePath"))
.andExpect(status().isOk())
.andExpect(view().name("someView"));
}
}
```
在上述测试代码中,我们使用`MockMvc`模拟请求并验证响应状态和视图名称。这样的单元测试能够帮助开发者快速验证Web层的功能。
以上就是对SpringMVC进阶应用的探讨。掌握这些知识点,将帮助你在实际开发中更有效地利用SpringMVC框架,提高开发效率和代码质量。
0
0
复制全文
相关推荐









