spring MVC统一异常处理的几种方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/syslbjjly/article/details/88952613

异常统一处理分为三种方式:

1.使用@ExceptionHandler + @ControllerAdvice注解

2.使用spring AOP (@AfterThrowing + @Aspect)

3.继承HandlerExceptionResolver 接口

4.使用@ExceptionHandler注解

1.使用@ExceptionHandler + @ControllerAdvice注解

此方法需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。

@RestControllerAdvice
public class RestMyExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(RestMyExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    public String handle(Exception e){
        log.info("参数异常:"+e.getMessage());
        return e.getMessage();
    }

}

继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式:

@Slf4j
@ControllerAdvice
public class ExceptionHandlerBean extends ResponseEntityExceptionHandler {

    /**
    * 数据找不到异常
    * @param ex
    * @param request
    * @return
    * @throws IOException
    */
    @ExceptionHandler({DataNotFoundException.class})
    public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException {
        return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException);
    }

    /**
    * 根据各种异常构建 ResponseEntity 实体. 服务于以上各种异常
    * @param ex
    * @param request
    * @param specificException
    * @return
    */
    private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) {
        ReturnTemplate returnTemplate = new ReturnTemplate();
        returnTemplate.setStatusCode(specificException);
        returnTemplate.setErrorMsg(ex.getMessage());
        return handleExceptionInternal(ex, returnTemplate,
        new HttpHeaders(), HttpStatus.OK, request);
    }

}

2.使用spring AOP (@AfterThrowing + @Aspect)

@Aspect
@Component
public class WebExceptionAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebExceptionAspect.class);

    //凡是注解了RequestMapping的方法都被拦截
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    private void webPointcut() {
    }

    /**
    * 拦截web层异常,记录异常日志,并返回友好信息到前端 目前只拦截Exception,是否要拦截Error需再做考虑
    * @param e 异常对象
    */
    @AfterThrowing(pointcut = "webPointcut()", throwing = "e")
    public void handleThrowing(Exception e) {
        e.printStackTrace();
        logger.error("发现异常!" + e.getMessage());
        logger.error(JSON.toJSONString(e.getStackTrace()));
        //这里输入友好性信息
        writeContent("出现异常");
    }

    /**
    * 将内容输出到浏览器
    *
    * @param content 输出内容
    */
    private void writeContent(String content) {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/plain;charset=UTF-8");
        response.setHeader("icop-content-type", "exception");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.print(content);
        writer.flush();
        writer.close();
    }
}

3.继承HandlerExceptionResolver 接口

这种方式可以进行全局的异常控制。例如:

@Component
public class ExceptionTest implements HandlerExceptionResolver{

    /**
    * TODO 简单描述该方法的实现功能(可选).
    * @see   org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
    */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("This is exception handler method!");
        return null;
    }
}

4.使用@ExceptionHandler注解

使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:

@Controller
public class GlobalController {

    /**
    * 用于处理异常的
    * @return
    */
    @ExceptionHandler({MyException.class})
    public String exception(MyException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
        return "exception";
    }

    @RequestMapping("test")
    public void test() {
        throw new MyException("出错了!");
    }
}

可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。

猜你喜欢

转载自blog.csdn.net/syslbjjly/article/details/88952613
今日推荐