SpringMvc --- Controller的异常处理

使用@ResponseStutas处理自定义异常

@ResponseStatus注解有两种用法,一种是注解在自定义异常类上,一种是注解在目标方法中。

首先是加在目标方法上的这种情况,注解中有两个参数,value属性设置异常的状态码,reaseon是异常的描述。

值得一提的是不管该方法是不是发生了异常,将@ResponseStatus注解加在目标方法上,一定会抛出异常日志。倘若没有发生异常的话方法还是会正常执行完毕的。

使用该注解去捕捉自定义异常则需要在自定义异常类上加载@ResponseStatus注解,对其指定状态码即可。

package com.rebecca.springmvc.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * 自定义异常
 * @Author: Rebecca
 * @Description:
 * @Modified By:
 */

@ResponseStatus(value = HttpStatus.NO_CONTENT, reason = "No Content")
public class NullOrgException extends RuntimeException {
}

使用try catch 手动捕获异常

定义了上述异常后,只要应用程序中有抛出NullOrgException异常,就会被捕获并映射为对应的状态码。那么如果程序不仅仅需要状态码,还要包含所产生的错误,那该怎么办呢?此时的话,我们就不能将异常视为HTTP错误了,而是要按照处理请求的方式来处理异常了。

package com.rebecca.springmvc.controller.exception;

import com.rebecca.springmvc.org.bean.Org;
import com.rebecca.springmvc.org.service.OrgService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("test/exception")
public class ExceptionTestController {
    private Logger logger = LoggerFactory.getLogger(ExceptionTestController.class);

    @Autowired
    private OrgService service;

    @RequestMapping(value = "orgs", method = RequestMethod.GET)
    @ResponseBody
    public List<Org> getOrgs ()  {
        List<Org> orgs = null;
        try {
            orgs = service.getOrgs();
        } catch (NullOrgException e) {
            logger.error("无组织机构相关数据!",e);
        }
        return orgs;
    }
}

比如上面代码中的NullOrgException异常,在Spring中没有默认映射,那最简单的办法就是try {…} catch (NullOrgException e) {…} 。

使用@ExceptionHandler处理自定义异常

上述try {…} catch方式不利于代码维护,好在Spring提供了一种机制,可以用@ExceptionHandler注解将异常映射为HTTP状态码。下面是使用@ExceptionHandler注解后的方式:

package com.rebecca.springmvc.controller.exception;

import com.rebecca.springmvc.org.bean.Org;
import com.rebecca.springmvc.org.service.OrgService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("test/exception")
public class ExceptionTestController {
    private Logger logger = LoggerFactory.getLogger(ExceptionTestController.class);

    @Autowired
    private OrgService service;

    @RequestMapping(value = "orgs", method = RequestMethod.GET)
    @ResponseBody
    public List<Org> getOrgs ()  {
        List<Org> orgs = service.getOrgs();
        return orgs;
    }

    @ExceptionHandler(NullOrgException.class)
    public String handleNullOrgException() {
        return "无组织机构相关数据!";
    }
}

上面代码我们在handleNullOrgException()方法上添加了@ExceptionHandler注解,当程序抛出NullOrgException异常时,将会委托该方法来处理。它的返回值是String,你也可以改为其它的返回类型以满足应用程序需要。对于用@ExceptionHandler注解标注的方法来说,它能处理同一个控制器(Controller)中所有处理器方法所抛出的异常。

为了避免在多个控制器中编写重复的@ExceptionHandler注解方法,我们会创建一个基础的控制器类,所有控制器类要扩展这个类,从而 继承 通用的@ExceptionHandler方法。

使用@ControllerAdvice注解处理所有的异常

前面我们说使用@ExceptionHandler注解只能处理一个控制器(Controller)中所有处理器方法所抛出的异常,那么有没有一种方法不用集成就能够处理所有控制器中处理器方法所抛出的异常呢?

答案是:有!从Spring 3.2开始,这肯定是能够实现的,我们只需将其定义到控制器通知类中即可。

在Spring 3.2之后,为这类问题引入了一个新的解决方案:控制器通知。

控制器通知(controller advice)是指任意带有@ControllerAdvice注解的类。

这个类会包含一个或多个如下类型的方法:

  1. @ExceptionHandler注解标注的方法;
  2. @InitBinder注解标注的方法;
  3. @ModelAttribute注解标注的方法。

在带有@ControllerAdvice注解的类中,上述的这些方法会运用到整个应用程序所有控制器中带有@RequestMapping注解的方法上。@ControllerAdvice注解本身已经使用了@Component,因此@ControllerAdvice注解所标注的类将会自动被组件扫描获取到,和有@Component注解的类一样。@ControllerAdvice最为实用的一个场景就是将所有的@ExceptionHandler方法收集到一个类中,这样所有控制器的异常就能在一个地方进行统一处理。例如,我们想将NullOrgException的处理方法用到整个应用程序的所有控制器上。如下的程序清单展现的AppWideExceptionHandler就能完成这一任务,这是一个带有@ControllerAdvice注解的类。下面代码使用@ControllerAdvice,为所有的控制器处理异常:

package com.rebecca.springmvc.controller.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * 控制器通知类
 * @Author: Rebecca
 * @Description:
 * @Modified By:
 */
@ControllerAdvice  // 定义控制器类
public class AppWideException {

    // 定义异常处理方法
    @ExceptionHandler(NullOrgException.class)
    public String handleNullOrgException() {
        return "无组织机构相关数据!";
    }
}

现在,如果任意的控制器方法抛出了DuplicateSpittleException,不管这个方法位于哪个控制器中,都会调用这个duplicateSpittleHandler()方法来处理异常。我们可以像编写@RequestMapping注解的方法那样来编写@ExceptionHandler注解的方法。如程序清单7.10所示,它返回“error/duplicate”作为逻辑视图名,因此将会为用户展现一个友好的出错页面。

 

那么,总的来说。Spring拥有着自己的异常处理HTTP状态码的特殊异常处理方式。除此之外,还有几种注解的方式来处理自定义的异常情况,(自定义)异常类上添加@ResponseStatus注解,从而将其映射为某一个HTTP状态码;当某个方法上增加注解@ExceptionHandler时,在参数中申明异常类型即可在方法处理异常;最后就是在Spring3.2版本之后可以将@ExceptionHandler注解的方法纳入到使用@ControllerAdvice注解的异常处理类中这样便可以统一处理异常信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值