当前位置: 首页 > news >正文

前后端分离项目中Spring MVC的请求执行流程

在前后端分离架构中,Spring MVC的执行流程与传统服务端渲染模式有显著差异,主要变化在于视图解析响应处理环节。以下是完整的执行流程分析,特别针对RESTful API场景:

一、核心执行流程(RESTful API场景)


二、关键阶段详细解析

1. 请求接收与分发阶段

DispatcherServlet的核心工作

  1. 初始化九大核心组件(包括HandlerMappingHandlerAdapter等)
  2. 处理Content-TypeAccept头部
  3. 处理CORS预检请求(OPTIONS方法)
  4. 根据请求路径选择对应的HandlerMapping

特殊处理

  • 对于application/json内容类型,会启用MappingJackson2HttpMessageConverter
  • 如果请求包含Authorization头,会触发安全过滤器链

2. 处理器映射阶段

HandlerMapping的工作机制

  1. RequestMappingHandlerMapping扫描所有@RestController注解的类
  2. 构建包含以下元素的映射注册表:
    • URL路径模式(支持Ant风格和路径变量)
    • 支持的HTTP方法(GET/POST/PUT等)
    • 消费/生产的媒体类型(consumes/produces)
    • 参数条件(@RequestParam等)
  1. 匹配优先级:
    • 精确路径优先于模式匹配
    • 最长路径模式优先

示例匹配过程

@RestController
@RequestMapping("/api/v1/users")
public class UserController {@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)public UserDTO getUser(@PathVariable Long id) {// ...}
}

当请求GET /api/v1/users/123时:

  1. 匹配到UserController.getUser()方法
  2. 提取路径变量id=123
  3. 确认produces类型匹配

3. 参数绑定阶段

参数解析器链(HandlerMethodArgumentResolver)

参数类型

对应解析器

典型注解

URL路径参数

PathVariableMethodArgumentResolver

@PathVariable

查询参数

RequestParamMethodArgumentResolver

@RequestParam

JSON/XML请求体

RequestResponseBodyMethodProcessor

@RequestBody

请求头

RequestHeaderMethodArgumentResolver

@RequestHeader

Cookie值

ServletCookieValueMethodArgumentResolver

@CookieValue

Session属性

SessionAttributeMethodArgumentResolver

@SessionAttribute

复杂参数绑定示例

@PostMapping("/search")
public PageResult<UserDTO> searchUsers(@RequestBody UserQuery query,@RequestHeader("X-Auth-Token") String token,@Valid PageRequest pageRequest) {// ...
}

4. 业务处理阶段

控制器的典型职责

  1. 参数验证(结合JSR-303)
  2. 业务逻辑编排
  3. 异常捕获与转换
  4. 返回领域对象或DTO

RESTful最佳实践

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<UserDTO> createUser(@Valid @RequestBody UserCreateDTO dto) {UserDTO created = userService.createUser(dto);URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(created.getId()).toUri();return ResponseEntity.created(location).body(created);
}

5. 返回值处理阶段

ResponseBody处理机制

  1. RequestResponseBodyMethodProcessor处理返回值
  2. 选择匹配的HttpMessageConverter
    • MappingJackson2HttpMessageConverter:处理JSON
    • MappingJackson2XmlHttpMessageConverter:处理XML
    • ByteArrayHttpMessageConverter:处理字节数组
  1. 根据Accept头决定响应格式

转换器选择算法

  1. 检查控制器方法声明的produces类型
  2. 检查请求的Accept头
  3. 按照转换器注册顺序选择第一个能处理的

三、前后端分离特有处理

1. 统一响应封装模式

响应体封装策略

public class ApiResult<T> {private long timestamp = System.currentTimeMillis();private String code;private String message;private T data;public static <T> ApiResult<T> success(T data) {return new ApiResult<>("200", "success", data);}// 工厂方法省略...
}

通过ControllerAdvice实现统一包装

@RestControllerAdvice
public class ResponseWrapper implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {// 不包装已经封装的结果或特定类型return !returnType.getParameterType().equals(ApiResult.class) && !returnType.hasMethodAnnotation(NoWrapper.class);}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {return ApiResult.success(body);}
}

2. 全局异常处理机制

异常处理中心

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ResponseEntity<ApiResult<Void>> handleBusinessException(BusinessException ex) {return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ApiResult.error(ex.getErrorCode(), ex.getMessage()));}@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public ApiResult<Map<String, String>> handleValidationException(MethodArgumentNotValidException ex) {Map<String, String> errors = ex.getBindingResult().getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,fieldError -> Optional.ofNullable(fieldError.getDefaultMessage()).orElse("")));return ApiResult.error("VALIDATION_FAILED", "参数校验失败", errors);}
}

