ToB企服应用市场:ToB评测及商务社交产业平台

标题: SpringMVC详解(全网最全) [打印本页]

作者: 宁睿    时间: 2025-1-8 11:49
标题: SpringMVC详解(全网最全)
起源

1. 三层架构:一个 Servlet 只能处理一个哀求,耦合度高,复用性差,整页刷新用户体验差


2. MVC 模式:部分解耦但后端仍负责 View层,高并发有限


3. 前后端分离:异步调用,复用性强,支持复杂交互,用户体验性强


概念

1. Model(模子 )

2. View(视图)

3. Controller(控制器)

执行流程


组件

1. DispatchServlet

2. HandlerMapping

3. HandlerAdapter

4. Handler(Controller)

5. ViewResolver

6. View

包含的注解

SpringMVC 中常用的注解可以分为以下几类,分别对应不同的功能和场景:
1. 核心控制器注解

@Controller

  1. @Controller
  2. public class MyController {
  3.     @RequestMapping("/hello")
  4.     public String hello() {
  5.         return "hello"; // 视图名
  6.     }
  7. }
复制代码
@RestController

  1. @RestController
  2. public class ApiController {
  3.     @GetMapping("/api/data")
  4.     public String getData() {
  5.         return "This is JSON response.";
  6.     }
  7. }
复制代码
2. 哀求映射干系注解

@RequestMapping

  1. @Controller
  2. @RequestMapping("/user")
  3. public class UserController {
  4.     @RequestMapping("/profile")
  5.     public String userProfile() {
  6.         return "profile";
  7.     }
  8. }
复制代码
@GetMapping / @PostMapping / @PutMapping / @DeleteMapping / @PatchMapping

  1. @GetMapping("/getUser")
  2. public String getUser() {
  3.     return "getUser";
  4. }
复制代码
3. 哀求参数干系注解

在 SpringMVC 中,HTTP 哀求中的参数通常是简朴范例(如 String、int 等),使用其他范例时,最好加上 @RequestParam,日期格式使用@DateTimeFormat
@RequestParam

  1. @GetMapping("/search")
  2. public String search(@RequestParam("keyword") String keyword) {
  3.     return "Search for: " + keyword;
  4. }
复制代码
@PathVariable

  1. @GetMapping("/user/{id}")
  2. public String getUserById(@PathVariable("id") String id) {
  3.     return "User ID: " + id;
  4. }
复制代码
@RequestBody

  1. @PostMapping("/addUser")
  2. public String addUser(@RequestBody User user) {
  3.     return "User Name: " + user.getName();
  4. }
复制代码
@RequestHeader

  1. @GetMapping("/header")
  2. public String getHeader(@RequestHeader("Authorization") String auth) {
  3.     return "Auth: " + auth;
  4. }
复制代码
@CookieValue

  1. @GetMapping("/cookie")
  2. public String getCookie(@CookieValue("sessionId") String sessionId) {
  3.     return "Session ID: " + sessionId;
  4. }
复制代码
4. 返回结果干系注解

@ResponseBody

  1. @ResponseBody
  2. @GetMapping("/json")
  3. public String jsonResponse() {
  4.     return "{"key":"value"}";
  5. }
复制代码
@ModelAttribute

  1. @ModelAttribute
  2. public void addAttributes(Model model) {
  3.     model.addAttribute("message", "Hello World");
  4. }
复制代码
5. 数据验证干系注解

@Valid

  1. @PostMapping("/save")
  2. public String saveUser(@Valid @RequestBody User user, BindingResult result) {
  3.     if (result.hasErrors()) {
  4.         return "Validation failed";
  5.     }
  6.     return "Success";
  7. }
复制代码
6. 其他注解

@SessionAttributes

  1. @SessionAttributes("user")
  2. @Controller
  3. public class SessionController {
  4.     @GetMapping("/setSession")
  5.     public String setSession(Model model) {
  6.         model.addAttribute("user", "John");
  7.         return "session";
  8.     }
  9. }
复制代码
@RequestPart

  1. @PostMapping("/upload")
  2. public String handleFileUpload(@RequestPart("file") MultipartFile file) {
  3.     return "Uploaded: " + file.getOriginalFilename();
  4. }
复制代码
总结

注解功能描述@Controller标记类为控制器,用于返回视图@RestController返回 JSON 或 XML 数据@RequestMapping映射哀求路径@RequestParam获取哀求参数@PathVariable获取路径参数@RequestBody获取哀求体数据@ResponseBody返回数据到响应体@ModelAttribute绑定模子数据@SessionAttributes生存会话属性@Valid数据校验@RequestHeader获取哀求头参数@CookieValue获取 Cookie 数据异常处理器

