Spring MVC 应用中统一处理异常的方法

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

Spring Web MVC应用中我们会遇到各式各样的异常,当这些异常发生时,为了避免客户端看到尴尬的5xx错误,我们通常会对这些异常做一些封装或者转换,展示为用户友好的界面或者消息。最简单的,我们可以这么做:


@Controller
SomeWebController {
	 @RequestMapping("/just-a-demo")
	public String doSomeBusiness(){
		try{
			doSomeServiceCall();
			return "demo-view-name"
		}
		catch (MyApplicationException ae)
		{
			handlerMyApplcationException(ae);
			return "error-view";
		}
		catch (Exception e)
		{
			hanlderCommonException(e);
			return "error-view";
		}
	}
}

上面例子中的做法是在每个控制器方法中通过try-catch方式处理应用级别的异常和其他通用异常,然后统一处理。但是这么做有个明显的缺点,那就是我们每个控制器方法都得重复这段逻辑,并且控制方法自身最关键的业务逻辑调用被淹没在try-catch中从而使该方法体变得啰嗦又隐晦。

为了解决异常统一处理问题,同时又要避免上面喧宾夺主的代码实现,我们可以采用以下两种方式:

1. @ExceptionHandler方式

这种方式下,我们可以将注解 @ExceptionHandler用在某个控制器方法上,这样该方法就可以充当对指定异常的处理器,并且该方法的实现方法和一般的控制器方法没有差别,都可以返回视图名称,返回ModelAndView对象,或者通过@ResponseBody注解方式直接将结果写入响应对象,抑或redirect/forward某个其他的页面或者视图。
基于 @ExceptionHandler的手段,也可以有基类实现方式,接口缺省方法方式或者结合@ControllerAdvisor注解的独立异常处理控制器方式等。其中,最简洁优雅的应该是结合@ControllerAdvice注解的独立异常处理控制器这种方式了。关于这几种方式的介绍,可以参考这篇文章:“Spring异常处理 ExceptionHandler的使用”

2. Filter方式

@ExceptionHandler方式实现异常统一处理是Spring Web MVC提供的机制,能捕捉的异常仅限于来自控制器方法及其服务调用方法的异常。但是有时候,出于某些原因,开发人员有可能将某些业务实现在Filter中,对于这些异常, @ExceptionHandler方式是看不到的,所以对于这些异常 @ExceptionHandler方式无能为力。这种情况下,我们可以诉诸于Filter方式。Filter机制本身是Java Servlet规范层面的概念,合理的设计异常处理Filter的逻辑并且合理地调整其调用优先级,异常处理Filter能够统一处理来自其他Filter或者所有控制器方法抛出的异常。其实现思路大致如下:

1. 代码实现示意

public class ExceptionFilter implements Filter {
	// ...
	
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            responseErrorOnException(response, e);
        }
    }

    private static void responseErrorOnException(ServletResponse response, Exception e) {
		// 这里分析异常 e ,将其转换成想要对客户端展示的内容写入到 response 中
       // 省略实现	  
    }
  
	// ...
}

2. 执行优先级安排

要求异常统一处理Filter的执行优先级要高于开发人员实现的需要被捕获异常的Filter

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/88672249