springmvc之异常处理

一.SpringMVC异常处理机制

  • springMVC会将所有在doDispatch方法中的异常捕获,然后处理。无法处理的异常会抛出给容器处理。
    在doDispatch()中调用processDispatchResult
  • 如果有异常出现,首先判断是不是ModelAndViewDefiningException,这个异常是人为的定义的,指定了modelAndView,如果不是ModelAndViewDefiningException,则要调用processHandlerException(request, response, handler, exception),该方法会遍历所有的handlerExceptionResolvers,判断能否处理该异常。调用各自的resolveException 方法(一般抛出的异常都需要通过这一步,要么能被处理;要么处理不了,向上抛)

二.web.xml配置错误页面

1.按错误号指定跳转(404,500,…)

(1) 使用error-page标签的要点

  • 如果是JSP中抛出的异常,容器首先查看JSP中有没有指定errorPage属性,如果没有,再查看web.xml中有没有error-page标签;如果是Web应用中的其它地方抛出异常,容器只会查看web.xml中的error-page标签。
  • 不论是根据exception-type还是error-code来声明错误页面,location指定的路径必须以斜线开头,也就是说它是相对于Web应用根的。
  • 一个web.xml中可以使用多个error-page标签,一个error-page标签中只能使用一个exception-type或error-page。

(2) 在web.xml新增配置信息
根据错误编码指定页面

    <error-page>
        <error-code>404</error-code>
        <location>/error/404</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/error/500</location>
    </error-page>

定义404,500页面控制器

/**
     * 错误:404
     */
    @RequestMapping(value = "/404")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String error404() {
        return "404";
    }

    /**
     * 错误:500
     */
    @RequestMapping(value = "/500")
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String error500() {
        return "505";
    }

2.按异常类型指定跳转

在web.xml添加error-page,根据异常类型,添加指定的页面

	<!--根据错误类型指定页面-->
    <error-page>
        <exception-type>java.lang.ArithmeticException</exception-type>
        <location>/error/null</location>
    </error-page>

定义null接口

    /**
     * 错误:空指针异常
     */
    @LoginAuth(validate = false)
    @RequestMapping(value = "/null")
    public String error_null() {
        return "null";
    }

测试用例

/**
     * @Description  测试空指针异常
     **/
    @RequestMapping("/test_null")
    public String test_null(){
        int c=1/0;
        return "/login";
    }

三.异常统一处理的三种方式

1.使用 @ ExceptionHandler 注解

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

@Controller
public class CustomExceptionController {

    /**
     * 用于处理自定义异常
     * @return
     */
    @ExceptionHandler({CustomException.class})
    @ResponseBody
    public TResult exception(CustomException e) {
        return TResultUtils.error(e.getMessage());
    }

    @RequestMapping("test_error")
    @ResponseBody
    public void test() {
        throw new CustomException("出错了!");
    }
}
2.使用 @ControllerAdvice+ @ ExceptionHandler 注解

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

1.示例

自定义异常信息

public class CustomException extends RuntimeException {

    private String message;

    public CustomException(String message) {
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

接口处理异常

 @Override
    public TResult login(User user) {
        //参数验证
        if(user.getUsername()==null||user.getUsername().equals("")
               ||user.getPassword()==null||user.getPassword().equals("") ){
            throw new CustomException("请输入完整");
        }

        //身份验证
        if(user.getUsername().equals("admin")&&user.getPassword().equals("admin")){
            request.getSession().setAttribute("user",user);
            return TResultUtils.success();
        }
        throw new CustomException("请检查您的用户名或者密码是否正确");
    }

全局异常信息处理

@ControllerAdvice
@ResponseBody
public class AllControllerAdvice {

    /**
     * 用于处理自定义异常
     * @return
     */
    @ExceptionHandler({CustomException.class})
    public TResult exception(CustomException e) {
        return TResultUtils.error(e.getMessage());
    }


    /**
     * @Description  400 - Bad Request
     **/
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public TResult handleBadRequst(Exception e) {
        return TResultUtils.error(e.getMessage());
    }


    /**
     * @Description  405 - Method Not Allowed
     **/
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public TResult handleMethodNotAllowed(Exception e) {
        return TResultUtils.error(e.getMessage());
    }


    /**
     * @Description  415 - Unsupported Media Type
     **/
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public TResult handleUnsupportedMediaType(Exception e) {
        return TResultUtils.error(e.getMessage());
    }


    /**
     * @Description  500
     **/
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public TResult handleIOException(Exception e) {
        return TResultUtils.error(e.getMessage());
    }
}

如果 @ExceptionHandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以还可以写成这样:

 	@ExceptionHandler()
    @ResponseBody
    TResult handleException(Exception e){
        return TResultUtils.error(e.getMessage());
    }
3.实现 HandlerExceptionResolver 接口

上面的异常处理方法是json信息,如果希望返回跳转页面,则需要实现HandlerExceptionResolver类来进行异常处理并跳转,下面定义HandleMvException ,实现HandleMvException 接口

public class HandleMvException implements HandleMvException {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
        CustomException customException = null;
        if (ex instanceof CustomException) {
            customException = (CustomException)ex;
        }else{
            customException = new CustomException("未知错误!");
        }
        String errMsg = customException.getMessage();

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", errMsg);
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

测试用例

/**
     * @Description  测试异常
     **/
    @RequestMapping("/test_error_msg")
    public String test_error_msg() {
        int c=0;
        if(c==0){
            throw  new CustomException("空指针异常...");
        }
        return "/login";
    }

访问 /test_error_msg 则会进入resolveException方法进行处理,然后直接进入error页面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值