SpringMVC 教程

SpringMVC 教程

1. SpringMVC 基本概念

SpringMVC 是 Spring 框架中用于构建 Web 应用程序的模块,它实现了 Model-View-Controller (MVC) 设计模式。其核心思想是将应用程序分为三个主要部分:

  • Model(模型):处理应用程序的数据和业务逻辑
  • View(视图):负责展示数据给用户的界面
  • Controller(控制器):处理用户请求,协调模型和视图

这种分离使得代码结构更清晰、可维护性更高,同时也便于测试。

2. SpringMVC 核心组件

SpringMVC 框架包含以下核心组件:

2.1 前端控制器(DispatcherServlet)

  • 作用:作为整个 SpringMVC 的核心,接收所有 HTTP 请求并协调其他组件工作
  • 特性:是 Servlet 容器中的一个标准 Servlet,需要在 web.xml 中配置
  • 职责:请求分发、组件协调、响应处理

2.2 处理器映射器(HandlerMapping)

  • 作用:根据请求 URL 查找对应的处理器(Controller 方法)
  • 常见实现类
    • RequestMappingHandlerMapping:基于注解 @RequestMapping 的映射
    • SimpleUrlHandlerMapping:基于简单 URL 路径规则的映射
    • BeanNameUrlHandlerMapping:根据 Bean 名称与 URL 进行映射

2.3 处理器适配器(HandlerAdapter)

  • 作用:适配不同类型的处理器,确保它们能够被正确调用
  • 常见实现类
    • RequestMappingHandlerAdapter:支持基于注解的 Controller 方法
    • SimpleControllerHandlerAdapter:支持传统的 Controller 接口实现

2.4 处理器(Handler/Controller)

  • 作用:执行具体的业务逻辑,处理请求并返回结果
  • 实现方式 :使用 @Controller 注解或实现 Controller 接口

2.5 视图解析器(ViewResolver)

  • 作用:将逻辑视图名称解析为具体的视图对象
  • 常见实现类
    • InternalResourceViewResolver:用于解析 JSP 视图
    • FreeMarkerViewResolver:用于解析 FreeMarker 视图

2.6 视图(View)

  • 作用:渲染模型数据,生成最终的响应结果
  • 类型:可以是 JSP、FreeMarker、Thymeleaf 等多种视图技术

3. SpringMVC 工作流程

SpringMVC 的工作流程可以分为以下几个关键步骤:

sql 复制代码
客户端请求 → DispatcherServlet → HandlerMapping → HandlerAdapter → Controller → ModelAndView → ViewResolver → View → 响应客户端

详细流程解析

  1. 客户端发送 HTTP 请求:用户通过浏览器或其他客户端发送请求到服务器

  2. DispatcherServlet 接收请求:所有请求首先被 DispatcherServlet 拦截

  3. 查找处理器

    • DispatcherServlet 向 HandlerMapping 询问当前请求应该由哪个处理器处理
    • HandlerMapping 根据请求 URL、请求方式等信息,返回对应的 HandlerExecutionChain(包含目标 Controller 方法及拦截器)
  4. 执行处理器

    • DispatcherServlet 通过 HandlerAdapter 调用具体的 Controller 方法
    • Controller 方法执行业务逻辑,可能调用 Service、Repository 等组件
    • 处理完成后,返回 ModelAndView 对象(包含模型数据和视图名称)
  5. 解析与渲染视图

    • DispatcherServlet 将 ModelAndView 传递给 ViewResolver
    • ViewResolver 将逻辑视图名称解析为具体的 View 对象
    • View 对象渲染模型数据,生成最终的响应内容
  6. 响应客户端:DispatcherServlet 将渲染后的响应返回给客户端

4. SpringMVC 配置方式

SpringMVC 支持两种主要的配置方式:XML 配置和注解配置。

4.1 XML 配置方式

web.xml 配置
xml 复制代码
<web-app>
  <!-- 配置 DispatcherServlet -->
  <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>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
spring-mvc.xml 配置
xml 复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="...">

  <!-- 启用组件扫描 -->
  <context:component-scan base-package="com.example.controller"/>
  
  <!-- 启用 SpringMVC 注解支持 -->
  <mvc:annotation-driven/>
  
  <!-- 配置视图解析器 -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
  
  <!-- 静态资源处理 -->
  <mvc:resources mapping="/static/**" location="/static/"/>
</beans>

4.2 注解配置方式(Java Config)

