zoukankan      html  css  js  c++  java
  • Springboot全局异常处理案例--@ControllerAdvice

    image

    源码在最后

    1.添加依赖

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.72</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
    

    2.自定义一个错误接口类,包含错误码和错误信息

    package com.example.demo.util;
    
    /**
     * @author lyd
     * @Description:
     * @date 16:15
     */
    public interface BaseErrorInfoInterface {
    
    
    	/**
    	 * 得到错误码
    	 *
    	 * @return {@link String}
    	 */
    	String getResultCode();
    
    	/**
    	 * 得到错误信息
    	 *
    	 * @return {@link String}
    	 */
    	String getResultMsg();
    
    }
    

    3.自定义一个枚举类,实现错误接口类,在这个枚举里面自定义一些错误类型

    package com.example.demo.util;
    
    
    /**
     * 常见的枚举
     *
     * @author lyd
     * @Description: 自定义枚举类
     * @date 16:16
     */
    public enum CommonEnum implements BaseErrorInfoInterface {
    
    	SUCCESS("200", "成功"),
    	BODY_NOT_MATCH("400", "请求的数据格式不符"),
    	SIGNATURE_NOT_MATCH("401", "请求的数字签名不匹配!"),
    	OT_FOUND("404", "未找到该资源!"),
    	INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),
    	SERVER_BUSY("503", "服务器正忙,请稍后再试!");
    
    	/**
    	 * 错误码
    	 */
    	private String resultCode;
    
    	/**
    	 * 错误描述
    	 */
    	private String resultMsg;
    
    	CommonEnum(String resultCode, String resultMsg) {
    		this.resultCode = resultCode;
    		this.resultMsg = resultMsg;
    	}
    
    	@Override
    	public String getResultCode() {
    		return resultCode;
    	}
    
    	@Override
    	public String getResultMsg() {
    		return resultMsg;
    	}
    }
    

    4.自定义一个异常类,等会处理业务异常的时候用

    package com.example.demo.exception;
    
    import com.example.demo.util.BaseErrorInfoInterface;
    
    /**
     * @author lyd
     * @Description: 自定义异常类
     * @date 16:25
     */
    public class BizException extends RuntimeException {
    
    
    	/**
    	 * 错误代码
    	 */
    	private String errorCode;
    	/**
    	 * 错误信息
    	 */
    	private String errorMsg;
    
    	public BizException() {
    		super();
    	}
    
    	public BizException(String message, String errorMsg) {
    		super(message);
    		this.errorMsg = errorMsg;
    	}
    
    	public BizException(String message, String errorCode, String errorMsg) {
    		super(message);
    		this.errorCode = errorCode;
    		this.errorMsg = errorMsg;
    	}
    
    	public BizException(BaseErrorInfoInterface baseErrorInfoInterface) {
    		super(baseErrorInfoInterface.getResultCode());
    		this.errorCode = baseErrorInfoInterface.getResultCode();
    		this.errorMsg = baseErrorInfoInterface.getResultMsg();
    	}
    
    	public BizException(BaseErrorInfoInterface baseErrorInfoInterface, Throwable cause) {
    		super(baseErrorInfoInterface.getResultCode(), cause);
    		this.errorCode = baseErrorInfoInterface.getResultCode();
    		this.errorMsg = baseErrorInfoInterface.getResultMsg();
    	}
    
    	public BizException(Throwable cause, String errorCode, String errorMsg) {
    		super(errorCode, cause);
    		this.errorCode = errorCode;
    		this.errorMsg = errorMsg;
    	}
    
    	public String getErrorCode() {
    		return errorCode;
    	}
    
    	public void setErrorCode(String errorCode) {
    		this.errorCode = errorCode;
    	}
    
    	public String getErrorMsg() {
    		return errorMsg;
    	}
    
    	public void setErrorMsg(String errorMsg) {
    		this.errorMsg = errorMsg;
    	}
    
    	@Override
    	public synchronized Throwable fillInStackTrace() {
    		return super.fillInStackTrace();
    	}
    }
    

    5.再定义一个数据响应格式,便于数据交互

    package com.example.demo.util;
    
    import com.alibaba.fastjson.JSONObject;
    
    /**
     * @author lyd
     * @Description: 自定义数据传输格式
     * @date 16:40
     */
    public class ResultBody {
    
    	/**
    	 * 响应代码
    	 */
    	private String code;
    	/**
    	 * 响应消息
    	 */
    	private String message;
    	/**
    	 * 响应结果
    	 */
    	private Object result;
    
    	public ResultBody() {
    	}
    
    	public ResultBody(BaseErrorInfoInterface baseErrorInfoInterface) {
    		this.code = baseErrorInfoInterface.getResultCode();
    		this.message = baseErrorInfoInterface.getResultMsg();
    	}
    
    	/**
    	 * 成功
    	 *
    	 * @param data 数据
    	 * @return {@link ResultBody}
    	 */
    	public static ResultBody success(Object data) {
    		ResultBody resultBody = new ResultBody();
    		resultBody.setCode(CommonEnum.SUCCESS.getResultCode());
    		resultBody.setMessage(CommonEnum.SUCCESS.getResultMsg());
    		resultBody.setResult(data);
    		return resultBody;
    	}
    
    	/**
    	 * 错误
    	 *
    	 * @param errorInfo 错误信息
    	 * @return {@link ResultBody}
    	 */
    	public static ResultBody error(BaseErrorInfoInterface errorInfo) {
    		ResultBody resultBody = new ResultBody();
    		resultBody.setCode(errorInfo.getResultCode());
    		resultBody.setMessage(errorInfo.getResultMsg());
    		resultBody.setResult(null);
    		return resultBody;
    	}
    
    	/**
    	 * 错误
    	 *
    	 * @return {@link ResultBody}
    	 */
    	public static ResultBody error(String code, String message) {
    		ResultBody resultBody = new ResultBody();
    		resultBody.setCode(code);
    		resultBody.setMessage(message);
    		resultBody.setResult(null);
    		return resultBody;
    	}
    
    	public String getCode() {
    		return code;
    	}
    
    	public void setCode(String code) {
    		this.code = code;
    	}
    
    	public String getMessage() {
    		return message;
    	}
    
    	public void setMessage(String message) {
    		this.message = message;
    	}
    
    	public Object getResult() {
    		return result;
    	}
    
    	public void setResult(Object result) {
    		this.result = result;
    	}
    
    	@Override
    	public String toString() {
    		return JSONObject.toJSONString(this);
    	}
    }
    

    6.最关键的一步:自定义一个全局异常处理类,用到两个注解@ControllerAdvice @ExceptionHandler

    package com.example.demo.exception;
    
    import com.example.demo.util.ResultBody;
    import com.example.demo.util.CommonEnum;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @author lyd
     * @Description:自定义全局异常处理类
     * @date 16:12
     */
    @ControllerAdvice
    public class MyExceptionHandler {
    
    	private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class);
    
    	/**
    	 * 自定义的业务异常处理程序
    	 *
    	 * @param httpServletRequest http servlet请求
    	 * @param ex
    	 * @return {@link ResultBody}
    	 */
    	@ExceptionHandler(value = BizException.class)
    	@ResponseBody
    	public ResultBody bizExceptionHandler(HttpServletRequest httpServletRequest, BizException ex) {
    		logger.error("啦啦啦啦啦发生业务异常,原因是:" + ex.getErrorMsg());
    		return ResultBody.error(ex.getErrorCode(), ex.getErrorMsg());
    	}
    
    	/**
    	 * 空指针异常处理程序
    	 *
    	 * @param req 要求的事情
    	 * @param e   e
    	 * @return {@link ResultBody}
    	 */
    	@ExceptionHandler(value = NullPointerException.class)
    	@ResponseBody
    	public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e) {
    		logger.error("啦啦啦啦发生空指针异常!原因是:", e);
    		return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
    	}
    
    	/**
    	 * 其他异常处理程序
    	 *
    	 * @param req 要求的事情
    	 * @param e   e
    	 * @return {@link ResultBody}
    	 */
    	@ExceptionHandler(value = Exception.class)
    	@ResponseBody
    	public ResultBody exceptionHandler(HttpServletRequest req, Exception e) {
    		logger.error("啦啦啦啦发生未知异常!原因是:", e);
    		return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
    	}
    
    }
    

    7.定义一个实体类,等会掉接口测试使用

    package com.example.demo.pojo;
    
    import java.io.Serializable;
    
    /**
     * @author lyd
     * @Description:
     * @date 17:19
     */
    public class User implements Serializable {
    
    	private int id;
    	private String name;
    	private int age;
    
    	public int getId() {
    		return id;
    	}
    
    	public void setId(int id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    }
    

    8.controller层定义几个接口做测试

    package com.example.demo.controller;
    
    import com.example.demo.exception.BizException;
    import com.example.demo.pojo.User;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RestController
    public class UserRestController {
    
    
    	@PostMapping("/user")
    	public boolean insert(User user) {
    		System.out.println("开始新增...");
    		//如果姓名为空就手动抛出一个自定义的异常!
    		if (user.getName() == null) {
    			throw new BizException("-1", "用户姓名不能为空!");
    		}
    		return true;
    	}
    
    	@PutMapping("/user")
    	public boolean update(User user) {
    		System.out.println("开始更新...");
    		//这里故意造成一个空指针的异常,并且不进行处理
    		String str = null;
    		str.equals("111");
    		return true;
    	}
    
    	@DeleteMapping("/user")
    	public boolean delete(User user) {
    		System.out.println("开始删除...");
    		//这里故意造成一个字符转换异常,并且不进行处理
    		Integer.parseInt("abc123");
    		System.out.println("发生异常后继续执行");
    		return true;
    	}
    
    	@GetMapping("/user")
    	public List<User> findByUser(User user) {
    		System.out.println("开始查询...");
    		List<User> userList = new ArrayList<>();
    		User user2 = new User();
    		user2.setId(1);
    		user2.setName("liuliu");
    		user2.setAge(18);
    		userList.add(user2);
    		return userList;
    	}
    
    
    }
    

    最后使用postman测试

    先使用Post请求测试

    image

    image

    可以看到有手动异常抛出

    再测一下Delete请求的,看看自动的捕捉异常

    image
    image

    项目源码

    https://github.com/Wranglery/test-ControllerAdvice

  • 相关阅读:
    nginx
    VSFTPD
    Dubbo
    ZooKeeper
    maven
    linux 学习
    Shiro安全框架
    Jqueryの锋利的jquery练习
    Java中的数组操作进阶
    Java IO总结之缓冲读入文件
  • 原文地址:https://www.cnblogs.com/lyd447113735/p/14980415.html
Copyright © 2011-2022 走看看