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

Spring Boot统一功能处理深度解析

第一章:为什么需要统一功能处理?

想象你正在开发一个电商系统,包含用户管理、商品管理、订单管理等模块。每个模块都需要:

  1. 用户身份验证
  2. 操作日志记录
  3. 异常统一处理
  4. 数据格式标准化

如果每个模块都单独实现这些功能:

// 用户模块
@PostMapping("/users")
public User createUser(@RequestBody User user) {try {// 1. 验证token// 2. 记录日志// 3. 业务处理// 4. 统一返回格式} catch (Exception e) {// 5. 异常处理}
}// 商品模块
@PostMapping("/products")
public Product createProduct(@RequestBody Product product) {try {// 重复步骤1-5...} catch (Exception e) {// ...}
}

问题暴露

  • 代码重复率高(DRY原则被破坏)
  • 维护困难(修改需多处调整)
  • 系统一致性差(不同开发者实现方式不同)

第二章:Spring Boot统一处理四大核心组件

2.1 拦截器(Interceptor) - 请求的"安检门"

作用:在请求到达Controller前/后执行通用逻辑

public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 1. 从请求头获取Token(就像门卫检查你的门禁卡)String token = request.getHeader("Authorization");// 2. 验证Token是否有效(门卫刷卡机验证)if (!validateToken(token)) {// 3. 无效则拒绝进入(设置401状态码)response.setStatus(401);return false; // 中断请求}return true; // 允许进入}// 验证Token的方法(门卫的验证设备)private boolean validateToken(String token) {// 实际验证逻辑(这里简化为非空检查)return token != null && !token.isEmpty();}
}

通俗解释

  • 这个类就像小区的门卫,检查每个进入的人(请求)
  • preHandle方法:在业主回家前检查门禁卡(Token)
  • 如果门禁卡无效(validateToken返回false),门卫会拒绝进入(返回401状态码)
  • 如果有效,就放行(return true)

配置方式

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 给门卫分配工作区域registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**")   // 保护所有/api路径.excludePathPatterns("/api/login"); // 但登录入口不需要检查}
}