配置类
java 复制代码
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "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;
    }
    
    // 配置静态资源处理
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
}
初始化器
java 复制代码
public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {
        // 创建根应用上下文
        AnnotationConfigWebApplicationContext rootContext = 
                new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);
        
        // 注册 ContextLoaderListener
        servletContext.addListener(new ContextLoaderListener(rootContext));
        
        // 创建 SpringMVC 应用上下文
        AnnotationConfigWebApplicationContext webContext = 
                new AnnotationConfigWebApplicationContext();
        webContext.register(WebConfig.class);
        
        // 注册 DispatcherServlet
        ServletRegistration.Dynamic dispatcher = 
                servletContext.addServlet("dispatcher", new DispatcherServlet(webContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

5. SpringMVC 控制器开发

5.1 基本控制器示例

java 复制代码
@Controller
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    // GET 请求 - 获取用户列表
    @GetMapping
    public String listUsers(Model model) {
        List<User> users = userService.findAllUsers();
        model.addAttribute("users", users);
        return "user/list"; // 返回视图名称
    }
    
    // GET 请求 - 显示添加用户表单
    @GetMapping("/add")
    public String showAddForm(Model model) {
        model.addAttribute("user", new User());
        return "user/add"; // 返回视图名称
    }
    
    // POST 请求 - 提交添加用户表单
    @PostMapping
    public String addUser(@ModelAttribute User user) {
        userService.addUser(user);
        return "redirect:/users"; // 重定向到用户列表页面
    }
    
    // GET 请求 - 根据 ID 获取用户详情
    @GetMapping("/{id}")
    public String getUserById(@PathVariable("id") Long id, Model model) {
        User user = userService.getUserById(id);
        model.addAttribute("user", user);
        return "user/detail"; // 返回视图名称
    }
    
    // PUT 请求 - 更新用户
    @PutMapping("/{id}")
    public String updateUser(@PathVariable("id") Long id, @ModelAttribute User user) {
        user.setId(id);
        userService.updateUser(user);
        return "redirect:/users"; // 重定向到用户列表页面
    }
    
    // DELETE 请求 - 删除用户
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable("id") Long id) {
        userService.deleteUser(id);
        return "redirect:/users"; // 重定向到用户列表页面
    }
}

5.2 RESTful API 控制器示例

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserRestController {
    
    @Autowired
    private UserService userService;
    
    // 获取所有用户
    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAllUsers();
    }
    
    // 根据 ID 获取用户
    @GetMapping("/{id}")
    public User getUserById(@PathVariable("id") Long id) {
        return userService.getUserById(id);
    }
    
    // 添加用户
    @PostMapping
    public User addUser(@RequestBody User user) {
        return userService.addUser(user);
    }
    
    // 更新用户
    @PutMapping("/{id}")
    public User updateUser(@PathVariable("id") Long id, @RequestBody User user) {
        user.setId(id);
        return userService.updateUser(user);
    }
    
    // 删除用户
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable("id") Long id) {
        userService.deleteUser(id);
    }
}

6. 请求参数绑定与验证

6.1 请求参数绑定

SpringMVC 支持多种方式的参数绑定:

java 复制代码
@Controller
public class ParamController {
    
    // 基本类型参数绑定
    @GetMapping("/param1")
    public String param1(@RequestParam("id") Integer id, 
                        @RequestParam("name") String name) {
        // 处理业务逻辑
        return "result";
    }
    
    // 路径变量绑定
    @GetMapping("/param2/{id}")
    public String param2(@PathVariable("id") Long id) {
        // 处理业务逻辑
        return "result";
    }
    
    // 请求头绑定
    @GetMapping("/param3")
    public String param3(@RequestHeader("User-Agent") String userAgent) {
        // 处理业务逻辑
        return "result";
    }
    
    // Cookie 值绑定
    @GetMapping("/param4")
    public String param4(@CookieValue("JSESSIONID") String sessionId) {
        // 处理业务逻辑
        return "result";
    }
    
    // 表单数据绑定到对象
    @PostMapping("/param5")
    public String param5(@ModelAttribute User user) {
        // 处理业务逻辑
        return "result";
    }
    
    // JSON 数据绑定到对象
    @PostMapping("/param6")
    public String param6(@RequestBody User user) {
        // 处理业务逻辑
        return "result";
    }
}

6.2 数据验证

使用 SpringMVC 结合 Bean Validation(JSR-380)进行数据验证:

java 复制代码
// 实体类添加验证注解
public class User {
    
    @NotNull(message = "ID 不能为空")
    private Long id;
    
