【Spring】7.深入理解Spring MVC:从基础概念到高级特性的全面解析

Spring MVC是Spring框架的一个模块,全称为Spring Model-View-Controller,是一个基于Java的实现MVC(Model-View-Controller)设计模式的请求驱动类型的轻量级Web框架。MVC模式是一种用于将应用程序分为三个核心组件的软件设计模式,以便分离内聚关注点,从而使得开发、测试和维护更加容易。

一.基本概念

  • Model(模型):负责数据和业务逻辑,即数据的增删改查等操作。
  • View(视图):负责展示数据(模型)并且可以提供用户交互的界面,通常是指用户看到的界面。
  • Controller(控制器):接收用户请求并将其委托给Model和View去处理,Controller本身不输出任何东西和做任何处理,它只是接收请求并决定调用哪个Model构件去处理请求,然后再确定用哪个View来显示返回的数据。

二.作用

在Web应用中,Spring MVC的作用主要体现在以下几个方面:

  1. 解耦:将视图层和业务逻辑层分离,提高代码的可维护性。
  2. 灵活的视图支持:支持多种视图技术,如JSP、FreeMarker、Thymeleaf等,允许开发者根据项目需求灵活选择。
  3. 请求驱动:以请求为中心,通过注解或配置将请求映射到对应的处理器(Controller中的方法)。
  4. 支持RESTful:支持RESTful风格的Web服务开发,简化了API的创建。
  5. 集成Spring生态:作为Spring大家族的一部分,Spring MVC能够无缝集成Spring的其他模块,如Spring Security、Spring Data等。
  6. 组件化:通过DispatcherServlet、HandlerMapping、ViewResolver等组件,提供了一个完整的请求处理流程。

三.工作流程

Spring MVC的工作原理大致如下:

  1. 用户发送请求到服务器,这个请求首先被DispatcherServlet(前端控制器)捕获。
  2. DispatcherServlet将请求委托给HandlerMapping,由它解析请求并映射到相应的Controller
  3. Controller执行业务逻辑后,返回一个ModelAndView对象,其中包含模型数据和要渲染的视图。
  4. HandlerAdapterModelAndView传递给DispatcherServlet
  5. DispatcherServletModelAndView传递给ViewResolver
  6. ViewResolver解析视图逻辑名,找到具体的视图实现。
  7. 视图将模型数据渲染成HTML,响应给客户端。

Spring MVC通过组件化和注解化的方式,简化了Web应用的开发过程,提高了开发效率和应用的可维护性。

Spring MVC的常用注解可以分为以下几类,每类都包含了注解的作用、使用案例以及使用时需要注意的事项:

四.常用注解

控制器定义注解

  • @Controller

    • 作用:标识该类是一个Spring MVC控制器。

    • 使用案例

      java 复制代码
      @Controller
      public class MyController {
          @GetMapping("/greeting")
          public String sayHello() {
              return "greeting";
          }
      }
    • 注意:控制器中的方法通常设计为线程安全的无状态方法。

  • @RestController

    • 作用 :组合了@Controller@ResponseBody,用于类上,意味着该类中的所有方法都默认带有@ResponseBody效果,直接返回数据。

    • 使用案例

      java 复制代码
      @RestController
      public class MyRestController {
          @GetMapping("/greeting")
          public String sayHello() {
              return "Hello, World!";
          }
      }
    • 注意:通常用于RESTful Web服务,无需返回视图。

请求映射注解

  • @RequestMapping

    • 作用:将HTTP请求映射到特定的方法上。

    • 使用案例

      java 复制代码
      @Controller
      public class MyMappingController {
          @RequestMapping(value = "/hello", method = RequestMethod.GET)
          public String sayHello(Model model) {
              model.addAttribute("message", "Hello, Spring MVC!");
              return "hello";
          }
      }
    • 注意:可以指定请求方法和路径,也可以有额外的属性如请求参数或请求头。

  • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

    • 作用:分别用于处理GET、POST、PUT、DELETE请求的简便方式。

    • 使用案例

      java 复制代码
      @RestController
      public class MyRestfulController {
          @GetMapping("/users/{id}")
          public User getUserById(@PathVariable Long id) {
              // 返回用户信息
              return userService.findById(id);
          }
      }
    • 注意 :它们是@RequestMapping的特化,限制了HTTP请求类型。

