当前位置: 首页 > 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.dtcms.com/a/328446.html

相关文章:

  • uni-app实战教程 从0到1开发 画图软件 (学会画图)
  • Ceph BlueStore存储引擎详解
  • 【数据结构】并查集:从入门到精通
  • 《Linux基础知识-1》
  • docker-compose搭建 redis 集群
  • 阿里巴巴开源多模态大模型-Qwen-VL系列论文精读(一)
  • VBS 时间函数
  • 基于 libwebsockets 库实现的 WebSocket 服务器类
  • Shader warning in ‘Universal Render Pipeline/Particles/Simple Lit‘
  • provide()函数和inject()函数
  • 【UEFI系列】Super IO
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-语音评测
  • 嵌入式学习(day25)文件IO:open read/write close
  • VGG改进(2):基于Local Attention的模型优化
  • 书籍数组中未出现的最小正整数(8)0812
  • 《飞算JavaAI:新一代智能编码引擎,革新Java研发范式》
  • 跑腿平台开发实战:同城O2O系统源码的模块化与可扩展性方案
  • 每日一练:将一个数字表示成幂的和的方案数;动态规划、深度优先搜索
  • 【Altium designer】快速建立原理图工程的步骤
  • 2025开放计算技术大会|开源开放推动系统创新 加速AIDC全球协作
  • 过拟合、欠拟合与方差/偏差的关系
  • Langchain结合deepseek:框架+模型的AI测试实践
  • 小白学习pid环控制-实现篇
  • 杰里平台7083G 如何支持4M flash
  • 【oracle闪回查询】记录字段短时间被修改的记录
  • MyBatis-Plus核心内容
  • AAC音频编码器技术详解:原理、应用与发展
  • Java数组排序
  • 嵌入式系统分层开发:架构模式与工程实践(四)(状态机的应用和面向对象的编程)
  • redis认识缓存击穿