SpringMVC 中,异常处理器用于集中处理控制器方法中发生的异常,避免将异常直接暴露给用户,同时可以返回友好的提示信息或进行日志记录。以下是常见的异常处理方式:
1. 使用 @ExceptionHandler 注解

可以在控制器类中定义一个方法,通过 @ExceptionHandler 注解指定要捕获的异常范例。
示例:
  1. @Controller
  2. public class MyController {
  3.     @RequestMapping("/test")
  4.     public String test() {
  5.         throw new RuntimeException("测试异常");
  6.     }
  7.     @ExceptionHandler(RuntimeException.class)
  8.     @ResponseBody
  9.     public String handleRuntimeException(RuntimeException e) {
  10.         return "捕获到异常: " + e.getMessage();
  11.     }
  12. }
复制代码

2. 使用 @ControllerAdvice

@ControllerAdvice 是一个全局异常处理器,实用于所有控制器。
示例:
  1. @ControllerAdvice
  2. public class GlobalExceptionHandler {
  3.     @ExceptionHandler(RuntimeException.class)
  4.     @ResponseBody
  5.     public String handleGlobalRuntimeException(RuntimeException e) {
  6.         return "全局异常处理器捕获: " + e.getMessage();
  7.     }
  8. }
复制代码

3. 实现 HandlerExceptionResolver 接口

可以自定义异常处理器,通过实现 HandlerExceptionResolver 接口来捕获和处理异常。
示例:
  1. @Component
  2. public class MyExceptionResolver implements HandlerExceptionResolver {
  3.     @Override
  4.     public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
  5.         ModelAndView modelAndView = new ModelAndView();
  6.         modelAndView.addObject("error", ex.getMessage());
  7.         modelAndView.setViewName("error"); // 指向 error.jsp
  8.         return modelAndView;
  9.     }
  10. }
复制代码

4. 使用 ResponseStatusExceptionResolver

通过在异常类上添加 @ResponseStatus 注解,指定 HTTP 状态码和原因。
示例:
  1. @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "资源未找到")
  2. public class ResourceNotFoundException extends RuntimeException {
  3. }
复制代码
在控制器中抛出该异常时,会返回对应的 HTTP 状态码和原因。
5. 基于 @RestControllerAdvice

@RestControllerAdvice 是 @ControllerAdvice 的变体,返回值默认是 JSON 格式(结合 @ResponseBody 的功能)。
示例:
  1. @RestControllerAdvice
  2. public class RestGlobalExceptionHandler {
  3.     @ExceptionHandler(RuntimeException.class)
  4.     public Map<String, Object> handleRuntimeException(RuntimeException e) {
  5.         Map<String, Object> response = new HashMap<>();
  6.         response.put("code", 500);
  7.         response.put("message", e.getMessage());
  8.         return response;
  9.     }
  10. }
复制代码

常见的异常范例处理



  1. @ExceptionHandler(MethodArgumentNotValidException.class)
  2. public Map<String, Object> handleValidationException(MethodArgumentNotValidException e) {
  3.     Map<String, Object> errors = new HashMap<>();
  4.     e.getBindingResult().getFieldErrors().forEach(error ->
  5.         errors.put(error.getField(), error.getDefaultMessage())
  6.     );
  7.     return errors;
  8. }
复制代码
选择适合的方式

通过合理设计异常处理器,可以进步体系的健壮性和用户体验。
Rest 风格

Rest 风格简介

REST(Representational State Transfer,表述性状态转移)是一种基于资源的网络架构风格,由 Roy Fielding 在他的博士论文中提出。它是一种设计 API 的方法,使客户端和服务端之间的交互更加简朴、机动和高效。
Rest 风格的核心原则








Rest 风格的 HTTP 哀求方法

HTTP 方法操作示例 URLGET获取资源/users 获取所有用户POST创建资源/users 创建新用户PUT更新资源(全量更新)/users/123 更新用户PATCH更新资源(部分更新)/users/123 更新部分信息DELETE删除资源/users/123 删除用户RESTful 状态码

状态码描述示例200乐成哀求乐成,返回资源数据201已创建乐成创建资源,通常用于 POST204无内容操作乐成,但不返回任何内容(如 DELETE)400客户端错误哀求参数有误401未授权缺少或无效的认证信息403禁止访问客户端无权访问资源404资源未找到哀求的资源不存在500服务器内部错误服务端处理哀求时发生错误示例:Rest 风格的 API

1. 获取所有用户(GET 哀求)
  1. GET /users HTTP/1.1
  2. Host: example.com
  3. Accept: application/json
