在spring mvc中异常处理几种种方式,由于每种方式使用的场景不一样,根据实际场景使用不同的异常处理方式,或者几种方式配合使用。几种配合时具有不同的优先级。编程的过程就是寻找最佳实践的过程。
这种方式的实现方式简单,在web.xml配置错误码和对应页面,配置异常处理类型以及错误处理连接,在web.xml中添加如下配置即可
<exception-type>java.lang.NullPointerException</exception-type>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<!--定向到Controller中-->
<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>
<!--定向到Controller中-->
<!-- 异常类型-->
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/nullpointer.html</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/uncaughtException</location>
</error-page>
优点
缺点
使用
根据特点,一般只用来配置错误码页面,具有通用性,在任何项目中都可以使用。对与异常处理需要编写相应代码完成(不同web框架实现方式不一样)。错误码的优先级在几种异常处理方式最高的的。
是web.xml中异常类型处理的不同形式。在spring-servlet中配置对于各种异常类型的处理。这种方式只是将web.xml中的异常类型处理挪到另一个配置文中和换另一种表达方式。
<prop key="java.lang.NullPointerException">/NullPointerException.do</prop>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默认错误页面,就是不在exceptionMappings指定范围内 -->
<property name="defaultErrorView" value="/uncaughtException.do" />
<property name="exceptionMappings">
<props>
<!-- 异常类名,可以是全路径,错误页面或Controller路径! -->
<prop key="java.lang.NullPointerException">/NullPointerException.do</prop>
<prop key="java.io.IOException">/IOException.do</prop>
</props>
</property>
</bean>
<!-- 异常处理 END -->
优点
缺点
使用
不好用,有更好的解决方案替代。优先级低,具体位于哪个等级不清楚,不关心。
统一处理在Controller层抛出的异常,在`public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)`方法中做异常类型判断,根据不同异常类型做不同的处理。
@Component
public class CustomerExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
System.out.println("Exception Resolver Handler Exception");
ModelAndView view = new ModelAndView("/error.jsp");
view.addObject("ex", ex);
return view;
}
}
优点
缺点
使用
建议使用统一处理异常,配合其他处理方式。优先级低
指定处理当前Controller中抛出异常,@ExceptionHandler({“exceptionlist”}) 一个方法可以处理多种异常类型
@Controller
@RequestMapping("/showcase/exception/enhance")
public class SpringMvcExceptionEnhance {
/**
* @Title: handleException
* @Description: 统一处理异常
* @param: @param exception
* @param: @return
* @return: ModelAndView
* @throws
* @author budingge.com
* @Date 2014年7月26日 上午3:07:43
*/
@ExceptionHandler(Exception.class)//制定处理异常
public ModelAndView handleException(Exception exception) {
ModelAndView view = new ModelAndView("/error.jsp");
view.addObject("ex", exception);
return view;
}
// 制定处理异常
@ExceptionHandler(CustomerException.class)
public ModelAndView handleCustomerException(CustomerException exception) {
ModelAndView view = new ModelAndView("/error.jsp");
view.addObject("ex", exception);
return view;
}
}
优点
缺点
使用
在需要特殊处理异常时使用,配置其他处理方式使用,优先级最高
能处理所有Controller中抛出异常,功能强大,优先级低于@Controller上的@ExceptionHandler
@ControllerAdvice
public class SpringMvcExceptionFutrue {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception exception) {
System.out.println("Exceptions Handler By @ControllerAdvice...");
ModelAndView view = new ModelAndView("/error.jsp");
view.addObject("ex", exception);
return view;
}
@ExceptionHandler(CustomerException.class)
public void handleCustomerException(HttpServletResponse response,CustomerException exception) throws IOException {
System.out.println("Exceptions Handler By @ControllerAdvice...");
response.getWriter().write("failed");
}
}
优点
缺点
使用
建议使用,可以完全处理异常
在拦截器中捕获Controller中抛出的异常,统一处理,与实现HandlerExceptionResolver接口方式一样,不过优先级低较低。
/**
* @ClassName: CustomerHandlerInterceptor.java
* @Description: spring mvc拦截器,处理异常
*
* @author budingge.com
* @version V1.0
* @Date 2014年7月26日 下午1:46:17
*/
public class CustomerHandlerInterceptor extends HandlerInterceptorAdapter {
/**
* 在Controller之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("Enter HandlerInterceptor preHandle....");
return super.preHandle(request, response, handler);
}
/**
* 在Controller之后和渲染视图之前执行
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
/**
* 在渲染视图之后执行,判断异常
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
if (ex != null) {
System.out
.println("An Exception Be Catched At HandlerInterceptor afterCompletion....");
System.out.println(ex);
request.setAttribute("ex", ex);
request.getRequestDispatcher("/error.jsp").forward(request,
response);
}
}
/**
* servlet3.0异步功能
*/
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
super.afterConcurrentHandlingStarted(request, response, handler);
}
}
在spring-servlet.xml中配置
<mvc:interceptors>
<!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<bean class="com.budingge.spring.chowcase.springmvc.web.interceptor.CustomerHandlerInterceptor" />
</mvc:interceptors>
优点
缺点
使用
可以使用,记录异常日志,不过拦截器最大的用处还是权限控制。
跟@ControllerAdvice类似,优先级应该是最高的,没有验证过。编写AOP类和处理规则即可
优点
缺点
使用
日志记录使用
综上spring mvc中几种已处理方式,每种有不同的应用场景,利用他们的特点在不同场景中使用,一个项目中同时使用几种也不见怪。但同时使用时要注意优先级问题。在一个spring mvc项目中的异常处理最佳实践我觉得应该是这样:
通过以上这配合完全可以处理Controller中的所有异常。