优化Wan2.2-T2V-A5B推理效率:数据结构与算法层面的调优实践
2026/3/20 6:26:26
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!
在没有统一异常处理前,你的代码可能是这样的:
@GetMapping("/user/{id}") public ResponseEntity<?> getUser(@PathVariable Long id) { try { User user = userService.findById(id); return ResponseEntity.ok(user); } catch (UserNotFoundException e) { return ResponseEntity.status(404).body("用户不存在"); } catch (Exception e) { log.error("查询用户出错", e); return ResponseEntity.status(500).body("系统繁忙"); } }问题很明显:
try-catch,重复代码多;✅目标:
一处定义,全局生效;结构清晰,前后端解耦;日志完整,便于监控。
@ControllerAdvice+@ExceptionHandlerimport lombok.Data; import java.time.LocalDateTime; @Data public class ApiResult<T> { private int code; private String message; private T data; private LocalDateTime timestamp; public static <T> ApiResult<T> success(T data) { ApiResult<T> result = new ApiResult<>(); result.code = 200; result.message = "success"; result.data = data; result.timestamp = LocalDateTime.now(); return result; } public static <T> ApiResult<T> error(int code, String message) { ApiResult<T> result = new ApiResult<>(); result.code = code; result.message = message; result.timestamp = LocalDateTime.now(); return result; } }💡 前端只需要判断
code == 200就知道成功,无需解析 HTTP 状态码!
public class BusinessException extends RuntimeException { private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(String message) { this(400, message); // 默认 400 } public int getCode() { return code; } }✅ 业务异常 vs 系统异常:
BusinessException:参数错误、余额不足等可预期错误;RuntimeException:空指针、数据库连接失败等不可预期错误。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import java.util.stream.Collectors; @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); // 处理自定义业务异常 @ExceptionHandler(BusinessException.class) public ApiResult<?> handleBusinessException(BusinessException e, HttpServletRequest request) { log.warn("业务异常 | URI: {} | Error: {}", request.getRequestURI(), e.getMessage()); return ApiResult.error(e.getCode(), e.getMessage()); } // 处理参数校验异常(JSR-303) @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ApiResult<?> handleValidationException(MethodArgumentNotValidException e) { String message = e.getBindingResult().getFieldErrors().stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.joining("; ")); log.warn("参数校验失败: {}", message); return ApiResult.error(400, "请求参数错误: " + message); } // 处理路径变量/请求参数类型转换错误 @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ApiResult<?> handleIllegalArgumentException(IllegalArgumentException e) { log.warn("非法参数: {}", e.getMessage()); return ApiResult.error(400, "参数格式错误"); } // 处理所有未捕获的系统异常(兜底) @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ApiResult<?> handleSystemException(Exception e, HttpServletRequest request) { // 生产环境不要暴露堆栈给前端! log.error("系统异常 | URI: {} | Error: {}", request.getRequestURI(), e.getMessage(), e); return ApiResult.error(500, "系统繁忙,请稍后再试"); } }🔑 关键点:
@RestControllerAdvice=@ControllerAdvice+@ResponseBody;- 按异常类型分层处理;
- 生产环境绝不返回
e.printStackTrace()给前端!
@Service public class UserService { public User findById(Long id) { if (id <= 0) { throw new BusinessException("用户ID必须大于0"); } // ... 查询逻辑 if (user == null) { throw new BusinessException(404, "用户不存在"); } return user; } }@RestController @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") public ApiResult<User> getUser(@PathVariable Long id) { User user = userService.findById(id); // 可能抛出 BusinessException return ApiResult.success(user); // 成功时直接返回 } }/api/user/0→ 返回:{ "code": 400, "message": "用户ID必须大于0", "data": null, "timestamp": "2026-01-29T12:00:00" }/api/user/999(不存在)→ 返回:{ "code": 404, "message": "用户不存在", "data": null, "timestamp": "2026-01-29T12:00:01" }✅ 前端只需判断code,无需关心 HTTP 状态码!
// ❌ 重复、难维护、风格不统一 @GetMapping("/user/{id}") public Object getUser(@PathVariable Long id) { try { // ... } catch (Exception e) { return Map.of("error", e.getMessage()); } }@ExceptionHandler(Exception.class) public String handle(Exception e) { return e.toString(); // 😱 前端看到一长串堆栈! }💥 风险:泄露服务器路径、框架版本、数据库结构!
// ❌ HTTP 状态码始终是 200,违背 RESTful 原则 public Map<String, Object> error(String msg) { return Map.of("code", 500, "msg", msg); }✅ 正确:HTTP 状态码 + JSON body 双重语义。
| 场景 | 建议 |
|---|---|
| 敏感信息 | 日志可打 full stack,但返回给前端的 message 要脱敏 |
| 国际化 | message可根据Accept-Language动态切换 |
| 监控告警 | 对5xx异常接入 Prometheus + AlertManager |
| 区分环境 | 开发环境可返回详细错误,生产环境必须隐藏 |
| 异常分类 | 建议定义ClientException(4xx)和ServerException(5xx) |
Controller 方法 ↓ 抛出 BusinessException / ValidationException / Exception ↓ GlobalExceptionHandler 拦截 ↓ 按类型返回标准化 ApiResult ↓ 前端统一处理 code == 200 ?好处:
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!