在开发阶段,遇到bug是常事,为了给了用户良好的体验,我们肯定得处理异常,比如跳转到一个错误页面打印对应的信息,而不是直接出现异常页面或者没有任何反应,所以说统一一个全局的异常处理是很必要的。
对于SpringBoot项目或SSM项目可借鉴的异常处理思路:
系统遇到异常时,在程序中手动抛出,dao抛给service,service再抛给Controller,最后Controller抛给前端控制器,前端控制器调用全局异常处理器
如下图:
代码如下:
声明一个全局的异常类(可选可不选)
/**
* @program: flea
* @classname: BadArgumentsException
* @description: 错误参数异常
* @author: 南街
* @create: 2019-11-09 08:46
**/
public class BizException extends RuntimeException {
/**
* 默认关闭栈追踪信息和挂起参数 优化性能
* https://blog.csdn.net/neosmith/article/details/82626960
* @param message
* @return
* @date 2019/11/9 9:55
*/
public BizException(String message) {
super(message, null, false, false);
}
public BizException(String message, Throwable cause) {
super(message, cause, false, false);
}
protected BizException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
声明全局异常处理器(返回json数据,因为我的项目是通过json来交互的)
@ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。
package com.changda.flea.management.config;
import com.changda.flea.common.constants.HttpStatusEnum;
import com.changda.flea.common.exception.BizException;
import com.changda.flea.common.util.Result;
import com.changda.flea.common.util.ResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @description: 全局异常统一处理类
* @author: 南街
* @create: 2019-01-17 10:24
**/
@RestControllerAdvice
public class ApplicationControllerExceptionHandler {
/**
* 方法参数效验 针对validation
*
* @param ex
* @return com.zhulin.ascentweb.dto.Result
* @date 2019/9/8 9:58
*/
@ExceptionHandler(value = BindException.class)
@ResponseBody
public Result<String> bindException(BindException ex) {
StringBuilder message = new StringBuilder();
ex.getBindingResult().getAllErrors()
.forEach(error -> message.append(error.getDefaultMessage()).append(","));
return ResultGenerator.getResultByHttp(HttpStatusEnum.BAD_REQUEST,
message.substring(0,message.length()-1));
}
/**
* 方法参数效验 针对validation
*
* @param ex
* @return com.zhulin.ascentweb.dto.Result
* @date 2019/9/8 9:58
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Result<String> handlerMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
StringBuilder message = new StringBuilder();
ex.getBindingResult().getAllErrors()
.forEach(error -> message.append(error.getDefaultMessage()).append(","));
return ResultGenerator.getResultByHttp(HttpStatusEnum.BAD_REQUEST,
message.substring(0,message.length()-1));
}
/**
* @RequestParam 注解请求参数有误
* @date 2019/11/8 20:09
*/
@ExceptionHandler(value = MissingServletRequestParameterException.class)
@ResponseBody
public Result<String> missingServletRequestParameterException(MissingServletRequestParameterException e) {
return ResultGenerator.getResultByHttp(HttpStatusEnum.BAD_REQUEST);
}
/**
* @RequestParam 业务异常
* @date 2019/11/8 20:09
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public Result<String> bizException(BizException e) {
return ResultGenerator.getResultByHttp(HttpStatusEnum.BAD_REQUEST, e.getMessage());
}
}
我这里意思就是如果出现异常,统一都返回错误提示给用户,告诉用户,系统碰到了一些预期之外的错误
也许有些小伙伴可能需要在一个方法中区分是系统异常还是自定义异常,然后返回对应的异常的信息,那就参考如下:
@ControllerAdvice
public class ApplicationControllerExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public MessageBean handlerError(HttpServletRequest req, Exception e) {
// MessageBean一个前后台交互的Json实体类,包括success,msg,data属性
if (e instanceof 自定义异常){
return new MessageBean(false,e.msg());
}
return new MessageBean(false, Constants.ERROR_MSG);
}
}
如上都是提供思路,代码仅供参考,直接复制可能报错哦。
这里的MessageBean和Result其实就是统一返回结果集,下面粘贴我平常使用的结果集。
/**
* 返回结果集
* @author: 南街
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int resultCode;
private String message;
private T data;
public Result() {
}
public Result(int resultCode, String message) {
this.resultCode = resultCode;
this.message = message;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "Result{" +
"resultCode=" + resultCode +
", message='" + message + '\'' +
", data=" + data +
'}';
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15231.html