请求参数注解

  • @RequestParam

    • 作用:将请求参数与方法参数绑定。

    • 使用案例

      java 复制代码
      public String searchByKeyword(@RequestParam String keyword, Model model) {
          // 根据关键词进行搜索
          model.addAttribute("results", searchService.search(keyword));
          return "search-results";
      }
    • 注意:可以指定请求参数是否是必需的,默认值是什么。

  • @PathVariable

    • 作用:从URI路径模板中提取变量。

    • 使用案例

      java 复制代码
      public String getUserDetails(@PathVariable("username") String username, Model model) {
          // 根据用户名获取用户详情
          model.addAttribute("user", userService.findByUsername(username));
          return "user-details";
      }
    • 注意 :通常与@RequestMapping一起使用,用于RESTful URI设计。

请求体注解

  • @RequestBody

    • 作用:允许将请求正文中的数据绑定到方法参数上。

    • 使用案例

      java 复制代码
      @PostMapping("/users")
      public User createUser(@RequestBody User user) {
          // 创建用户
          return userService.create(user);
      }
    • 注意:常用于接收JSON格式的请求体,需要配置适当的转换器。

  • @ResponseBody

    • 作用:指示方法的返回值作为HTTP响应正文返回。

    • 使用案例

      java 复制代码
      @GetMapping("/users/{id}")
      public User getUserById(@PathVariable Long id) {
          // 获取用户信息
          return userService.findById(id);
      }
    • 注意:通常用于RESTful Web服务,返回值将被序列化为JSON或XML。

异常处理注解

  • @ExceptionHandler
    • 作用:用于全局或特定异常的处理。

    • 使用案例

      java 复制代码
      @ControllerAdvice
      public class GlobalExceptionHandler {
          @ExceptionHandler(NotFoundException.class)
          public ResponseEntity<String> handleNotFoundException() {
              return ResponseEntity.notFound().build();
          }
      }
    • 注意:可以捕获并处理控制器中抛出的异常。

数据注解

  • @ModelAttribute
    • 作用:用于将请求参数或Session中的对象绑定到模型中。

    • 使用案例

      java 复制代码
      public String showForm(@ModelAttribute("user") User user) {
          // 显示表单
          return "user-form";
      }
    • 注意:可以用于表单数据的初始化。

安全性注解

  • @CrossOrigin
    • 作用:用于跨域资源共享。

    • 使用案例

      java 复制代码
      @RestController
      @CrossOrigin(origins = "http://localhost:4200")
      public class MyRestController {
          // ...
      }
    • 注意:应谨慎使用,以避免开放不受限制的外部访问。

@ControllerAdvice@RestControllerAdvice

  • 作用:定义全局的控制器增强功能,如异常处理器、数据预处理等。

  • 使用案例

    java 复制代码
    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(Exception.class)
        public ResponseEntity<String> handleException(Exception e) {
            // 全局异常处理逻辑
        }
    }
  • 注意:可以集中处理全局的控制器相关事宜。使用全局注解时,需要注意它们之间的相互影响,确保全局配置符合应用程序的整体架构和设计原则。此外,全局配置的更改可能会影响到整个应用程序的行为,因此在进行全局配置时需要谨慎。

这些注解的组合使用,为Spring MVC应用程序提供了强大的请求映射能力和数据处理能力。在使用过程中,应根据实际需求和最佳实践来选择和配置注解,以确保应用程序的安全性和高效性。

五.异常处理机制

Spring MVC的异常处理机制是一种强大且灵活的错误处理方式,允许开发者捕获和处理应用程序中的异常,以提供更友好的反馈给客户端。以下是Spring MVC处理异常的详细解释和如何自定义异常处理器的步骤:

处理异常的基本流程

  1. 异常抛出

    • 当Spring MVC中的Controller处理方法执行业务逻辑时,如果遇到任何问题导致异常被抛出,该异常会被Spring MVC框架捕获。
  2. 查找异常处理器

    • Spring MVC会查找是否有匹配的异常处理器可以处理这个异常。异常处理器是带有@ExceptionHandler注解的方法。
  3. 执行异常处理器

    • 如果找到合适的异常处理器,Spring MVC会调用该处理器中的相关方法来处理异常。
  4. 返回错误响应

    • 异常处理器负责生成一个适当的响应,可以是一个错误页面、一个JSON对象、一个HTML字符串,或者任何其他类型的响应体。
  5. 无匹配的异常处理器

    • 如果没有找到匹配的异常处理器,Spring MVC将使用其默认的异常处理策略。

自定义异常处理器

  1. 定义异常处理器类

    • 创建一个新的类,使用@ControllerAdvice注解来声明这是一个异常处理器类。这个类可以捕获所有Spring MVC控制器抛出的异常。

      java 复制代码
      @ControllerAdvice
      public class GlobalExceptionHandler {
          // 这里可以定义异常处理方法
      }
  2. 定义异常处理方法

    • 在异常处理器类中定义方法,使用@ExceptionHandler注解指定可以处理的异常类型。

      java 复制代码
      @ExceptionHandler(MethodArgumentNotValidException.class)
      public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException ex) {
          // 构建并返回一个包含验证错误信息的响应实体
          String errorMessage = "Validation failed: " + ex.getBindingResult().toString();
          return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorMessage);
      }
  3. 处理方法的返回值

    • 异常处理方法可以返回多种类型的值,如ModelAndViewViewStringResponseEntity等。
  4. 配置异常处理顺序

    • 如果有多个异常处理器可以处理同一个异常,可以通过@Order注解或实现Ordered接口来指定处理顺序。
  5. 使用ResponseEntity

    • 使用ResponseEntity可以自定义响应的状态码、头部信息以及响应体。
  6. 全局与局部异常处理器

    • @ControllerAdvice可以用于全局异常处理,也可以限制在特定的包或控制器上使用@Profile@Component注解来定义局部异常处理器。
  7. 异常处理的响应体

    • 对于@RestController@RestControllerAdvice注解的类,异常处理方法的返回值会直接作为响应体返回,无需显式使用@ResponseBody注解。
  8. 自定义异常

    • 可以创建自定义异常类,使得异常处理器能够更精细地处理特定的业务场景。
  9. 日志记录

    • 在异常处理方法中,可以记录异常日志,便于问题的追踪和调试。

通过自定义异常处理器,可以控制异常信息的呈现方式,提供更友好的错误提示,同时确保API的安全性和稳定性。自定义异常处理器是RESTful API设计中不可或缺的一部分,它提升了用户体验并有助于API的健壮性。

六.高级特性

Spring MVC 提供了一系列高级特性,用以增强应用程序的功能和性能。以下是一些重要的高级特性及其用途、使用方法和注意事项:

拦截器(Interceptor)

用途:拦截器用于在请求处理前后执行通用的处理逻辑,如日志记录、安全验证、事务管理等。

使用案例

java 复制代码
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 在请求处理之前执行的操作,如权限检查
        return true; // 返回 true 表示继续执行请求,返回 false 表示中断请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 请求处理之后执行的操作,如统一的响应格式处理
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求完成后执行的操作,如资源清理
    }
}

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                  .addPathPatterns("/**") // 所有路径
                  .excludePathPatterns("/css/**", "/js/**"); // 排除静态资源路径
    }
}

注意:拦截器可能会影响性能,需要谨慎使用。拦截器的执行顺序可以在注册时指定。

过滤器(Filter)

用途:过滤器用于在请求进入DispatcherServlet之前进行预处理,如日志记录、安全控制、监控等。

使用案例

java 复制代码
@WebFilter("/*")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) {
        // 初始化过滤器
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        // 在请求进入DispatcherServlet之前执行的操作
        filterChain.doFilter(servletRequest, servletResponse); // 继续过滤器链
        // 在请求离开DispatcherServlet之后执行的操作
    }

    @Override
    public void destroy() {
        // 销毁过滤器
    }
}

注意:过滤器主要用于处理通用的预处理和后处理逻辑,不涉及请求映射。

