今天主要给大家介绍以下传统项目中如何解决代码中存在的大量try....catch...
代码问题。在传统的项目框架中,我们不可避免的会遇到程序抛出异常的情况,有些异常不会影响程序的正常运行,而有些异常则是致命的,经常会导致我们的项目宕机。而为了尽可能的避免这种情况,我们一般会对代码进行异常捕获处理,这就造成代码中会存在大量的异常捕获代码try....catch...
,这使得我们的代码易读性及美观性都相当的差。今天就给大家介绍以下如何捕获全局异常,从而避免对每一次请求进行异常捕获。
话不多说,上代码::
- 首先我们希望我们的接口每次返回的数据都是一定的格式的,这样前端访问接口就可以直观的了解接口的可用性。所以我们新建类
ResultBean
来作为统一返回接口的Bean
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ResultBean {
private Integer code; //执行编号
private String message; //返回信息
private Object data; //封装内容
}
- 其次,我们不同的接口返回的异常也是不尽相同的,所以我们新建枚举类
ResultEnum
来定义我们的返回类型。
public enum ResultEnum {
SUCCESS(200,"操作成功"),
FAIL(500,"操作失败"),
EXCEPTION(400,"系统错误"),
NOPERMISS(401,"用户没有权限");
private Integer code;
private String message;
private ResultEnum(Integer code,String message){
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 当然我们需要自己的异常处理类
MyException
public class MyException extends Exception {
private Integer code;
public MyException(String msg){
super(msg);
}
public MyException(Integer code,String msg){
super(msg);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
- 接下来就是今天的重点了
@RestControllerAdvice
及@ExceptionHandler
进行异常捕获处理
@RestControllerAdvice
public class ExceptionAdvice {
private static Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultBean defaultException(Exception e){
logger.error("系统发生异常:{},请及时处理!",e.getMessage());
if(null != e.getMessage()){
if(e.getMessage().contains("Subject does not have permission")){
return ResultBean.builder()
.code(ResultEnum.NOPERMISS.getCode())
.message(ResultEnum.NOPERMISS.getMessage())
.build();
}
return ResultBean.builder()
.code(ResultEnum.EXCEPTION.getCode())
.message(ResultEnum.EXCEPTION.getMessage())
.build();
}
return ResultBean.builder()
.code(ResultEnum.EXCEPTION.getCode())
.message("空指针异常")
.build();
}
@ExceptionHandler(value = MyException.class)
@ResponseBody
public ResultBean myException(MyException e){
e.printStackTrace();
Integer code = e.getCode();
String message = e.getMessage();
if(null == e.getCode()){
code = ResultEnum.EXCEPTION.getCode();
}
if (null == e.getMessage()){
message = ResultEnum.EXCEPTION.getMessage();
}
return ResultBean.builder()
.code(code)
.message(message)
.build();
}
}
- 为了以后的使用方便,我们可以编写自己的返回信息封装工具类
ResultUtil
public class ResultUtil {
/**
* 返回错误信息
* @param message 错误信息
* @return
*/
public static ResultBean error(String message){
return ResultBean.builder()
.code(ResultEnum.FAIL.getCode())
.message(message)
.build();
}
/**
* 返回错误信息
* @param code 错误编码
* @param message 错误信息
* @return
*/
public static ResultBean error(Integer code,String message){
return ResultBean.builder()
.code(code)
.message(message)
.build();
}
/**
* 返回错误信息
* @param resultEnum 枚举类
* @return
*/
public static ResultBean error(ResultEnum resultEnum){
return ResultBean.builder()
.code(resultEnum.getCode())
.message(resultEnum.getMessage())
.build();
}
/**
* 返回错误信息
* @return
*/
public static ResultBean error(){
return ResultBean.builder()
.code(ResultEnum.FAIL.getCode())
.message(ResultEnum.FAIL.getMessage())
.build();
}
/**
* 返回操作成功信息
* @param message 枚举类
* @return
*/
public static ResultBean success(String message){
return ResultBean.builder()
.code(ResultEnum.SUCCESS.getCode())
.message(message)
.build();
}
/**
* 返回操作成功信息
* @param code 成功编号
* @param message 成功信息
* @return
*/
public static ResultBean success(Integer code,String message){
return ResultBean.builder()
.code(code)
.message(message)
.build();
}
/**
* 返回操作成功信息
* @param resultEnum 枚举类
* @return
*/
public static ResultBean success(ResultEnum resultEnum){
return ResultBean.builder()
.code(resultEnum.getCode())
.message(resultEnum.getMessage())
.build();
}
/**
* 返回操作成功信息
* @return
*/
public static ResultBean success(){
return ResultBean.builder()
.code(ResultEnum.SUCCESS.getCode())
.message(ResultEnum.SUCCESS.getMessage())
.build();
}
/**
* 返回操作成功信息
* @return
*/
public static ResultBean success(Object data){
return ResultBean.builder()
.code(ResultEnum.SUCCESS.getCode())
.message(ResultEnum.SUCCESS.getMessage())
.data(data)
.build();
}
/**
* 返回操系统异常信息
* @param message 枚举类
* @return
*/
public static ResultBean exception(String message){
return ResultBean.builder()
.code(ResultEnum.EXCEPTION.getCode())
.message(message)
.build();
}
/**
* 返回操系统异常信息
* @param resultEnum 枚举类
* @return
*/
public static ResultBean exception(ResultEnum resultEnum){
return ResultBean.builder()
.code(resultEnum.getCode())
.message(resultEnum.getMessage())
.build();
}
/**
* 返回操系统异常信息
* @return
*/
public static ResultBean exception(){
return ResultBean.builder()
.code(ResultEnum.EXCEPTION.getCode())
.message(ResultEnum.EXCEPTION.getMessage())
.build();
}
}
至此,我们的全局异常捕获及统一接口返回就实现完成了
大家可以编写测试Controoller进行测试
@PostMapping("/login")
@ResponseBody
public Object login(String username, String password){
if(StringUtils.isEmpty(username)){
return ResultUtil.error("用户名为空");
}
if(StringUtils.isEmpty(password)){
return ResultUtil.error("密码为空");
}
/**
* 登录业务流程
*/
return ResultUtil.success("登录成功");
}