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