通俗解释

  • 这相当于给门卫划定工作范围:
    • /api/**:需要检查的所有区域
    • /api/login:特殊通道(登录入口),不需要检查
2.2 过滤器(Filter) - 请求的"净化器"

作用:处理HTTP请求/响应的原始数据

public class LoggingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// 1. 记录请求开始时间(水电表开始计数)long startTime = System.currentTimeMillis();// 2. 继续处理请求(让水流/电流继续)chain.doFilter(request, response);// 3. 计算耗时(计算水电用量)long duration = System.currentTimeMillis() - startTime;// 4. 记录日志(生成水电账单)System.out.println("请求耗时: " + duration + "ms");}
}
  • 这个过滤器就像水电表:
    1. 请求开始时记录时间(开水龙头)
    2. chain.doFilter让请求继续处理(水流)
    3. 请求结束后计算耗时(关水龙头,计算用水量)
    4. 记录日志(生成水电账单)

与拦截器区别

特性过滤器(Filter)拦截器(Interceptor)
作用范围Servlet规范Spring MVC特有
依赖不依赖Spring容器依赖Spring容器
获取信息原始HTTP请求/响应HandlerMethod信息
执行顺序最先执行在DispatcherServlet后执行
2.3 切面(AOP) - 功能的"手术刀"

作用:在方法执行前后插入通用逻辑

@Aspect
@Component
public class ServiceMonitorAspect {// 监控Service层方法@Around("execution(* com.example..service.*.*(..))")public Object monitorService(ProceedingJoinPoint pjp) throws Throwable {long start = System.currentTimeMillis();try {return pjp.proceed(); // 执行目标方法} finally {long duration = System.currentTimeMillis() - start;// 记录慢查询if (duration > 500) {log.warn("慢方法: {} 耗时: {}ms", pjp.getSignature(), duration);}}}
}
2.4 控制器增强(@ControllerAdvice) - 全局的"管理员"

作用:统一处理控制器异常和返回格式

@ControllerAdvice
public class GlobalExceptionHandler {// 处理业务异常@ExceptionHandler(BusinessException.class)@ResponseBodypublic ResponseResult<Void> handleBusinessEx(BusinessException e) {return ResponseResult.error(e.getCode(), e.getMessage());}// 处理所有未捕获异常@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseResult<Void> handleException(Exception e) {log.error("系统异常", e);return ResponseResult.error(500, "系统繁忙");}
}

第三章:统一功能处理实战案例

3.1 统一响应格式
// 标准响应体
public class ResponseResult<T> {private int code;private String msg;private T data;// 成功响应public static <T> ResponseResult<T> success(T data) {return new ResponseResult<>(200, "成功", data);}// 错误响应public static <T> ResponseResult<T> error(int code, String msg) {return new ResponseResult<>(code, msg, null);}
}// 控制器统一返回
@RestController
public class UserController {@GetMapping("/users/{id}")public ResponseResult<User> getUser(@PathVariable Long id) {User user = userService.findById(id);return ResponseResult.success(user);}
}
3.2 统一异常处理
@ControllerAdvice // 1. 声明这是全局异常处理器
public class GlobalExceptionHandler {// 2. 处理业务异常(如订单处理失败)@ExceptionHandler(BusinessException.class)@ResponseBodypublic ResponseResult<Void> handleBusinessEx(BusinessException e) {// 返回标准错误格式return ResponseResult.error(e.getCode(), e.getMessage());}// 3. 处理所有未预料异常(系统崩溃)@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseResult<Void> handleException(Exception e) {// 记录错误日志(就像应急系统记录事故)e.printStackTrace();// 返回友好提示return ResponseResult.error(500, "系统繁忙,请稍后再试");}
}
  • @ControllerAdvice:这是整个小区的应急中心
  • @ExceptionHandler:不同类型的应急处理小组
    • BusinessException:处理业务问题(如订单错误)
    • Exception:处理所有未预料的问题(系统崩溃)
  • 当发生问题时,系统会自动调用对应的方法处理
3.3 统一日志记录
@Aspect
@Component
public class ControllerLogAspect {@Around("@within(org.springframework.web.bind.annotation.RestController)")public Object logController(ProceedingJoinPoint pjp) throws Throwable {// 获取请求信息HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();// 记录请求日志log.info("请求开始 => URI: {}, 参数: {}", request.getRequestURI(), Arrays.toString(pjp.getArgs()));long start = System.currentTimeMillis();try {Object result = pjp.proceed();// 记录响应日志log.info("请求完成 <= URI: {}, 耗时: {}ms", request.getRequestURI(), System.currentTimeMillis() - start);return result;} catch (Exception e) {// 记录异常日志log.error("请求异常 <= URI: {}, 错误: {}", request.getRequestURI(), e.getMessage());throw e;}}
}
3.4 统一身份认证
public class JwtAuthInterceptor implements HandlerInterceptor {@Autowiredprivate JwtTokenService tokenService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 1. 获取TokenString token = request.getHeader("Authorization");if (StringUtils.isEmpty(token)) {sendError(response, 401, "未提供认证信息");return false;}// 2. 验证TokenClaims claims = tokenService.parseToken(token);if (claims == null) {sendError(response, 401, "无效的Token");return false;}// 3. 存储用户信息UserContext.setCurrentUser(claims.getSubject());return true;}private void sendError(HttpServletResponse response, int status, String msg) {response.setStatus(status);response.setContentType("application/json");try {response.getWriter().write(new ResponseResult<>(status, msg).toString());} catch (IOException e) {log.error("响应写入失败", e);}}
}

第四章:高级应用场景

4.1 接口限流(Rate Limiting)
@Aspect
@Component
public class RateLimitAspect {private final Map<String, RateLimiter> limiters = new ConcurrentHashMap<>();@Around("@annotation(rateLimit)")public Object rateLimit(ProceedingJoinPoint pjp, RateLimit rateLimit) throws Throwable {String key = getRateLimitKey(pjp);RateLimiter limiter = limiters.computeIfAbsent(key, k -> RateLimiter.create(rateLimit.value()));if (limiter.tryAcquire()) {return pjp.proceed();} else {throw new BusinessException(429, "请求过于频繁");}}private String getRateLimitKey(ProceedingJoinPoint pjp) {// 根据方法+IP生成唯一keyMethodSignature signature = (MethodSignature) pjp.getSignature();HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();return signature.getMethod().getName() + ":" + request.getRemoteAddr();}
}// 使用注解
@GetMapping("/api/data")
@RateLimit(value = 10) // 每秒10次
public ResponseResult<Data> getData() {// ...
}
4.2 多租户数据隔离
public class TenantInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 从请求头获取租户IDString tenantId = request.getHeader("X-Tenant-ID");if (StringUtils.isNotBlank(tenantId)) {TenantContext.setCurrentTenant(tenantId);}return true;}
}// 在MyBatis拦截器中应用
@Intercepts({@Signature(type = Executor.class, method = "query", ...)})
public class TenantInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 自动添加租户过滤条件String tenantId = TenantContext.getCurrentTenant();if (tenantId != null) {MappedStatement ms = (MappedStatement) invocation.getArgs()[0];Object parameter = invocation.getArgs()[1];// 修改SQL添加 tenant_id = #{tenantId}}return invocation.proceed();}
}
4.3 API版本控制
public class ApiVersionInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 从URL路径获取版本号String path = request.getRequestURI();Matcher matcher = Pattern.compile("/v(\\d+)/").matcher(path);if (matcher.find()) {int version = Integer.parseInt(matcher.group(1));ApiVersionContext.setVersion(version);}return true;}
}// 控制器根据版本路由
@RestController
@RequestMapping("/api/users")
public class UserController {@GetMapping@ApiVersion(1) // v1版本public ResponseResult<List<User>> getUsersV1() {// 旧版逻辑}@GetMapping@ApiVersion(2) // v2版本public ResponseResult<List<UserDto>> getUsersV2() {// 新版逻辑}
}

第五章:性能优化与最佳实践

5.1 组件执行顺序优化
请求进入

Filter-Interceptor-preHandle-Controller-Interceptor-postHandle-Filter-after-Response

优化策略

  1. 过滤器优先处理原始数据(如请求体缓存)
  2. 拦截器处理业务相关逻辑(如认证、日志)
  3. 切面处理具体方法逻辑(如性能监控)
  4. @ControllerAdvice最后处理异常和响应
5.2 避免的陷阱
  1. 循环依赖问题

  2. @Component
    public class AuthInterceptor implements HandlerInterceptor {@Autowiredprivate AuthService authService; // 可能导致循环依赖
    }
    

    解决方案:使用@Lazy延迟注入

  3. @Lazy
    @Autowired
    private AuthService authService;
    

    线程安全问题

  4. public class UserContext {private static final ThreadLocal<User> currentUser = new ThreadLocal<>();
    }
    

    性能热点

  5. // 避免在拦截器/过滤器中执行耗时操作
    public boolean preHandle(...) {// 错误:执行数据库查询User user = userRepository.findById(userId);
    }
    
    5.3 最佳实践总结
  6. 职责分离原则

    • 过滤器:处理原始HTTP请求/响应
    • 拦截器:处理业务相关前置/后置逻辑
    • 切面:处理具体方法逻辑
    • 控制器增强:统一异常和响应处理
  7. 配置顺序原则

  8. @Override
    public void addInterceptors(InterceptorRegistry registry) {// 1. 认证拦截器(最先执行)registry.addInterceptor(authInterceptor);// 2. 日志拦截器registry.addInterceptor(logInterceptor);// 3. 其他业务拦截器
    }
    

    性能监控指标

  9. // 使用Micrometer监控
    @Autowired
    private MeterRegistry meterRegistry;public void afterCompletion(...) {meterRegistry.counter("api.requests", "uri", request.getRequestURI(),"status", String.valueOf(response.getStatus())).increment();
    }
    

    第六章:综合实战 - 电商系统统一处理

  6.1 系统架构图

 6.2 核心配置代码

// 网关统一配置
@Configuration
public class GatewayConfig {@Beanpublic GlobalFilter customFilter() {return (exchange, chain) -> {// 1. 统一添加请求IDServerHttpRequest request = exchange.getRequest().mutate().header("X-Request-ID", UUID.randomUUID().toString()).build();return chain.filter(exchange.mutate().request(request).build());};}
}// 微服务统一配置
@Configuration
public class ServiceConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TenantInterceptor());registry.addInterceptor(new AuthInterceptor());}@Beanpublic FilterRegistrationBean<LoggingFilter> loggingFilter() {FilterRegistrationBean<LoggingFilter> bean = new FilterRegistrationBean<>();bean.setFilter(new LoggingFilter());bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;}
}
6.3 业务服务示例
@RestController
@RequestMapping("/orders")
public class OrderController {@PostMappingpublic ResponseResult<Order> createOrder(@Valid @RequestBody OrderCreateDTO dto) {// 无需处理认证、日志、异常等Order order = orderService.createOrder(dto);return

相关文章:

  • 系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
  • 网络安全面试题目(无答案)
  • Next.js中Protected Route(受保护路由)
  • reverse笔记
  • Neo4j 完全指南:从入门到精通
  • 八:操作系统设备管理之缓冲、缓存与假脱机
  • 编程技能:格式化打印05,格式控制符
  • NVM!(可以快速替换你的node版本)
  • 免费wordpress模板下载
  • 神经网络与深度学习 网络优化与正则化
  • 63、.NET 异常处理
  • [QMT量化交易小白入门]-六十一、多因子选股+布林带择时年化收益率21.5%
  • FPGA 的硬件结构
  • 成工fpga(知识星球号)——精品来袭
  • PySpark性能调优手册:大数据处理中的避坑与实践
  • GC1809:高性能24bit/192kHz音频接收芯片解析
  • 《一生一芯》数字实验六:实现随机数发生器
  • Dockerfile实践java项目
  • Postgresql常用函数操作
  • uniapp中使用aixos 报错
  • 企业为什么做网站 图片/企业营销推广策划
  • 政府网站建设招标方案/武汉新闻最新消息
  • 网站怎么能快速备案/网站关键词优化wang
  • 医疗网站的在线聊天怎么做的/seo关键词的选择步骤
  • 济南做网站价格/网站网络排名优化方法
  • 网站建设数据表设计 性别/网店运营推广平台