Spring校验注解3:异常统一处理类

Easter79
• 阅读 726

@ControllerAdvice

该注解为统一异常处理的核心

是一种作用于控制层的切面通知(Advice),该注解能够将通用的@ExceptionHandler、@InitBinder和@ModelAttributes方法收集到一个类型,并应用到所有控制器上

该类中的设计思路:

  • 使用@ExceptionHandler注解捕获指定或自定义的异常;

  • 使用@ControllerAdvice集成@ExceptionHandler的方法到一个类中;

  • 必须定义一个通用的异常捕获方法,便于捕获未定义的异常信息;

  • 自定一个异常类,捕获针对项目或业务的异常;

  • 异常的对象信息补充到统一结果枚举中;

自定义全局异常类

import com.example.demo.util.R;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 全局异常处理类
 */
@ControllerAdvice
public class CommonExceptionHandler {

    /**
     * 通用异常处理
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R exceptionHandler(Exception ex) {
        //输出异常信息
        ex.printStackTrace();
        //处理校验注解异常信息
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException mex = (MethodArgumentNotValidException) ex;
            List<FieldError> errorList = mex.getBindingResult().getFieldErrors();
            StringBuffer strBuffer = new StringBuffer();
            for(FieldError err: errorList){
                strBuffer.append(err.getDefaultMessage()).append(",");
            }
            return R.failed(strBuffer.substring(0, strBuffer.length() - 1));
        } else {
            return R.failed(ex.getMessage());
        }
    }

    /**
     * 单独针对某个异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException e) {
        //输出异常信息
        e.printStackTrace();
        return R.failed("空指针异常");
    }
}

这就是主要核心的代码。

SpringBoot代码示例

1.项目目录:

Spring校验注解3:异常统一处理类

2.Controller代码:

import com.example.demo.model.User;
import com.example.demo.util.R;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * 用户登录控制器
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {

    /**
     * 用户登录
     * @param user
     * @return
     */
    @PostMapping(value = "/login")
    public R login(@Valid @RequestBody User user){
        System.out.println("登录成功!");
        return R.ok(user);
    }

}

3.User实体类

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

/**
 * 用户登录实体类
 */
@Data
public class User {

    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Size(max = 20, min = 6, message = "密码长度在6-20字符之间")
    private String password;

}

4.ApiCode枚举

/**
 * api枚举器
 */
public enum ApiCode {

    FAILED(-1L, "操作失败"),
    SUCCESS(0L, "执行成功");

    private final long code;
    private final String msg;

    private ApiCode(long code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public long getCode() {
        return this.code;
    }

    public String getMsg() {
        return this.msg;
    }

}

5.R返回对象参考了mybatis-plus中R对象的设计

import com.example.demo.myenum.ApiCode;
import lombok.Data;

/**
 * 返回对象
 */
@Data
public class R<T> {

    private long code;
    private String msg;
    private T data;

    public R() {
    }

    public static <T> R<T> ok(T data) {
        ApiCode aec = ApiCode.SUCCESS;
        if(data instanceof Boolean && Boolean.FALSE.equals(data)) {
            aec = ApiCode.FAILED;
        }

        return restResult(data, aec.getCode(), aec.getMsg());
    }

    public static <T> R<T> failed(String msg) {
        return restResult(null, ApiCode.FAILED.getCode(), msg);
    }

    private static <T> R<T> restResult(T data, long code, String msg) {
        R<T> apiResult = new R();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }

}

PostMan请求测试

Spring校验注解3:异常统一处理类

看到这个结果我们的全局统一处理注解校验异常就成功了。

更多阅读

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
spring注解
随着越来越多地使用Springboot敏捷开发,更多地使用注解配置Spring,而不是Spring的applicationContext.xml文件。Configuration注解:Spring解析为配置类,相当于spring配置文件Bean注解:容器注册Bean组件,默认id为方法名@Configurat
Easter79 Easter79
3年前
Spring的AOP的注解的通知类型,切入点的注解
Spring的注解的AOP的通知类型@Before:前置通知@AfterReturning:后置通知@Around:环绕通知@AfterThrowing:异常抛出通知@After:最终通知@Pointcut:切入点的注解1/
Easter79 Easter79
3年前
Spring注解大全,汇总版
Spring使用的注解大全和解释注解解释@Controller组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。@Service组合注解(组合了@Component注解),应用在
Stella981 Stella981
3年前
Spring Boot @ControllerAdvice+@ExceptionHandler处理controller异常
需求:  1.springboot 项目restful 风格统一放回json  2.不在controller写trycatch代码块简洁controller层  3.对异常做统一处理,同时处理@Validated校验器注解的异常方法:  @ControllerAdvice注解定义全局异常处理类@ControllerAdvice
Easter79 Easter79
3年前
Spring异常处理
@ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度@ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开@ResponseStatus:可以将某种异常映射为HTTP状态码@ControllerAdvicepublicclassExceptio
Stella981 Stella981
3年前
Spring Boot实践——统一异常处理
注解说明@ControllerAdvice,是Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强。让我们先看看@ControllerAdvice的实现:/Specializationof{@linkComponent@Component}forclassesthatdecl
@ControllerAdvice注解使用及原理探究 | 京东物流技术团队
最近在新项目的开发过程中,遇到了个问题,需要将一些异常的业务流程返回给前端,需要提供给前端不同的响应码,前端再在次基础上做提示语言的国际化适配。这些异常流程涉及业务层和控制层的各个地方,如果每个地方都写一些重复代码显得很冗余。然后查询解决方案时发现了@ControllerAdvice这个注解,可以对业务异常进行统一处理。经过仔细了解后,发现这个注解还有更多的用处,都很实用。
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k