当前位置: 首页 > web >正文

SSM从入门到实战:3.1 SpringMVC框架概述与工作原理

👋 大家好,我是 阿问学长!专注于分享优质开源项目解析、毕业设计项目指导支持、幼小初高教辅资料推荐等,欢迎关注交流!🚀

SpringMVC框架概述与工作原理

📖 本文概述

本文是SSM框架系列SpringMVC基础篇的第一篇,将深入介绍SpringMVC框架的核心概念、设计理念和工作原理。通过理论分析和代码示例,帮助读者建立对SpringMVC框架的全面认知。

🎯 学习目标

  • 理解SpringMVC框架的设计理念和核心特性
  • 掌握SpringMVC的工作原理和执行流程
  • 学会SpringMVC的基本配置和使用
  • 了解MVC设计模式在Web开发中的应用
  • 能够搭建基本的SpringMVC应用

1. SpringMVC框架概述

1.1 什么是SpringMVC

SpringMVC是Spring框架的一个模块,是一个基于MVC设计模式的Web框架。它提供了一种分离式的方法来开发Web应用,将业务逻辑、数据、界面显示分离,使代码更加清晰和易于维护。

1.2 SpringMVC的特点

/*** SpringMVC特点演示* 对比传统Servlet开发和SpringMVC开发*/// 传统Servlet方式
@WebServlet("/user")
public class UserServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String action = request.getParameter("action");if ("list".equals(action)) {// 查询用户列表List<User> users = userService.findAll();request.setAttribute("users", users);request.getRequestDispatcher("/WEB-INF/views/user/list.jsp").forward(request, response);} else if ("detail".equals(action)) {// 查询用户详情String id = request.getParameter("id");User user = userService.findById(Long.valueOf(id));request.setAttribute("user", user);request.getRequestDispatcher("/WEB-INF/views/user/detail.jsp").forward(request, response);}// 更多if-else判断...}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 处理POST请求...}
}// SpringMVC方式
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/list")public String list(Model model) {List<User> users = userService.findAll();model.addAttribute("users", users);return "user/list"; // 返回视图名称}@GetMapping("/detail/{id}")public String detail(@PathVariable Long id, Model model) {User user = userService.findById(id);model.addAttribute("user", user);return "user/detail";}@PostMapping("/save")public String save(@ModelAttribute User user) {userService.save(user);return "redirect:/user/list";}
}

SpringMVC的主要特点:

  1. 清晰的角色分工:Controller、Model、View各司其职
  2. 灵活的配置:支持注解和XML配置
  3. 强大的数据绑定:自动将请求参数绑定到Java对象
  4. 丰富的视图技术:支持JSP、Thymeleaf、FreeMarker等
  5. RESTful支持:天然支持RESTful风格的URL
  6. 拦截器机制:提供强大的拦截器功能
  7. 异常处理:统一的异常处理机制

1.3 MVC设计模式

MVC(Model-View-Controller)是一种软件设计模式,将应用程序分为三个核心组件:

/*** MVC模式在SpringMVC中的体现*/// Model(模型)- 数据和业务逻辑
@Entity
public class User {private Long id;private String username;private String email;private String phone;private Date createTime;// 构造方法public User() {}public User(String username, String email) {this.username = username;this.email = email;this.createTime = new Date();}// getter/setter方法public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }
}@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public List<User> findAll() {return userRepository.findAll();}public User findById(Long id) {return userRepository.findById(id).orElse(null);}public User save(User user) {if (user.getId() == null) {user.setCreateTime(new Date());}return userRepository.save(user);}public void deleteById(Long id) {userRepository.deleteById(id);}
}// View(视图)- 用户界面
// user/list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head><title>用户列表</title><style>table { border-collapse: collapse; width: 100%; }th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }th { background-color: #f2f2f2; }</style>
</head>
<body><h1>用户管理系统</h1><a href="${pageContext.request.contextPath}/user/add">添加用户</a><table><thead><tr><th>ID</th><th>用户名</th><th>邮箱</th><th>电话</th><th>创建时间</th><th>操作</th></tr></thead><tbody><c:forEach items="${users}" var="user"><tr><td>${user.id}</td><td>${user.username}</td><td>${user.email}</td><td>${user.phone}</td><td><fmt:formatDate value="${user.createTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td><td><a href="${pageContext.request.contextPath}/user/detail/${user.id}">查看</a><a href="${pageContext.request.contextPath}/user/edit/${user.id}">编辑</a><a href="${pageContext.request.contextPath}/user/delete/${user.id}"onclick="return confirm('确定删除吗?')">删除</a></td></tr></c:forEach></tbody></table>
</body>
</html>// Controller(控制器)- 处理用户输入和协调Model、View
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/list")public String list(Model model) {// 1. 调用Model获取数据List<User> users = userService.findAll();// 2. 将数据传递给Viewmodel.addAttribute("users", users);// 3. 返回View名称return "user/list";}@GetMapping("/detail/{id}")public String detail(@PathVariable Long id, Model model) {User user = userService.findById(id);model.addAttribute("user", user);return "user/detail";}@GetMapping("/add")public String showAddForm(Model model) {model.addAttribute("user", new User());return "user/add";}@PostMapping("/add")public String add(@ModelAttribute User user, RedirectAttributes redirectAttributes) {userService.save(user);redirectAttributes.addFlashAttribute("message", "用户添加成功");return "redirect:/user/list";}
}

