package com.yunhai.bschclassmanage.controller.Handler; import com.yunhai.platform.utils.exception.DException; import com.yunhai.platform.utils.exception.ErrorCode; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; @Order(Ordered.HIGHEST_PRECEDENCE) @RestControllerAdvice public class ValidationExceptionHandler { /** * 兜底 DException:平台 GlobalExceptionHandler 只返回 code/msg,会丢掉 data。 * 本项目优先捕获,把业务异常里的 data(如导入错误列表)透传给前端。 */ @ExceptionHandler(DException.class) public ResponseEntity> handleDException(DException ex) { Map response = new LinkedHashMap<>(); response.put("code", ex.getCode() != null ? ex.getCode().getCode() : ErrorCode.CUSTOM.getCode()); response.put("msg", ex.getMessage()); response.put("data", ex.getData()); response.put("timeNow", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return new ResponseEntity<>(response, HttpStatus.OK); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity> handleValidationExceptions(MethodArgumentNotValidException ex) { List msgList = new ArrayList<>(); ex.getBindingResult().getAllErrors().forEach(error -> { String errorMessage = error.getDefaultMessage(); msgList.add(errorMessage); }); Map response = new LinkedHashMap<>(); response.put("code", ErrorCode.ERROR.getCode()); response.put("msg", String.join(";", msgList)); response.put("data", null); response.put("timeNow", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return new ResponseEntity(response, HttpStatus.BAD_REQUEST); } /** * @RequestBody 反序列化失败(JSON 格式错 / 字段类型不符 / 未知字段被拒)。 * 不捕获会被平台兜底成 code:6 / 内部服务错误,这里把真实原因透出来。 */ @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity> handleNotReadable(HttpMessageNotReadableException ex) { Map response = new LinkedHashMap<>(); response.put("code", ErrorCode.ERROR.getCode()); response.put("msg", "请求体(JSON)解析失败: " + (ex.getRootCause() != null ? ex.getRootCause().getMessage() : ex.getMessage())); response.put("data", null); response.put("timeNow", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return new ResponseEntity(response, HttpStatus.BAD_REQUEST); } /** * Content-Type 不是 application/json(如 text/plain、form 表单、缺省),@RequestBody 无法选择转换器。 */ @ExceptionHandler(HttpMediaTypeNotSupportedException.class) public ResponseEntity> handleMediaType(HttpMediaTypeNotSupportedException ex) { Map response = new LinkedHashMap<>(); response.put("code", ErrorCode.ERROR.getCode()); response.put("msg", "请求 Content-Type 不被支持: " + ex.getMessage()); response.put("data", null); response.put("timeNow", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return new ResponseEntity(response, HttpStatus.BAD_REQUEST); } }