项目中的异常处理
写在前面:
项目中经常遇到的异常处理一般分为两大类:可以预知的异常处理,不可预知的异常处理,本文针对于这两种异常处理给出具体的解决思路,如有问题,烦请斧正
可预知的异常
指的是在程序中根据业务需求或者是程序运行之前保证运行无误,提前对异常进行判断处理。一般返回的异常信息包括:执行结果标志(成功/失败)、错误码、错误提示信息。处理方案,看代码
不可预知的异常
指的是由框架抛出来的异常
首先定义一个interface,以便于扩展
/**
*错误信息通用类
*/
public interface ResultCode {
//操作是否成功,true为成功,false操作失败
boolean success();
//操作代码
int code();
//提示信息
String message();
}
定义一个具体的类来实现interface
@ToString
public enum CmsCode implements ResultCode {
//这里使用枚举类型,可以定义多种错误信息
CMS_ADDPAGE_EXISTSNAME(false,24001,"页面名称已存在!");
//操作代码
boolean success;
//操作代码
int code;
//提示信息
String message;
private CmsCode(boolean success, int code, String message){
this.success = success;
this.code = code;
this.message = message;
}
@Override
public boolean success() {
return success;
}
@Override
public int code() {
return code;
}
@Override
public String message() {
return message;
}
}
定义一个通用的异常捕获类
public class CustomException extends RuntimeException {
private ResultCode resultCode;
public CustomException(ResultCode resultCode){
super("错误代码:"+resultCode.code()+"错误信息:"+resultCode.message());
this.resultCode = resultCode;
}
public ResultCode getResultCode(){
return this.resultCode;
}
}
将异常捕获类进行封装使用
public class CastException {
public static void cast(ResultCode resultCode){
throw new CustomException(resultCode);
}
}
对异常捕获类进行捕获
@ControllerAdvice:控制器增强注解
@ExceptionHandler(CustomException.class):异常捕获注解,该注解会将拦截指定的异常类信息,然后就可以进行处理
@ResponseBody:将捕获到的异常信息进行返回,主要是结合springmvc返回json字符串使用
@ControllerAdvice
public class CatchException {
Logger logger = LoggerFactory.getLogger(CastException.class);
//处理不可知异常,ImmutableMap的特点的一旦创建不可改变,并且线程安全
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
//使用builder来构建一个异常类型和错误代码的异常
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
static{
//在这里加入一些基础的异常类型判断
builder.put(HttpMessageNotReadableException.class, CommonCode.INVALIDPARAM);
}
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException e){
logger.error("catch exception",e.getMessage(),e);
ResultCode resultCode = e.getResultCode();
return new ResponseResult(resultCode);
}
//处理可以预知的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult Exception(Exception e){
logger.error("catch exception",e.getMessage(),e);
if(EXCEPTIONS == null){
//构建异常信息
EXCEPTIONS = builder.build();
}
//从构建的异常信息中获取指定的异常
ResultCode resultCode = EXCEPTIONS.get(e.getClass());
if(resultCode!=null){
return new ResponseResult(resultCode);
}else{
return new ResponseResult(CommonCode.SERVER_ERROR);
}
}
}
@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response {
//操作是否成功
boolean success = SUCCESS;
//操作代码
int code = SUCCESS_CODE;
//提示信息
String message;
public ResponseResult(ResultCode resultCode){
this.success = resultCode.success();
this.code = resultCode.code();
this.message = resultCode.message();
}
public static ResponseResult SUCCESS(){
return new ResponseResult(CommonCode.SUCCESS);
}
public static ResponseResult FAIL(){
return new ResponseResult(CommonCode.FAIL);
}
}
public interface Response {
public static final boolean SUCCESS = true;
public static final int SUCCESS_CODE = 10000;
}
在具体业务中的使用
public CmsPageResult add(CmsPage cmsPage){
//检验是否重复插入,根据页面名称,站点id,页面的访问路径
CmsPage page = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName()
, cmsPage.getSiteId(), cmsPage.getPageWebPath());
if(page != null){
CastException.cast(CmsCode.CMS_ADDPAGE_EXISTSNAME);
}
…… ……
}
注意:
如果是springboot微服务工程,异常处理类和微服务工程不在同一个module下,需要在启动类上进行扫描处理
@SpringBootApplication
//进行包扫描
@ComponentScan(basePackages = {"com.xuecheng.framework"})
public class ManageCmsApplication {
public static void main(String[] args){
SpringApplication.run(ManageCmsApplication.class);
}
}