    @NotBlank(message = "用户名不能为空")
    @Size(min = 2, max = 50, message = "用户名长度必须在 2-50 之间")
    private String username;
    
    @NotBlank(message = "邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
    
    // getter 和 setter 方法
}

// 控制器中添加验证
@Controller
public class ValidationController {
    
    @PostMapping("/validate")
    public String validateUser(@Valid @ModelAttribute User user, 
                              BindingResult bindingResult) {
        // 检查验证结果
        if (bindingResult.hasErrors()) {
            // 处理验证错误
            return "form";
        }
        
        // 处理业务逻辑
        return "success";
    }
}

7. 异常处理

7.1 全局异常处理器

java 复制代码
@ControllerAdvice
public class GlobalExceptionHandler {
    
    // 处理特定异常
    @ExceptionHandler(UserNotFoundException.class)
    public ModelAndView handleUserNotFound(UserNotFoundException ex) {
        ModelAndView model = new ModelAndView("error");
        model.addObject("errorMessage", ex.getMessage());
        model.addObject("errorCode", "404");
        return model;
    }
    
    // 处理所有异常
    @ExceptionHandler(Exception.class)
    public ModelAndView handleGenericException(Exception ex) {
        ModelAndView model = new ModelAndView("error");
        model.addObject("errorMessage", "发生未知错误");
        model.addObject("errorCode", "500");
        return model;
    }
    
    // 处理 REST API 异常
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleValidationException(ValidationException ex) {
        ErrorResponse error = new ErrorResponse("400", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

8. SpringMVC 与 Spring Boot 集成

在 Spring Boot 中使用 SpringMVC 变得更加简单:

8.1 基本配置

创建一个 Spring Boot 应用并添加依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

8.2 应用主类

java 复制代码
@SpringBootApplication
public class SpringBootMvcApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMvcApplication.class, args);
    }
}

8.3 控制器开发

与普通 SpringMVC 控制器相同,但无需额外配置:

java 复制代码
@RestController
public class HelloController {
    
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring MVC with Spring Boot!";
    }
}

9. 最佳实践

  1. 使用 RESTful 风格:遵循 REST 原则设计 API,使用合适的 HTTP 方法

  2. 合理使用注解 :使用 @RestController 简化 REST API 开发,使用 @Controller 开发视图控制器

  3. 统一异常处理 :使用 @ControllerAdvice 实现全局异常处理

  4. 请求参数验证:使用 Bean Validation 进行输入验证

  5. 使用拦截器:处理横切关注点,如日志记录、权限验证等

  6. 优化静态资源处理:配置适当的资源处理器和缓存策略

  7. 使用 Spring Boot:简化配置,提高开发效率

  8. 性能优化:合理使用缓存、异步处理等技术提升性能

10. 总结

SpringMVC 是一个功能强大、灵活的 Web 框架,通过 DispatcherServlet 作为核心,协调各个组件完成请求处理和响应生成。它支持多种配置方式和视图技术,与 Spring 框架无缝集成,是构建 Java Web 应用的理想选择。

通过本教程,您应该能够理解 SpringMVC 的基本概念、核心组件和工作流程,并能够开始开发自己的 SpringMVC 应用程序。

相关推荐
观望过往24 分钟前
Spring Boot 集成 EMQ X 4.0 完整技术指南
java·spring boot·后端·emqx
心之语歌36 分钟前
对于 时间复杂度和空间复杂度分析
后端
青旬41 分钟前
AI编程祛魅-最近几个失败的ai编程经历
后端·程序员
莹Innsane1 小时前
记一次 float64 排序失效的灵异事件
后端
Python私教1 小时前
使用 SQLAlchemy 操作单表:以 SQLite 用户表为例的完整实战指南
后端
Python私教1 小时前
使用 SQLAlchemy 连接数据库:从基础到最佳实践
后端
码起来呗2 小时前
基于Spring Boot的乡村拼车小程序的设计与实现-项目分享
spring boot·后端·小程序
我命由我123452 小时前
Java 并发编程 - Delay(Delayed 概述、Delayed 实现、Delayed 使用、Delay 缓存实现、Delayed 延迟获取数据实现)
java·开发语言·后端·缓存·java-ee·intellij-idea·intellij idea
我是天龙_绍4 小时前
java 比对两对象大小 重写 comparator
后端
IT_陈寒4 小时前
Python 3.12新特性实测:10个让你的代码提速30%的隐藏技巧 🚀
前端·人工智能·后端