格式化器(Formatter)

用途:格式化器用于自定义数据的格式化和解析,特别是对于日期、数字等类型的数据。

使用案例

java 复制代码
public class MyFormatter implements Formatter<Date> {
    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        // 实现字符串到日期的转换逻辑
        return new SimpleDateFormat("yyyy-MM-dd").parse(text);
    }

    @Override
    public String print(Date object, Locale locale) {
        // 实现日期到字符串的转换逻辑
        return new SimpleDateFormat("yyyy-MM-dd").format(object);
    }
}

@Configuration
public class FormatterConfig {
    @Bean
    public Formatter<Date> dateFormatter() {
        return new MyFormatter();
    }
}

注意:格式化器需要注册到Spring MVC的格式化器工厂中,并且与字段的注解结合使用。

异步请求处理

用途:异步请求处理允许应用程序在后台线程中处理长时间运行的任务,而不阻塞请求线程。

使用案例

java 复制代码
@Controller
public class AsyncController {
    @RequestMapping(value = "/async", method = RequestMethod.GET)
    public Callable<String> handleRequest() {
        return () -> {
            // 执行耗时操作
            Thread.sleep(1000); // 模拟耗时操作
            return "asyncResult";
        };
    }
}

注意 :异步请求处理需要配置线程池,并且要处理好异常和超时情况。可以使用@Async注解在方法上启用异步执行。

这些高级特性在Spring MVC中发挥着重要作用,它们提供了一种灵活的方式来增强应用程序的功能和性能。在使用这些特性时,需要仔细考虑它们对应用程序的影响,并确保它们被正确配置和使用。

七.Spring MVC与Spring Boot的关系

Spring MVC 和 Spring Boot 的关系可以概括为:

  1. 补充关系:Spring MVC 是 Spring 框架的一部分,专注于 Web 应用的模型-视图-控制器模式。Spring Boot 是一个独立的项目,提供了简化的初始搭建以及开发过程。

  2. 简化配置:Spring Boot 通过自动配置和起步依赖(starters)减少了传统 Spring MVC 应用所需的大量配置。

  3. 集成使用:Spring Boot 并没有取代 Spring MVC,而是与其集成,让开发者可以轻松地在 Spring Boot 应用中使用 Spring MVC。

  4. 快速开发:Spring Boot 鼓励使用约定优于配置的原则,加快了开发速度。

  5. 微服务支持:Spring Boot 与 Spring Cloud 等微服务项目配合,支持构建微服务应用。

在实践中,Spring Boot 应用通常会包含 Spring MVC 作为处理 Web 请求的组件,Spring Boot 提供了对 Spring MVC 的自动配置支持,使得开发者可以快速搭建 RESTful API 或传统的 Web 应用。

Spring MVC作为一个功能强大且灵活的Web框架,为Java开发者提供了构建高效、可维护Web应用的坚实基础。从基础的MVC模式到高级的异步处理和格式化,Spring MVC不断扩展其能力,以适应快速变化的Web开发需求。同时,Spring Boot的出现进一步简化了Spring MVC的应用,让开发者能够更加专注于业务逻辑的实现。

相关推荐
A-刘晨阳5 小时前
AI原生时序数据库选型指南:从数据存储到智能决策的范式跃迁
数据库·时序数据库·ai-native
whinc6 小时前
Rust技术周刊 2026年第17周
后端·rust
whinc6 小时前
Rust技术周刊 2026年第18周
后端·rust
xqqxqxxq6 小时前
Java AI智能P图工具技术笔记
java·人工智能·笔记
whinc6 小时前
Rust技术周刊 2026年第16周
后端·rust
HalvmånEver6 小时前
MySQL的增删改查命令合集合集
数据库·sql·oracle
谷雨不太卷6 小时前
进程的状态码
java·前端·算法
jieyucx6 小时前
Go语言深度解剖:Map扩容机制全解析(增量扩容+等量扩容+渐进式迁移)
开发语言·后端·golang·map·扩容策略
顾温6 小时前
default——C#/C++
java·c++·c#
空中海7 小时前
02 ArkTS 语言与工程规范
java·前端·spring