1. Java Web的发展历史与MVC模式
1.1 Model I与Model II的演进
Model I(JSP+JavaBean)
作为早期Java Web开发的主流模式,其核心架构如下:
graph LR
A[客户端] --> B[JSP页面]
B --> C{业务逻辑}
C --> D[JavaBean]
D --> B
B --> A
痛点分析:
-
JSP同时承担视图渲染与业务控制,代码耦合度高
-
项目规模扩大后维护成本指数级增长
Model II(Servlet+JSP+JavaBean)
通过分层思想实现解耦:
graph LR
A[客户端] --> B[Servlet]
B --> C{控制逻辑}
C --> D[JavaBean]
D --> E[JSP]
E --> A
优势:
-
职责分离:Servlet负责流程控制,JSP专注视图展示
-
更适合大型项目开发
1.2 MVC设计模式的精髓
组件 | 职责说明 | 具体实现 |
---|---|---|
Model | 数据处理与业务逻辑 | Service/Dao/Entity |
View | 用户界面与数据展示 | JSP/Thymeleaf模板 |
Controller | 请求调度与响应处理 | @Controller注解类 |
2. Spring MVC快速入门实战
2.1 环境搭建(IntelliJ IDEA演示)
Maven依赖配置:
<properties>
<spring.version>5.3.18</spring.version>
</properties>
<dependencies>
<!-- Spring MVC核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 视图解析 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.15.RELEASE</version>
</dependency>
</dependencies>
2.2 核心配置详解
web.xml配置:
<!-- 字符编码过滤器 -->
<filter>
<filter-name>encodingFilter</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>
</filter>
<!-- 前端控制器 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Spring MVC配置(spring-mvc.xml):
<!-- 组件扫描 -->
<context:component-scan base-package="com.example.controller"/>
<!-- 视图解析器 -->
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine"/>
</bean>
<!-- 模板引擎配置 -->
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".html"/>
</bean>
</property>
</bean>
2.3 控制器开发实例
@Controller
public class HelloController {
@GetMapping("/hello")
public String sayHello(Model model) {
model.addAttribute("message", "Welcome to Spring MVC!");
return "result-page";
}
}
页面结构:
src
├── main
│ ├── webapp
│ │ └── WEB-INF
│ │ └── views
│ │ └── result-page.html
3. Spring MVC核心原理剖析
3.1 请求处理全流程
-
DispatcherServlet接收请求
作为统一入口,拦截所有HTTP请求 -
HandlerMapping路由匹配
根据URL找到对应的Controller方法 -
HandlerAdapter执行处理
通过反射调用目标方法 -
视图解析与渲染
将逻辑视图名转换为物理视图路径
sequenceDiagram
客户端->>DispatcherServlet: HTTP请求
DispatcherServlet->>HandlerMapping: 查询处理器
HandlerMapping-->>DispatcherServlet: 返回Handler
DispatcherServlet->>HandlerAdapter: 执行处理器
HandlerAdapter->>Controller: 调用方法
Controller-->>HandlerAdapter: 返回ModelAndView
HandlerAdapter-->>DispatcherServlet: 返回结果
DispatcherServlet->>ViewResolver: 解析视图
ViewResolver-->>DispatcherServlet: 返回视图
DispatcherServlet->>View: 渲染视图
View-->>客户端: 响应HTML
3.2 核心组件详解
组件 | 职责说明 | 默认实现类 |
---|---|---|
HandlerMapping | 请求到处理器的映射 | RequestMappingHandlerMapping |
HandlerAdapter | 执行处理器方法 | RequestMappingHandlerAdapter |
ViewResolver | 解析逻辑视图名 | InternalResourceViewResolver |
HandlerExceptionResolver | 异常处理 | ExceptionHandlerExceptionResolver |
4. 开发技巧与最佳实践
-
RESTful风格设计
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
// 业务逻辑
}
}
2.统一异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView mav = new ModelAndView();
mav.addObject("errorMsg", ex.getMessage());
mav.setViewName("error-page");
return mav;
}
}
3. 参数验证技巧
@PostMapping("/register")
public String register(@Valid User user, BindingResult result) {
if (result.hasErrors()) {
return "register-form";
}
// 处理注册逻辑
}
5. 常见问题排查指南
问题1:404未找到页面
✅ 检查项:
-
控制器是否添加@Controller注解
-
请求路径是否匹配@RequestMapping
-
视图文件位置是否符合配置的prefix/suffix
问题2:参数绑定失败
✅ 解决方案:
-
检查表单字段名与POJO属性名是否一致
-
使用@RequestParam指定参数名称
-
添加BindingResult参数捕获错误
6. 性能优化建议
-
启用缓存
@Cacheable("users")
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// 数据库查询
}
2.异步处理
@Async
public CompletableFuture<User> fetchUserAsync(Long id) {
// 异步操作
}
3.静态资源优化
结语
<mvc:resources mapping="/static/**" location="/static/" cache-period="31556926"/>
通过本文的学习,我们不仅掌握了Spring MVC的核心原理,还完成了从环境搭建到实战开发的完整流程。建议读者在掌握基础后,继续深入以下方向:
-
深入理解拦截器(Interceptor)机制
-
研究Spring Boot对MVC的自动化配置
-
探索响应式编程WebFlux框架