2. SpringMVC工作原理

2.1 SpringMVC架构图

┌─────────────┐    ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   浏览器     │───▶│ DispatcherServlet│───▶│ HandlerMapping  │───▶│   Controller    │
│  (Client)   │    │   (前端控制器)    │    │  (处理器映射器)   │    │   (控制器)      │
└─────────────┘    └─────────────────┘    └─────────────────┘    └─────────────────┘▲                      │                      ▲                      ││                      ▼                      │                      ▼
┌─────────────┐    ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   响应结果   │◀───│      View       │◀───│  ViewResolver   │◀───│  ModelAndView   │
│  (Response) │    │     (视图)      │    │  (视图解析器)    │    │  (模型和视图)    │
└─────────────┘    └─────────────────┘    └─────────────────┘    └─────────────────┘详细流程:
1. 用户发送请求至前端控制器DispatcherServlet
2. DispatcherServlet收到请求调用HandlerMapping处理器映射器
3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找)
4. 返回给DispatcherServlet
5. DispatcherServlet调用HandlerAdapter处理器适配器
6. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
7. Controller执行完成返回ModelAndView
8. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
9. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
10. ViewReslover解析后返回具体View
11. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
12. DispatcherServlet响应用户

2.2 核心组件详解

/*** SpringMVC核心组件说明*/
public class SpringMVCComponents {/*** DispatcherServlet - 前端控制器* SpringMVC的核心,负责接收请求并协调各个组件** 主要职责:* 1. 接收HTTP请求* 2. 根据请求信息查找对应的Handler* 3. 调用Handler处理请求* 4. 处理Handler返回的ModelAndView* 5. 渲染视图并返回响应*/private DispatcherServlet dispatcherServlet;/*** HandlerMapping - 处理器映射器* 负责根据请求URL找到对应的Handler(Controller)** 常用实现:* - RequestMappingHandlerMapping:基于@RequestMapping注解* - BeanNameUrlHandlerMapping:基于Bean名称* - SimpleUrlHandlerMapping:基于URL配置*/private HandlerMapping handlerMapping;/*** HandlerAdapter - 处理器适配器* 负责调用具体的Handler方法** 常用实现:* - RequestMappingHandlerAdapter:处理@RequestMapping注解的方法* - HttpRequestHandlerAdapter:处理HttpRequestHandler* - SimpleControllerHandlerAdapter:处理Controller接口*/private HandlerAdapter handlerAdapter;/*** Controller - 控制器* 处理具体的业务逻辑** 实现方式:* - 基于注解的Controller(推荐)* - 实现Controller接口* - 实现HttpRequestHandler接口*/private Controller controller;/*** ModelAndView - 模型和视图* 封装了模型数据和视图信息** 包含内容:* - Model:存储业务数据* - View:视图名称或View对象* - Status:HTTP状态码*/private ModelAndView modelAndView;/*** ViewResolver - 视图解析器* 负责解析视图名称,找到具体的视图** 常用实现:* - InternalResourceViewResolver:解析JSP视图* - ThymeleafViewResolver:解析Thymeleaf视图* - FreeMarkerViewResolver:解析FreeMarker视图*/private ViewResolver viewResolver;/*** View - 视图* 负责渲染模型数据,生成响应** 常用实现:* - JstlView:JSP视图* - ThymeleafView:Thymeleaf视图* - RedirectView:重定向视图* - JsonView:JSON视图*/private View view;
}

2.3 SpringMVC执行流程

