【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的应用,让开发者能够更加专注于业务逻辑的实现。

相关推荐
逊嘘5 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
morris13112 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
十叶知秋25 分钟前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
monkey_meng30 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马32 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng36 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
七星静香37 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员38 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU38 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie642 分钟前
在IDEA中使用Git
java·git