复制代码
响应:
  1. [
  2.     {
  3.         "id": 1,
  4.         "name": "Alice",
  5.         "email": "alice@example.com"
  6.     },
  7.     {
  8.         "id": 2,
  9.         "name": "Bob",
  10.         "email": "bob@example.com"
  11.     }
  12. ]
复制代码
2. 创建新用户(POST 哀求)
  1. POST /users HTTP/1.1
  2. Host: example.com
  3. Content-Type: application/json
  4. {
  5.     "name": "Charlie",
  6.     "email": "charlie@example.com"
  7. }
复制代码
响应:
  1. HTTP/1.1 201 Created
  2. Location: /users/3
复制代码
3. 更新用户信息(PUT 哀求)
  1. PUT /users/3 HTTP/1.1
  2. Host: example.com
  3. Content-Type: application/json
  4. {
  5.     "name": "Charlie",
  6.     "email": "charlie.new@example.com"
  7. }
复制代码
响应:
  1. HTTP/1.1 200 OK
复制代码
4. 删除用户(DELETE 哀求)
  1. DELETE /users/3 HTTP/1.1
  2. Host: example.com
复制代码
响应:
  1. HTTP/1.1 204 No Content
复制代码
Rest 风格的优点

Rest 风格的局限性

总结

Rest 风格是一种通用的、机动的 API 设计模式,广泛应用于 Web 服务和微服务架构。通过严酷遵守其原则,开发者可以构建出高效、易维护的体系。
拦截器

SpringMVC 中,拦截器(Interceptor)是一种动态拦截哀求并对其进行预处理和后处理的机制,雷同于 Servlet 的过滤器(Filter),但功能更强大且更风雅化。拦截器的核心是实现 HandlerInterceptor 接口或继续其实现类,并通过配置注册到应用程序中。
1. 拦截器的用途

2. 拦截器的核心接口

HandlerInterceptor 接口定义了拦截器的三个核心方法,分别在不同的生命周期阶段调用。
接口方法:
  1. public interface HandlerInterceptor {
  2.     // 在处理请求之前调用
  3.     default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4.         return true;
  5.     }
  6.     // 在处理请求之后,渲染视图之前调用
  7.     default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  8.     }
  9.     // 在整个请求完成之后调用
  10.     default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  11.     }
  12. }
复制代码






















3. 拦截器的实现

实现 HandlerInterceptor 接口或继续其默认实现类 HandlerInterceptorAdapter。
示例:简朴的日志拦截器
  1. @Component
  2. public class LoggingInterceptor implements HandlerInterceptor {
  3.     @Override
  4.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  5.         System.out.println("preHandle: 请求路径是 " + request.getRequestURI());
  6.         return true; // 返回 true 表示继续执行
  7.     }
  8.     @Override
  9.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  10.         System.out.println("postHandle: 处理完成,但视图还未渲染");
  11.     }
  12.     @Override
  13.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  14.         System.out.println("afterCompletion: 请求已完成,视图已渲染");
  15.     }
  16. }
复制代码
4. 拦截器的注册

拦截器需要注册到 SpringMVC 的拦截器链中,通过实现 WebMvcConfigurer 来完成。
注册示例:
  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3.     @Override
  4.     public void addInterceptors(InterceptorRegistry registry) {
  5.         registry.addInterceptor(new LoggingInterceptor())
  6.                 .addPathPatterns("/**") // 拦截所有路径
  7.                 .excludePathPatterns("/login", "/error"); // 排除路径
  8.     }
  9. }
复制代码
5. 多拦截器的执行顺序

多个拦截器按注册顺序执行:
示例 1:


示例 2:
  1. @Override
  2. public void addInterceptors(InterceptorRegistry registry) {
  3.     registry.addInterceptor(new FirstInterceptor());
  4.     registry.addInterceptor(new SecondInterceptor());
  5. }
复制代码
执行顺序:
小结:
6. 与过滤器的区别

特性拦截器(Interceptor)过滤器(Filter)工作层级SpringMVC 层Servlet 容器层拦截对象控制器(Handler)所有哀求(静态资源也可拦截)功能扩展可以访问 Spring 上下文,支持依赖注入无法直接访问 Spring 上下文配置方式Spring 配置类web.xml或 @WebFilter注解7. 常见场景

  1. @Component
  2. public class AuthInterceptor implements HandlerInterceptor {
  3.     @Override
  4.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  5.         HttpSession session = request.getSession();
  6.         if (session.getAttribute("user") == null) {
  7.             response.sendRedirect("/login");
  8.             return false; // 阻止后续处理
  9.         }
  10.         return true;
  11.     }
  12. }
复制代码
通过合理设计和注册拦截器,可以明显提升应用的扩展性和机动性。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4