统一异常处理

统一异常处理类

  1. import com.honghe.managerTool.config.exception.MySecurityException;
  2. import com.honghe.managerTool.entity.Result;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.web.bind.annotation.ControllerAdvice;
  6. import org.springframework.web.bind.annotation.ExceptionHandler;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. /**
  9. * @ControllerAdvice //处理所有
  10. * @ControllerAdvice(annotations=RestController.class) //处理这个类下的异常
  11. * @ControllerAdvice(basePackages={"com.honghe.managerTool.controller"}) //处理包下的异常
  12. */
  13. @ControllerAdvice
  14. public class GlobalExceptionHandler {
  15. private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
  16. /**
  17. * //处理需要处理的异常类
  18. * @ExceptionHandler(value={RuntimeException.class,MyRuntimeException.class})
  19. * @ExceptionHandler //处理所有异常
  20. * @ExceptionHandler(MySecurityException.class) //处理专门的异常
  21. */
  22. @ResponseBody//返回字符串
  23. @ExceptionHandler
  24. public Result exceptionHandler(Exception e) {
  25. if (e instanceof MySecurityException){
  26. MySecurityException me = (MySecurityException)e;
  27. //logger.error("权限异常",e);
  28. return new Result(me.getCode(),false,e.getMessage());
  29. }else if (e instanceof NullPointerException){
  30. logger.error("空指针异常",e);
  31. return new Result(-3,false,"空指针异常");
  32. }else{
  33. return new Result(-3,false,"异常");
  34. }
  35. }
  36. }

2.统一异常处理 - 图1
自定义异常类

  1. /**
  2. * 权限验证异常
  3. * @author zhaojianyu
  4. */
  5. public class MySecurityException extends RuntimeException {
  6. private Integer code;
  7. /**
  8. * 无参构造方法
  9. */
  10. public MySecurityException(){
  11. super();
  12. }
  13. /**
  14. * 有参的构造方法
  15. */
  16. public MySecurityException(String message,Integer code){
  17. super(message);
  18. this.code = code;
  19. }
  20. /**
  21. * 用指定的详细信息和原因构造一个新的异常
  22. */
  23. public MySecurityException(String message, Throwable cause){
  24. super(message,cause);
  25. }
  26. /**
  27. * 用指定原因构造一个新的异常
  28. */
  29. public MySecurityException(Throwable cause) {
  30. super(cause);
  31. }
  32. public Integer getCode() {
  33. return code;
  34. }
  35. public void setCode(Integer code) {
  36. this.code = code;
  37. }
  38. }

抛出自定义异常

  1. throw new MySecurityException("请求超时,请同步服务器时间",-2);

返回值代码枚举类

  1. /**
  2. *
  3. * 返回值枚举类
  4. * @author: zhaojianyu
  5. * @create: 2018-10-11 17:50
  6. **/
  7. public enum ResultEnum {
  8. /**
  9. * 异常信息
  10. */
  11. UNKONW_ERROR(-1,"未知错误"),
  12. SUCCESS(0,"请求成功"),
  13. SECURITY_EXCEPTION(-2,"权限异常"),
  14. PARAMS_EXCEPTION(-3,"权限异常")
  15. ;
  16. private Integer code;
  17. private String message;
  18. ResultEnum() {
  19. }
  20. ResultEnum(Integer code, String message) {
  21. this.code = code;
  22. this.message = message;
  23. }
  24. public Integer getCode() {
  25. return code;
  26. }
  27. public void setCode(Integer code) {
  28. this.code = code;
  29. }
  30. public String getMessage() {
  31. return message;
  32. }
  33. public void setMessage(String message) {
  34. this.message = message;
  35. }
  36. }

统一处理校验异常

针对参数校验 会发生以下三种异常

  • @RequestBody 可以标注在实体上 校验失败抛出异常: MethodArgumentNotValidException
  • @PathVariable 以及 @RequestParam 时 直接标注在方法参数上,同时需要在controller类上加上 @Validated 进行标注 校验失败抛出异常: ConstraintViolationException
  • 当get请求中 参数为实体时, 校验失败会抛出 BindException
  1. import com.tinet.smartlink.commons.mvc.response.ApiResponseEntity;
  2. import com.tinet.smartlink.commons.mvc.response.ErrorCode;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.http.ResponseEntity;
  5. import org.springframework.validation.BindException;
  6. import org.springframework.validation.BindingResult;
  7. import org.springframework.validation.FieldError;
  8. import org.springframework.web.bind.MethodArgumentNotValidException;
  9. import org.springframework.web.bind.annotation.ExceptionHandler;
  10. import org.springframework.web.bind.annotation.ResponseBody;
  11. import org.springframework.web.bind.annotation.RestControllerAdvice;
  12. import org.springframework.web.context.request.WebRequest;
  13. import javax.validation.ConstraintViolationException;
  14. import java.util.*;
  15. /**
  16. * 统一异常处理
  17. * @author zhaojy
  18. */
  19. @Slf4j
  20. @RestControllerAdvice
  21. public class GlobalExceptionHandler {
  22. /**
  23. * 参数校验统一异常处理
  24. */
  25. @ResponseBody
  26. @ExceptionHandler(value = {ConstraintViolationException.class, MethodArgumentNotValidException.class, BindException.class})
  27. public ResponseEntity<Object> handleMethodArgumentException(Exception e, WebRequest request) {
  28. StringBuilder message = new StringBuilder("[参数校验失败]: ");
  29. Map<String, Object> map = null;
  30. if (e instanceof MethodArgumentNotValidException) {
  31. BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
  32. message.append(getExceptionMessageMap(bindingResult));
  33. } else if (e instanceof ConstraintViolationException) {
  34. message.append(e.getMessage());
  35. } else if (e instanceof BindException) {
  36. message.append(getExceptionMessageMap((BindingResult) e));
  37. }
  38. log.warn(message.toString());
  39. return ApiResponseEntity.error(ErrorCode.InvalidParameter, message.toString()).toResponseEntity();
  40. }
  41. /**
  42. * 获取校验失败字段 及message
  43. *
  44. * @param bindingResult 结果
  45. * @return 空map 或 错误信息map
  46. */
  47. private Map<String, Object> getExceptionMessageMap(BindingResult bindingResult) {
  48. Map<String, Object> map;
  49. if (Objects.isNull(bindingResult)){
  50. return new HashMap<>(1);
  51. }
  52. if (bindingResult.hasErrors()) {
  53. List<FieldError> fieldErrors = bindingResult.getFieldErrors();
  54. map = new HashMap<>(fieldErrors.size());
  55. fieldErrors.forEach(error -> map.put(error.getField(), error.getDefaultMessage()));
  56. } else {
  57. map = new HashMap<>(1);
  58. }
  59. return map;
  60. }
  61. }

参考视频连接
https://www.bilibili.com/video/av62728471