@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。
这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。
3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。
配合 @ExceptionHandler注解结合使用,当异常抛到controller层时,可以对异常进行统一的处理,规定返回的json格式或者跳转到指定的错误页面等.
@ExceptionHandler的作用主要在于声明一个或多个类型的异常,当符合条件的Controller抛出这些异常之后将会对这些异常进行捕获,然后按照其标注的方法的逻辑进行处理,从而改变返回的视图信息。
/**
* 自定义一个异常类,用于处理我们发生的业务异常
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2021/11/27 - 20:14
*/
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(FrontResult errorInfoInterface) {
super(errorInfoInterface.getCode());
this.errorCode = errorInfoInterface.getMessage();
this.errorMsg = errorInfoInterface.getMessage();
}
public BizException(FrontResult errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getCode(), cause);
this.errorCode = errorInfoInterface.getCode();
this.errorMsg = errorInfoInterface.getMessage();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public String getMessage() {
return errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
import com.tfjy.arbackend.enumtool.ResultCodeEnum;
import com.tfjy.arbackend.enumtool.ResutlMsgEnum;
import com.tfjy.arbackend.util.FrontResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.SQLException;
/**
* 统一异常处理
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2021/11/27 - 20:14
*/
@ControllerAdvice//使用该注解表示开启了全局异常的捕获
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理自定义的业务异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public FrontResult bizExceptionHandler(HttpServletRequest req, BizException e){
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("发生业务异常!原因是:{}",e.getErrorMsg());
return FrontResult.getExceptionResult(e.getErrorCode(),e.getErrorMsg());
}
/**
* 处理空指针的异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =NullPointerException.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, NullPointerException e) {
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("发生空指针异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
/**
* 处理索引越界异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =IndexOutOfBoundsException.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, IndexOutOfBoundsException e){
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("索引越界异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
/**
* 处理类未找到异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =ClassNotFoundException.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, ClassNotFoundException e) {
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("发生类未找到异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
/**
* 处理SQL异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = SQLException.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, SQLException e) {
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("发生SQL异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
/**
* 处理IO异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = IOException.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, IOException e) {
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("发生IO异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
/**
* 处理其他异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
@ResponseBody
public FrontResult exceptionHandler(HttpServletRequest req, Exception e){
logger.error("URL : " + req.getRequestURL().toString());
logger.error("HTTP_METHOD : " + req.getMethod());
logger.error("未知异常!原因是:",e);
return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());
}
}
import com.tfjy.arbackend.enumtool.ResultCodeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FrontResult {
/**
* 结果状态码
*/
private String code;
/**
* 响应结果描述
*/
private String message;
/**
* 返回数据
*/
private Object data;
/**
* 静态方法,返回前端实体结果
*
* @param code 状态码
* @param message 消息
* @param data 数据
* @return 前端实体结果
*/
public static FrontResult build(String code, String message, Object data) {
return new FrontResult(code, message, data);
}
/**
* 返回成功的结果实体
*
* @param message 消息
* @param data 数据
* @return 实体
*/
public static FrontResult getSuccessResult(String message, Object data) {
FrontResult result = new FrontResult();
result.code = ResultCodeEnum.SUCCESS.getCode();
result.message = message;
result.data = data;
return result;
}
/**
* 返回无需data的成功结果实体
*
* @param message 消息内容
* @return 返回结果
*/
public static FrontResult getSuccessResultOnlyMessage(String message) {
FrontResult result = new FrontResult();
result.code = ResultCodeEnum.SUCCESS.getCode();
result.message = message;
result.data = null;
return result;
}
/**
* 获取一个异常结果
*
* @param code 错误码
* @param message 自定义异常信息
* @return FrontResult
*/
public static FrontResult getExceptionResult(String code, String message) {
FrontResult result = new FrontResult();
result.code = code.isEmpty() ? ResultCodeEnum.CODE_EXCEPTION.getCode() : code;
result.message = message.isEmpty() ? ResultCodeEnum.CODE_EXCEPTION.getMsg() : message;
return result;
}
}
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum ResultCodeEnum {
// 请求成功
SUCCESS("0000"),
// 请求失败
FAIL("1111"),
// EXCEL 导入失败
EXCEL_FAIL("1000"),
// userID 为空
ID_NULL("1001"),
// 前端传的实体为空
MODEL_NULL("1002"),
// 更新失败
UPDATE_FAIL("1011"),
// 参数为空
PARAM_ERROR("400"),
// 代码内部异常
CODE_EXCEPTION("500", "代码内部异常");
/**
* 状态码
*/
private String code;
public String getCode() {
return code;
}
ResultCodeEnum(String code) {
this.code = code;
}
private String msg;
public String getMsg() {
return msg;
}
}
public enum ResutlMsgEnum {
//查询成功
FIND_SUCCESS("查询成功!"),
//查询失败
FIND_FAIL("查询失败!"),
//更新成功
UPDATE_SUCCESS("更新成功"),
//更新失败
UPDATE_FAIL("更新成功"),
SEND_SUCCESS("发送成功"),
SEND_FAIL("发送失败");
private String msg;
ResutlMsgEnum(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
/**
* 测试用例
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2021/11/29 - 9:05
*/
@Api(tags = {"测试controller"})
@RequestMapping(value = "/testController")
@RestController
public class TestController {
@ApiOperation(value = "测试null")
@GetMapping(value = "getNull")
public FrontResult getNull() {
int length = 0;
String name=null;
length = name.length();
return FrontResult.build(ResultCodeEnum.SUCCESS.getCode(),
ResutlMsgEnum.EXECUTE_SUCCESS.getMsg(), length);
}
}
其他异常同理,也可以捕获。完美,没问题。全局统一异常处理设置成功。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/promsing/article/details/121655576
内容来源于网络,如有侵权,请联系作者删除!