第五课:springboot实现全局异常处理

简介

项目中经常会碰到各种各样的异常处理,如果在项目各个地方都通过
try{
}catch{
}
就会觉得代码很凌乱,而且我们需要对代码中的异常进行包装;不能吧对应的异常信息直接返回给上游.
正常的操作使用统一的异常处理内容;
同时根据异常码给定指定的异常信息内容; 通常我们可以配置在对于的properties文件中;或者存放到指定的redis缓存中去;对于从缓存中获取比较简单结合项目直接使用;
本案例是通过读取本地properties文件中的code->msg来处理的;
项目demo下载

项目的结构

在这里插入图片描述

代码内容

1.pom文件

pom文件内容

2.启动的main方法

springboot 项目的启动入口类

@SpringBootApplication
public class MainApplication {
	public static void main(String[] args) throws Exception {
		SpringApplication.run(MainApplication.class, args);
	}

}

3. GlobalExceptionHandler

全局的异常处理类,在当前类里面定义各种exception类的处理方式;
案例中我们自定义的 BusinessException 里面通过异常code 来获取对于的msg

@RestController
@ControllerAdvice
public class GlobalExceptionHandler {
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private static final String ASSERT_ERROR_CODE ="10000";
	private static final String SYSTEM_ERROR_CODE ="20000";
			
	@ExceptionHandler(value = BusinessException.class)
	@ResponseBody
	public Object businessException(HttpServletRequest req, Exception e) throws Exception {
		boolean instance = BusinessException.class.isInstance(e);
		if (instance) {
			BusinessException bex = (BusinessException) e;
			JSONObject json = new JSONObject();
			json.put("retCode", bex.getErrorCode());
			json.put("retMsg", bex.getErrorMsg());
			json.put("path", req.getRequestURI());
			json.put("timestamp", sdf.format(new Date()));
			return json;
		}
		return "---BusinessException Handler---:" + e.getMessage();
	}

	@ExceptionHandler(value = IllegalArgumentException.class)
	@ResponseBody
	public Object testException(HttpServletRequest req, Exception e) throws Exception {
		boolean instance = IllegalArgumentException.class.isInstance(e);
		if (instance) {
			IllegalArgumentException bex = (IllegalArgumentException) e;
			JSONObject json = new JSONObject();
			json.put("retCode", ASSERT_ERROR_CODE);//标识统一的断言的异常信息
			json.put("retMsg", PropertiesResource.getMessage(ASSERT_ERROR_CODE));
			json.put("retDesc", bex.getMessage());
			json.put("path", req.getRequestURI());
			json.put("timestamp", sdf.format(new Date()));
			return json;
		}
		return "---IllegalArgumentException Handler---:" + e.getMessage();
	}

	@ExceptionHandler(value = Exception.class)
	@ResponseBody
	public Object exception(HttpServletRequest req, Exception e) throws Exception {
		JSONObject json = new JSONObject();
		json.put("retCode", SYSTEM_ERROR_CODE);//标识统一的断言的异常信息
		json.put("retMsg", PropertiesResource.getMessage(SYSTEM_ERROR_CODE));
		json.put("retDesc", e.getMessage());
		json.put("path", req.getRequestURI());
		json.put("timestamp", sdf.format(new Date()));
		return json;
	}

4. BusinessException

我们自定义的exception类, 里面新增errorCode 和errorMsg字段
当我们往外抛出异常的时间指定对于的errorCode 然后在当前方法里面设置
errorMsg 主要是通过 PropertiesResource 来实现的内容;

public class BusinessException extends RuntimeException {
	private static final long serialVersionUID = 1L;
	private String errorCode;
	private String errorMsg;

	public BusinessException(String exceptionCode) {
		this.errorCode = exceptionCode;
		this.errorMsg = PropertiesResource.getMessage(exceptionCode);
	}

	public BusinessException(String exceptionCode,String errorMsg) {
		this.errorCode = exceptionCode;
		this.errorMsg = errorMsg;
	}

	public BusinessException(String exceptionCode, String errorMsg, Throwable cause) {
		super(cause);
		this.errorCode = exceptionCode;
		this.errorMsg = errorMsg;
	}
	// ..get/set 省略..
}

5. PropertiesResource

当前类似一个工具类吧properties文件中的异常码对于的 异常信息给加载进来
static 代码块中指定需要加载的properties文件的地址;

public class PropertiesResource {
    private static ReloadableResourceBundleMessageSource i18nMessage ;

    public PropertiesResource() {
    }

    public static String getMessage(String messageKey, Object[] messageArgs) {
        String message = null;
        try {
            message = i18nMessage.getMessage(messageKey, messageArgs, LocaleContextHolder.getLocale());
        } catch (MissingResourceException var4) {
            message = "i18nMessage is: " + messageKey + ", can't get the I18n properties";
        } catch (Throwable var5) {
            message = "i18nMessage is: " + messageKey + ", can't get the I18n properties";
        }
        return message;
    }

    public static String getMessage(String messageKey) {
        return getMessage(messageKey, (Object[])null);
    }
    static {
    	i18nMessage	= new ReloadableResourceBundleMessageSource();
    	//读取message.properties文件内容
        i18nMessage.setBasenames(new String[]{"config/message", "classpath:message"});
    }
}

6. ExceptionController

访问的入口类内容;
通过访问
http://localhost:8080/exception/test 测试统一的断言异常
http://localhost:8080/exception/test?flag=3000 测试业务异常内容
http://localhost:8080/exception/test?flag=20000 测试系统异常内容
观察不同的异常的处理内容

@RestController
@RequestMapping("/exception")
public class ExceptionController {
	private static final Logger khy = LoggerFactory.getLogger("KHY");
	@RequestMapping("/test")
	public String login(String flag) throws Exception{
        Assert.notNull(flag, "flag不能为空");
        if(flag.equals("30000")){
        	throw new BusinessException("30000");
        }else if(flag.equals("30001")){
        	throw new BusinessException("30001");
        }else if(flag.equals("30002")){
        	throw new BusinessException("30002");
        }else if(flag.equals("20000")){
        	throw new Exception("测试系统异常");
        }
		return "执行成功";
	}
}	
 

访问对于的链接的效果图
1.
在这里插入图片描述
2.在这里插入图片描述

3.在这里插入图片描述
这么就完成了一个简单的全局异常处理的内容;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值