/*** SpringMVC请求处理流程详解* 以用户访问 /user/list 为例*/
public class SpringMVCWorkflow {/*** 完整的请求处理流程演示*/public void processRequest() {// 1. 用户发送请求到DispatcherServlet// 浏览器发送:GET http://localhost:8080/app/user/list// 2. DispatcherServlet调用HandlerMapping查找Handler// RequestMappingHandlerMapping根据URL和HTTP方法找到:// UserController.list()方法(标注了@GetMapping("/list"))// 3. DispatcherServlet调用HandlerAdapter执行Handler// RequestMappingHandlerAdapter负责:// - 解析方法参数(如Model model)// - 调用UserController.list(model)方法// - 处理方法返回值// 4. Controller执行业务逻辑,返回ModelAndView// UserController.list()执行:// - 调用userService.findAll()获取数据// - 将数据添加到model中:model.addAttribute("users", users)// - 返回视图名称:"user/list"// 5. DispatcherServlet将ModelAndView传给ViewResolver// InternalResourceViewResolver解析:// "user/list" → "/WEB-INF/views/user/list.jsp"// 6. DispatcherServlet根据View进行渲染// JstlView渲染:// - 将model数据设置为request属性// - 转发到JSP页面进行渲染// - JSP引擎生成最终HTML// 7. 返回响应给用户// HTTP响应包含渲染后的HTML页面// 浏览器接收并显示用户列表页面}
}

2.4 详细执行流程图

/*** SpringMVC详细执行流程示例* 展示每个步骤的具体操作*/
@Component
public class DetailedWorkflowExample {public void demonstrateWorkflow() {/** 步骤1:客户端发送请求* 请求信息:* - URL: http://localhost:8080/app/user/list* - Method: GET* - Headers: Accept: text/html, User-Agent: Mozilla/5.0...*//** 步骤2:DispatcherServlet接收请求* DispatcherServlet执行:* - 解析请求URL:/user/list* - 确定请求方法:GET* - 获取请求参数和头信息* - 初始化处理上下文*//** 步骤3:查找Handler* HandlerMapping查找过程:* - 遍历所有注册的HandlerMapping* - RequestMappingHandlerMapping匹配URL模式* - 找到匹配的Handler:UserController.list()* - 返回HandlerExecutionChain(包含Handler和拦截器)*//** 步骤4:执行拦截器的preHandle方法* 拦截器执行:* - 按顺序执行所有拦截器的preHandle方法* - 如果任一拦截器返回false,则终止处理* - 可以进行权限检查、日志记录等*//** 步骤5:HandlerAdapter调用Handler* RequestMappingHandlerAdapter执行:* - 解析方法参数:Model model* - 创建参数实例:new ExtendedModelMap()* - 反射调用:UserController.list(model)* - 处理返回值:"user/list"*//** 步骤6:Controller执行业务逻辑* UserController.list()执行:* - 注入依赖:@Autowired UserService userService* - 调用业务方法:List<User> users = userService.findAll()* - 设置模型数据:model.addAttribute("users", users)* - 返回视图名称:return "user/list"*//** 步骤7:执行拦截器的postHandle方法* 拦截器执行:* - 按逆序执行所有拦截器的postHandle方法* - 可以修改ModelAndView* - 进行后置处理*//** 步骤8:ViewResolver解析视图* InternalResourceViewResolver执行:* - 拼接视图路径:prefix + viewName + suffix* - "/WEB-INF/views/" + "user/list" + ".jsp"* - 创建JstlView对象* - 设置视图属性*//** 步骤9:View渲染* JstlView渲染过程:* - 将Model数据设置为request属性* - request.setAttribute("users", userList)* - 转发到JSP:request.getRequestDispatcher().forward()* - JSP引擎解析并生成HTML*//** 步骤10:执行拦截器的afterCompletion方法* 拦截器执行:* - 按逆序执行所有拦截器的afterCompletion方法* - 进行清理工作* - 记录处理时间等*//** 步骤11:返回响应给客户端* HTTP响应:* - Status: 200 OK* - Content-Type: text/html;charset=UTF-8* - Body: 渲染后的HTML内容* - 浏览器接收并显示页面*/}
}

3. SpringMVC环境搭建

3.1 项目结构

springmvc-demo/
├── pom.xml                                    # Maven配置文件
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/
│   │   │       ├── controller/                # 控制器层
│   │   │       │   ├── HelloController.java
│   │   │       │   └── UserController.java
│   │   │       ├── service/                   # 业务逻辑层
│   │   │       │   ├── UserService.java
│   │   │       │   └── impl/
│   │   │       │       └── UserServiceImpl.java
│   │   │       ├── entity/                    # 实体类
│   │   │       │   └── User.java
│   │   │       ├── config/                    # 配置类
│   │   │       │   └── WebConfig.java
│   │   │       └── interceptor/               # 拦截器
│   │   │           └── LoggingInterceptor.java
│   │   ├── resources/
│   │   │   ├── spring/                        # Spring配置文件
│   │   │   │   ├── applicationContext.xml
│   │   │   │   └── springmvc-config.xml
│   │   │   └── logback.xml                    # 日志配置
│   │   └── webapp/
│   │       ├── WEB-INF/
│   │       │   ├── web.xml                    # Web应用配置
│   │       │   └── views/                     # JSP视图文件
│   │       │       ├── hello.jsp
│   │       │       ├── user/
│   │       │       │   ├── list.jsp
│   │       │       │   ├── detail.jsp
│   │       │       │   ├── add.jsp
│   │       │       │   └── edit.jsp
│   │       │       └── common/
│   │       │           ├── header.jsp
│   │       │           └── footer.jsp
│   │       ├── static/                        # 静态资源
│   │       │   ├── css/
│   │       │   │   └── style.css
│   │       │   ├── js/
│   │       │   │   └── main.js
│   │       │   └── images/
│   │       └── index.jsp                      # 首页
│   └── test/
│       └── java/
│           └── com/example/
│               └── controller/
│                   └── UserControllerTest.java
└── README.md

3.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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>springmvc-demo</artifactId><version>1.0.0</version><packaging>war</packaging><name>SpringMVC Demo Project</name><description>SpringMVC框架基础示例项目</description><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- 版本管理 --><spring.version>5.3.21</spring.version><servlet.version>4.0.1</servlet.version><jsp.version>2.3.3</jsp.version><jstl.version>1.2</jstl.version><jackson.version>2.13.3</jackson.version><slf4j.version>1.7.36</slf4j.version><logback.version>1.2.12</logback.version><junit.version>4.13.2</junit.version></properties><dependencies><!-- Spring MVC核心依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!-- Spring Context支持 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- Servlet API --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>${servlet.version}</version><scope>provided</scope></dependency><!-- JSP API --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>${jsp.version}</version><scope>provided</scope></dependency><!-- JSTL标签库 --><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>${jstl.version}</version></dependency><!-- Jackson JSON处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>${jackson.version}</version></dependency><!-- 日志框架 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version></dependency><!-- 文件上传 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><!-- 工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><!-- 测试依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version><scope>test</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>3.12.4</version><scope>test</scope></dependency></dependencies><build><finalName>springmvc-demo</finalName><plugins><!-- 编译插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>8</source><target>8</target><encoding>UTF-8</encoding></configuration></plugin><!-- WAR打包插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.2.3</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin><!-- Tomcat插件 --><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><port>8080</port><path>/springmvc-demo</path><uriEncoding>UTF-8</uriEncoding></configuration></plugin><!-- 测试插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.22.2</version></plugin></plugins></build>
</project>

3.3 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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><display-name>SpringMVC Demo Application</display-name><description>SpringMVC框架基础示例应用</description><!-- Spring根容器配置 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/applicationContext.xml</param-value></context-param><!-- Spring容器监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 字符编码过滤器 --><filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- HTTP方法过滤器(支持PUT、DELETE等方法) --><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- SpringMVC前端控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc-config.xml</param-value></init-param><load-on-startup>1</load-on-startup><async-supported>true</async-supported></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 会话超时配置 --><session-config><session-timeout>30</session-timeout><cookie-config><http-only>true</http-only></cookie-config></session-config><!-- 错误页面配置 --><error-page><error-code>404</error-code><location>/WEB-INF/views/error/404.jsp</location></error-page><error-page><error-code>500</error-code><location>/WEB-INF/views/error/500.jsp</location></error-page><!-- 欢迎页面 --><welcome-file-list><welcome-file>index.jsp</welcome-file><welcome-file>index.html</welcome-file></welcome-file-list><!-- MIME类型配置 --><mime-mapping><extension>css</extension><mime-type>text/css</mime-type></mime-mapping><mime-mapping><extension>js</extension><mime-type>application/javascript</mime-type></mime-mapping></web-app>

3.4 SpringMVC配置文件

<?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"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 开启Controller注解扫描 --><context:component-scan base-package="com.example.controller"/><!-- 开启SpringMVC注解支持 --><mvc:annotation-driven><!-- 配置消息转换器 --><mvc:message-converters><!-- JSON消息转换器 --><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="supportedMediaTypes"><list><value>application/json;charset=UTF-8</value><value>text/json;charset=UTF-8</value></list></property></bean><!-- 字符串消息转换器 --><bean class="org.springframework.http.converter.StringHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value><value>text/html;charset=UTF-8</value></list></property></bean></mvc:message-converters></mvc:annotation-driven><!-- 静态资源处理 --><mvc:resources mapping="/static/**" location="/static/" cache-period="31556926"/><mvc:resources mapping="/css/**" location="/static/css/" cache-period="31556926"/><mvc:resources mapping="/js/**" location="/static/js/" cache-period="31556926"/><mvc:resources mapping="/images/**" location="/static/images/" cache-period="31556926"/><mvc:resources mapping="/favicon.ico" location="/static/favicon.ico" cache-period="31556926"/><!-- 默认Servlet处理器 --><mvc:default-servlet-handler/><!-- 视图解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"/><property name="suffix" value=".jsp"/><property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/><property name="order" value="1"/></bean><!-- 文件上传解析器 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="52428800"/> <!-- 50MB --><property name="maxInMemorySize" value="4096"/><property name="defaultEncoding" value="UTF-8"/><property name="resolveLazily" value="true"/></bean><!-- 异常解析器 --><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="java.lang.Exception">error/error</prop><prop key="java.lang.RuntimeException">error/error</prop></props></property><property name="defaultErrorView" value="error/error"/><property name="exceptionAttribute" value="exception"/></bean><!-- 拦截器配置 --><mvc:interceptors><!-- 日志拦截器 --><mvc:interceptor><mvc:mapping path="/**"/><mvc:exclude-mapping path="/static/**"/><mvc:exclude-mapping path="/css/**"/><mvc:exclude-mapping path="/js/**"/><mvc:exclude-mapping path="/images/**"/><bean class="com.example.interceptor.LoggingInterceptor"/></mvc:interceptor></mvc:interceptors><!-- 内容协商管理器 --><bean id="contentNegotiationManager"class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"><property name="favorPathExtension" value="false"/><property name="favorParameter" value="true"/><property name="parameterName" value="format"/><property name="ignoreAcceptHeader" value="false"/><property name="mediaTypes"><map><entry key="json" value="application/json"/><entry key="xml" value="application/xml"/><entry key="html" value="text/html"/></map></property><property name="defaultContentType" value="text/html"/></bean></beans>

3.5 Spring根配置文件

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启注解扫描,排除Controller --><context:component-scan base-package="com.example"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan><!-- 属性文件加载 --><context:property-placeholder location="classpath:application.properties"ignore-unresolvable="true"/></beans>

4. 基本Controller示例

4.1 简单Controller

package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;/*** 基础Controller示例* 演示SpringMVC的基本用法*/
@Controller
@RequestMapping("/hello")
public class HelloController {/*** 最简单的处理方法* 访问路径:/hello/world*/@RequestMapping("/world")public String hello() {return "hello"; // 返回视图名称,对应 /WEB-INF/views/hello.jsp}/*** 带参数的处理方法* 访问路径:/hello/user?name=张三*/@RequestMapping("/user")public String helloUser(@RequestParam String name, Model model) {model.addAttribute("message", "Hello, " + name + "!");model.addAttribute("currentTime", new java.util.Date());return "hello";}/*** 带默认值的参数* 访问路径:/hello/welcome 或 /hello/welcome?name=李四*/@GetMapping("/welcome")public String welcome(@RequestParam(defaultValue = "Guest") String name, Model model) {model.addAttribute("message", "Welcome, " + name + "!");return "hello";}/*** RESTful风格的URL* 访问路径:/hello/user/123*/@GetMapping("/user/{id}")public String getUserById(@PathVariable Long id, Model model) {model.addAttribute("userId", id);model.addAttribute("message", "User ID: " + id);return "user/detail";}/*** 多个路径变量* 访问路径:/hello/user/123/profile/456*/@GetMapping("/user/{userId}/profile/{profileId}")public String getUserProfile(@PathVariable Long userId,@PathVariable Long profileId,Model model) {model.addAttribute("userId", userId);model.addAttribute("profileId", profileId);model.addAttribute("message", "User " + userId + " Profile " + profileId);return "user/profile";}/*** 返回JSON数据* 访问路径:/hello/api/user/123*/@GetMapping("/api/user/{id}")@ResponseBodypublic Map<String, Object> getUserJson(@PathVariable Long id) {Map<String, Object> result = new HashMap<>();result.put("id", id);result.put("name", "User " + id);result.put("email", "user" + id + "@example.com");result.put("timestamp", new Date());return result;}/*** 处理POST请求* 访问路径:POST /hello/submit*/@PostMapping("/submit")public String handleSubmit(@RequestParam String content, Model model) {model.addAttribute("message", "Submitted: " + content);model.addAttribute("submitTime", new Date());return "hello";}
}

4.2 完整的CRUD Controller

package com.example.controller;import com.example.entity.User;
import com.example.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;import javax.validation.Valid;
import java.util.List;/*** 完整的用户管理Controller* 演示CRUD操作的完整实现*/
@Controller
@RequestMapping("/user")
public class UserController {private static final Logger logger = LoggerFactory.getLogger(UserController.class);@Autowiredprivate UserService userService;/*** 显示用户列表* GET /user/list*/@GetMapping("/list")public String list(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,Model model) {try {List<User> users = userService.findAll();model.addAttribute("users", users);model.addAttribute("currentPage", page);model.addAttribute("pageSize", size);model.addAttribute("totalUsers", users.size());logger.info("用户列表查询成功,共{}条记录", users.size());return "user/list";} catch (Exception e) {logger.error("查询用户列表失败", e);model.addAttribute("error", "查询用户列表失败:" + e.getMessage());return "error/error";}}/*** 显示用户详情* GET /user/detail/{id}*/@GetMapping("/detail/{id}")public String detail(@PathVariable Long id, Model model) {try {User user = userService.findById(id);if (user == null) {model.addAttribute("error", "用户不存在(ID: " + id + ")");return "error/404";}model.addAttribute("user", user);logger.info("查询用户详情成功,用户ID: {}", id);return "user/detail";} catch (Exception e) {logger.error("查询用户详情失败,用户ID: {}", id, e);model.addAttribute("error", "查询用户详情失败:" + e.getMessage());return "error/error";}}/*** 显示添加用户表单* GET /user/add*/@GetMapping("/add")public String showAddForm(Model model) {model.addAttribute("user", new User());model.addAttribute("action", "add");return "user/form";}/*** 处理添加用户请求* POST /user/add*/@PostMapping("/add")public String add(@Valid @ModelAttribute User user,BindingResult bindingResult,RedirectAttributes redirectAttributes,Model model) {if (bindingResult.hasErrors()) {model.addAttribute("action", "add");return "user/form";}try {User savedUser = userService.save(user);redirectAttributes.addFlashAttribute("successMessage","用户添加成功!用户ID: " + savedUser.getId());logger.info("用户添加成功,用户名: {}, ID: {}", user.getUsername(), savedUser.getId());return "redirect:/user/list";} catch (Exception e) {logger.error("用户添加失败,用户名: {}", user.getUsername(), e);model.addAttribute("errorMessage", "用户添加失败:" + e.getMessage());model.addAttribute("action", "add");return "user/form";}}/*** 显示编辑用户表单* GET /user/edit/{id}*/@GetMapping("/edit/{id}")public String showEditForm(@PathVariable Long id, Model model) {try {User user = userService.findById(id);if (user == null) {model.addAttribute("error", "用户不存在(ID: " + id + ")");return "error/404";}model.addAttribute("user", user);model.addAttribute("action", "edit");return "user/form";} catch (Exception e) {logger.error("获取编辑用户信息失败,用户ID: {}", id, e);model.addAttribute("error", "获取用户信息失败:" + e.getMessage());return "error/error";}}/*** 处理编辑用户请求* POST /user/edit*/@PostMapping("/edit")public String edit(@Valid @ModelAttribute User user,BindingResult bindingResult,RedirectAttributes redirectAttributes,Model model) {if (bindingResult.hasErrors()) {model.addAttribute("action", "edit");return "user/form";}try {userService.update(user);redirectAttributes.addFlashAttribute("successMessage","用户更新成功!用户: " + user.getUsername());logger.info("用户更新成功,用户ID: {}, 用户名: {}", user.getId(), user.getUsername());return "redirect:/user/list";} catch (Exception e) {logger.error("用户更新失败,用户ID: {}", user.getId(), e);model.addAttribute("errorMessage", "用户更新失败:" + e.getMessage());model.addAttribute("action", "edit");return "user/form";}}/*** 删除用户* POST /user/delete/{id}*/@PostMapping("/delete/{id}")public String delete(@PathVariable Long id, RedirectAttributes redirectAttributes) {try {User user = userService.findById(id);if (user == null) {redirectAttributes.addFlashAttribute("errorMessage","删除失败:用户不存在(ID: " + id + ")");return "redirect:/user/list";}userService.deleteById(id);redirectAttributes.addFlashAttribute("successMessage","用户删除成功!用户: " + user.getUsername());logger.info("用户删除成功,用户ID: {}, 用户名: {}", id, user.getUsername());} catch (Exception e) {logger.error("用户删除失败,用户ID: {}", id, e);redirectAttributes.addFlashAttribute("errorMessage","用户删除失败:" + e.getMessage());}return "redirect:/user/list";}/*** 批量删除用户* POST /user/batchDelete*/@PostMapping("/batchDelete")public String batchDelete(@RequestParam("userIds") List<Long> userIds,RedirectAttributes redirectAttributes) {try {if (userIds == null || userIds.isEmpty()) {redirectAttributes.addFlashAttribute("errorMessage", "请选择要删除的用户");return "redirect:/user/list";}int deletedCount = userService.batchDelete(userIds);redirectAttributes.addFlashAttribute("successMessage","批量删除成功!共删除 " + deletedCount + " 个用户");logger.info("批量删除用户成功,删除数量: {}", deletedCount);} catch (Exception e) {logger.error("批量删除用户失败", e);redirectAttributes.addFlashAttribute("errorMessage","批量删除失败:" + e.getMessage());}return "redirect:/user/list";}/*** 搜索用户* GET /user/search*/@GetMapping("/search")public String search(@RequestParam(required = false) String keyword,@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,Model model) {try {List<User> users;if (keyword != null && !keyword.trim().isEmpty()) {users = userService.searchByKeyword(keyword.trim());model.addAttribute("keyword", keyword);} else {users = userService.findAll();}model.addAttribute("users", users);model.addAttribute("currentPage", page);model.addAttribute("pageSize", size);model.addAttribute("totalUsers", users.size());logger.info("用户搜索完成,关键词: {}, 结果数量: {}", keyword, users.size());return "user/list";} catch (Exception e) {logger.error("用户搜索失败,关键词: {}", keyword, e);model.addAttribute("error", "搜索失败:" + e.getMessage());return "error/error";}}
}

5. 实体类和服务层示例

5.1 User实体类

package com.example.entity;import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Date;/*** 用户实体类*/
public class User {private Long id;@NotBlank(message = "用户名不能为空")@Size(min = 2, max = 20, message = "用户名长度必须在2-20个字符之间")private String username;@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;@Size(max = 11, message = "电话号码长度不能超过11位")private String phone;private Date createTime;private Date updateTime;// 构造方法public User() {this.createTime = new Date();this.updateTime = new Date();}public User(String username, String email) {this();this.username = username;this.email = email;}// getter和setter方法public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }public Date getUpdateTime() { return updateTime; }public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", email='" + email + '\'' +", phone='" + phone + '\'' +", createTime=" + createTime +'}';}
}

5.2 UserService服务层

package com.example.service;import com.example.entity.User;
import java.util.List;/*** 用户服务接口*/
public interface UserService {/*** 查询所有用户*/List<User> findAll();/*** 根据ID查询用户*/User findById(Long id);/*** 保存用户*/User save(User user);/*** 更新用户*/User update(User user);/*** 删除用户*/void deleteById(Long id);/*** 批量删除用户*/int batchDelete(List<Long> userIds);/*** 根据关键词搜索用户*/List<User> searchByKeyword(String keyword);
}
package com.example.service.impl;import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.stereotype.Service;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;/*** 用户服务实现类* 使用内存存储模拟数据库操作*/
@Service
public class UserServiceImpl implements UserService {// 模拟数据库存储private final Map<Long, User> userStorage = new ConcurrentHashMap<>();private final AtomicLong idGenerator = new AtomicLong(1);// 初始化一些测试数据public UserServiceImpl() {initTestData();}private void initTestData() {save(new User("张三", "zhangsan@example.com"));save(new User("李四", "lisi@example.com"));save(new User("王五", "wangwu@example.com"));}@Overridepublic List<User> findAll() {return new ArrayList<>(userStorage.values());}@Overridepublic User findById(Long id) {return userStorage.get(id);}@Overridepublic User save(User user) {if (user.getId() == null) {user.setId(idGenerator.getAndIncrement());user.setCreateTime(new Date());}user.setUpdateTime(new Date());userStorage.put(user.getId(), user);return user;}@Overridepublic User update(User user) {if (user.getId() == null || !userStorage.containsKey(user.getId())) {throw new RuntimeException("用户不存在,无法更新");}user.setUpdateTime(new Date());userStorage.put(user.getId(), user);return user;}@Overridepublic void deleteById(Long id) {if (!userStorage.containsKey(id)) {throw new RuntimeException("用户不存在,无法删除");}userStorage.remove(id);}@Overridepublic int batchDelete(List<Long> userIds) {int deletedCount = 0;for (Long id : userIds) {if (userStorage.containsKey(id)) {userStorage.remove(id);deletedCount++;}}return deletedCount;}@Overridepublic List<User> searchByKeyword(String keyword) {return userStorage.values().stream().filter(user -> user.getUsername().contains(keyword) ||user.getEmail().contains(keyword)).collect(Collectors.toList());}
}

6. 小结

本文全面介绍了SpringMVC框架的核心概念和基础应用:

6.1 核心内容回顾