3. 跨域解决方案

精细化CORS配置

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("https://frontend.com").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("Content-Type", "Authorization").exposedHeaders("X-Custom-Header").allowCredentials(true).maxAge(3600);}
}

四、性能优化关键点

1. 消息转换器优化

Jackson自定义配置

@Configuration
public class JacksonConfig {@Beanpublic Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {return builder -> {builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");builder.timeZone(TimeZone.getTimeZone("Asia/Shanghai"));builder.modules(new JavaTimeModule());builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);builder.featuresToEnable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL,MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);};}
}

2. 异步处理模式

异步控制器实现

@RestController
@RequestMapping("/async")
public class AsyncController {@GetMapping("/data")public CompletableFuture<ApiResult<Data>> fetchData() {return CompletableFuture.supplyAsync(() -> {// 模拟耗时操作try { Thread.sleep(1000); } catch (InterruptedException e) { /*...*/ }return dataService.getComplexData();}).thenApply(ApiResult::success);}@GetMapping("/deferred")public DeferredResult<ApiResult<Data>> deferredResult() {DeferredResult<ApiResult<Data>> result = new DeferredResult<>(5000L);CompletableFuture.runAsync(() -> {try {Data data = dataService.getComplexData();result.setResult(ApiResult.success(data));} catch (Exception e) {result.setErrorResult(e);}});return result;}
}

五、安全防护措施

1. 输入验证体系

DTO验证示例

public class UserCreateDTO {@NotBlank(message = "用户名不能为空")@Size(min = 4, max = 20, message = "用户名长度4-20个字符")private String username;@Email(message = "邮箱格式不正确")private String email;@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$",message = "密码必须至少8个字符,包含字母和数字")private String password;@AssertTrue(message = "必须接受用户协议")private boolean acceptedTerms;
}

2. 防XSS/CSRF策略

XSS过滤配置

@Bean
public FilterRegistrationBean<XssFilter> xssFilter() {FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new XssFilter());registration.addUrlPatterns("/api/*");registration.setOrder(Ordered.HIGHEST_PRECEDENCE);return registration;
}public class XssFilter extends OncePerRequestFilter {private final XssCleaner xssCleaner = new DefaultXssCleaner();@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws IOException, ServletException {chain.doFilter(new XssRequestWrapper(request, xssCleaner), response);}
}

通过以上深度解析,开发者可以全面掌握前后端分离架构下Spring MVC的完整工作流程,包括从请求接收到响应返回的每个关键环节,以及针对RESTful API场景的特殊处理方式和优化策略。

http://www.lryc.cn/news/619158.html

相关文章:

  • Kubernetes 资源管理全解析:从基础到企业级实践
  • TDengine 可观测性最佳实践
  • VBS 时间函数
  • 移动端网页调试实战,键盘弹出与视口错位问题的定位与优化
  • 需求跟踪矩阵是什么
  • mysql参数调优之 sync_binlog (二)
  • python技巧:控制转台的2个坑。
  • [激光原理与应用-253]:理论 - 几何光学 - 变焦镜头的组成原理及图示解析
  • 分布式事务Seata使用不当引发的全局锁问题
  • hashmap如何解决碰撞
  • JavaWeb从入门到精通!第二天!(Servlet)
  • 揭开Spectre漏洞的神秘面纱
  • 【后端】Spring @Resource和@Autowired的用法和区别
  • 告别数据孤岛!React 路由 3 种传参方法全解析
  • [Robotics_py] 定位滤波器 | 预测与更新 | 扩展卡尔曼滤波器(`EKF`)
  • 嵌入式学习 标准IO(完整版)
  • 浏览器面试题及详细答案 88道(12-22)
  • 【C#补全计划】StringBuilder
  • 【shell脚本编程】-4 shell脚本编写冒泡排序
  • C++11新增关键字和范围for循环
  • Flutter ExpansionPanel组件(可收缩的列表)
  • Qt中定时器介绍和使用
  • Gradle(二)Gradle的优势、项目结构介绍
  • python2操作neo4j
  • HTTPS加密与私有CA配置全攻略
  • spring-cloud整合nacos详细攻略
  • 读《精益数据分析》:UGC平台的数据指标梳理
  • 11-docker单机版的容器编排工具docker-compose基本使用
  • 数据分析专栏记录之 -基础数学与统计知识
  • Threejs 设置灯光照射点位置 辅助器不跟随移动