Spring MVC深度解析:从原理到实战

文章目录

    • [一、Spring MVC概述](#一、Spring MVC概述)
      • [1.1 MVC设计模式](#1.1 MVC设计模式)
      • [1.2 Spring MVC特点](#1.2 Spring MVC特点)
    • [二、Spring MVC核心组件](#二、Spring MVC核心组件)
      • [2.1 架构流程图解](#2.1 架构流程图解)
      • [2.2 核心组件说明](#2.2 核心组件说明)
    • 三、环境搭建与配置
      • [3.1 Maven依赖](#3.1 Maven依赖)
      • [3.2 传统XML配置 vs JavaConfig](#3.2 传统XML配置 vs JavaConfig)
    • 四、控制器开发实践
      • [4.1 基础控制器示例](#4.1 基础控制器示例)
      • [4.2 请求映射注解](#4.2 请求映射注解)
    • 五、数据处理与绑定
      • [5.1 表单处理示例](#5.1 表单处理示例)
      • [5.2 数据验证](#5.2 数据验证)
    • 六、视图技术集成
      • [6.1 Thymeleaf配置](#6.1 Thymeleaf配置)
      • [6.2 JSP视图示例](#6.2 JSP视图示例)
    • [七、RESTful API开发](#七、RESTful API开发)
      • [7.1 REST控制器](#7.1 REST控制器)
    • 八、高级特性
      • [8.1 拦截器实现](#8.1 拦截器实现)
      • [8.2 全局异常处理](#8.2 全局异常处理)
    • 九、最佳实践建议
    • 十、常见问题排查

一、Spring MVC概述

1.1 MVC设计模式

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

  • Model:数据模型,负责业务逻辑和数据管理
  • View:视图层,负责数据展示
  • Controller:控制器,处理用户请求并协调Model和View

1.2 Spring MVC特点

  • 基于DispatcherServlet的前端控制器模式
  • 灵活的配置方式(注解驱动)
  • 强大的数据绑定和验证机制
  • 支持多种视图技术(JSP、Thymeleaf等)
  • 与Spring框架无缝集成

二、Spring MVC核心组件

2.1 架构流程图解

复制代码
[客户端] --> [DispatcherServlet] 
           --> [HandlerMapping]
           --> [Controller] 
           --> [ModelAndView]
           --> [ViewResolver]
           --> [视图]

2.2 核心组件说明

  • DispatcherServlet:前端控制器,统一处理请求
  • HandlerMapping:请求到处理器的映射
  • Controller:业务逻辑处理器
  • ViewResolver:视图解析器
  • HandlerAdapter:处理器适配器
  • Model:数据模型容器

三、环境搭建与配置

3.1 Maven依赖

xml 复制代码
<dependencies>
    <!-- Spring MVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.20</version>
    </dependency>
    
    <!-- Servlet API -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

3.2 传统XML配置 vs JavaConfig

XML配置示例:

xml 复制代码
<!-- web.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-mvc.xml</param-value>
    </init-param>
</servlet>

JavaConfig实现:

java 复制代码
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {
    
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

四、控制器开发实践

4.1 基础控制器示例

java 复制代码
@Controller
@RequestMapping("/user")
public class UserController {

    @GetMapping("/profile")
    public String showProfile(Model model) {
        User user = userService.getCurrentUser();
        model.addAttribute("user", user);
        return "profile";
    }

    @PostMapping("/update")
    public String updateProfile(@Valid UserForm form, 
                              BindingResult result) {
        if (result.hasErrors()) {
            return "edit-profile";
        }
        userService.updateUser(form);
        return "redirect:/user/profile";
    }
}

4.2 请求映射注解

  • @RequestMapping:通用请求映射
  • @GetMapping/@PostMapping:特定HTTP方法映射
  • @PathVariable:URL模板变量
  • @RequestParam:请求参数绑定
java 复制代码
@GetMapping("/articles/{id}")
public String getArticle(@PathVariable Long id,
                        @RequestParam(defaultValue = "desc") String sort,
                        Model model) {
    // 业务逻辑
    return "article-detail";
}

五、数据处理与绑定

5.1 表单处理示例

java 复制代码
@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping("/create")
    public String showForm(Model model) {
        model.addAttribute("product", new Product());
        return "product-form";
    }

    @PostMapping("/save")
    public String saveProduct(@ModelAttribute("product") Product product,
                             BindingResult result) {
        if (result.hasErrors()) {
            return "product-form";
        }
        productService.save(product);
        return "redirect:/product/list";
    }
}

5.2 数据验证

java 复制代码
public class Product {
    
    @NotBlank(message = "产品名称不能为空")
    @Size(max = 50, message = "名称长度不能超过50字符")
    private String name;

    @Min(value = 0, message = "价格不能为负数")
    private BigDecimal price;
    
    // getters/setters
}

六、视图技术集成

6.1 Thymeleaf配置

java 复制代码
@Configuration
@EnableWebMvc
public class ThymeleafConfig {

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }
}

6.2 JSP视图示例

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>用户列表</title>
</head>
<body>
    <h2>用户列表</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
        <c:forEach items="${users}" var="user">
            <tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.email}</td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

七、RESTful API开发

7.1 REST控制器

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserApiController {

    @Autowired
    private UserService userService;

    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        return ResponseEntity.ok(userService.findAll());
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return userService.findById(id)
               .map(ResponseEntity::ok)
               .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
        User savedUser = userService.save(user);
        return ResponseEntity.created(URI.create("/api/users/" + savedUser.getId()))
                             .body(savedUser);
    }
}

八、高级特性

8.1 拦截器实现

java 复制代码
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response,
                            Object handler) throws Exception {
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login");
            return false;
        }
        return true;
    }
}

// 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login", "/register");
    }
}

8.2 全局异常处理

java 复制代码
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse();
        error.setTimestamp(LocalDateTime.now());
        error.setStatus(HttpStatus.NOT_FOUND.value());
        error.setMessage(ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationException(
            MethodArgumentNotValidException ex) {
        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.toList());

        ErrorResponse error = new ErrorResponse();
        error.setStatus(HttpStatus.BAD_REQUEST.value());
        error.setMessage("Validation failed");
        error.setDetails(errors);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

九、最佳实践建议

  1. 遵循分层架构原则:

    • Controller层保持精简
    • 业务逻辑放在Service层
    • 数据访问使用Repository模式
  2. 使用DTO进行数据传输:

    java 复制代码
    public class UserDTO {
        private String username;
        private String email;
        // 省略getter/setter
    }
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody UserDTO dto) {
        User user = userConverter.convertToEntity(dto);
        // ...
    }
  3. 性能优化建议:

    • 合理使用缓存(@Cacheable)
    • 启用GZIP压缩
    • 异步处理(@Async)
  4. 安全注意事项:

    • 使用CSRF保护
    • 输入验证和输出编码
    • 参数化查询防止SQL注入

十、常见问题排查

  1. 404错误排查步骤:

    • 检查@RequestMapping注解路径
    • 确认视图解析器配置
    • 查看组件扫描范围
  2. 数据绑定失败处理:

    • 检查字段名称是否匹配
    • 验证数据类型是否兼容
    • 使用@InitBinder进行自定义绑定
  3. 性能问题分析:

    • 使用Spring Actuator监控端点
    • 分析数据库查询性能
    • 检查视图渲染时间
相关推荐
极客智谷2 分钟前
深入理解Java线程池:从原理到实战的完整指南
java·后端
程序员小陈在成都9 分钟前
Spring Ioc源码引入:什么是IoC,IoC解决了什么问题
spring
代码不行的搬运工10 分钟前
HTML快速入门-4:HTML <meta> 标签属性详解
java·前端·html
bug菌1 小时前
面十年开发候选人被反问:当类被标注为@Service后,会有什么好处?我...🫨
spring boot·后端·spring
mask哥1 小时前
详解最新链路追踪skywalking框架介绍、架构、环境本地部署&配置、整合微服务springcloudalibaba 、日志收集、自定义链路追踪、告警等
java·spring cloud·架构·gateway·springboot·skywalking·链路追踪
XU磊2601 小时前
javaWeb开发---前后端开发全景图解(基础梳理 + 技术体系)
java·idea
学也不会1 小时前
雪花算法
java·数据库·oracle
晓华-warm1 小时前
国产免费工作流引擎star 5.9k,Warm-Flow版本升级1.7.0(新增大量好用功能)
java·中间件·流程图·开源软件·flowable·工作流·activities
凭君语未可1 小时前
介绍 IntelliJ IDEA 快捷键操作
java·ide·intellij-idea
码上飞扬1 小时前
Java大师成长计划之第5天:Java中的集合框架
java·开发语言