  1. SpringMVC框架概述

    • MVC设计模式的理念和优势
    • SpringMVC与传统Servlet开发的对比
    • 框架的主要特点和优势
  2. SpringMVC工作原理

    • 详细的架构图和组件说明
    • 完整的请求处理流程
    • 各个核心组件的职责和作用
  3. 环境搭建和配置

    • 标准的项目结构设计
    • Maven依赖配置和版本管理
    • Web.xml和SpringMVC配置文件详解
  4. Controller开发实践

    • 基础Controller的编写方法
    • 完整CRUD操作的实现
    • 参数绑定和数据验证
  5. 实体类和服务层

    • 标准的实体类设计
    • 服务层接口和实现
    • 业务逻辑的组织方式

6.2 SpringMVC的主要优势

  • 简化Web开发:通过注解和约定大大简化了Web应用的开发
  • 清晰的分层架构:MVC模式使代码结构更加清晰
  • 强大的数据绑定:自动完成请求参数到Java对象的转换
  • 灵活的视图技术:支持多种视图技术和内容协商
  • 良好的RESTful支持:天然支持RESTful风格的API开发
  • 完善的异常处理:提供统一的异常处理机制
  • 丰富的拦截器功能:支持请求的预处理和后处理

6.3 最佳实践建议

  1. 合理的项目结构:按照分层架构组织代码
  2. 统一的异常处理:使用全局异常处理器
  3. 参数验证:使用JSR-303验证注解
  4. 日志记录:在关键操作点添加日志
  5. RESTful设计:遵循RESTful API设计原则

🔗 下一篇预告

下一篇文章将详细介绍SpringMVC请求处理与控制器,深入学习:

  • 请求映射的高级用法
  • 参数绑定和类型转换
  • 数据验证和错误处理
  • 文件上传和下载
  • 异步请求处理

相关文章:

  • 下一篇:SpringMVC请求处理与控制器
  • SpringMVC数据绑定与验证
  • 返回目录
http://www.xdnf.cn/news/18858.html

相关文章:

  • AI 应用开发:从 Prompt 工程到实战应用开发
  • 基于Flask和AI的智能简历分析系统开发全流程
  • golang 基础类 八股文400题
  • 数据赋能(406)——大数据——数据系统安全性原则
  • k8s笔记04-常用部署命令
  • Matlab高光谱遥感、数据处理与混合像元分解实践技术应用
  • 从Java全栈到前端框架的深度探索
  • Android进入Activity时闪黑生命周期销毁并重建
  • 波音787项目:AR技术重塑航空制造的数字化转型
  • 如何用DeepSeek让Excel数据处理自动化:告别重复劳动的智能助手
  • EXCEL自动调整列宽适应A4 A3 A2
  • 云手机挂机掉线是由哪些因素造成的?
  • SQL语法指南
  • Maven下载历史版本
  • AI测试工具midsence和browse_use的使用场景和差异
  • 行向量和列向量在神经网络应用中的选择
  • CPTS-Pressed复现(XML-RPC)
  • 【沉浸式解决问题】NVIDIA 显示设置不可用。 您当前未使用连接到NVIDIA GPU 的显示器。
  • 智能电视MaxHub恢复系统
  • 了解一下大模型微调
  • 基于SpringBoot的物资管理系统【2026最新】
  • pikachu之Over permission
  • 从零到一:现代化充电桩App的React前端参考
  • 自动修改excel 自动统计文件名称插入 excel辅助工具
  • 【基础-单选】向服务器提交表单数据,以下哪种请求方式比较合适
  • 处理端口和 IP 地址
  • 基于Java企业商城网站
  • 彻底解决PyCharm中Matplotlib无法显示图形及中文乱码问题
  • C-JSON接口的使用
  • “无人驾驶与人”之浅析