您的位置:首页 > 编程语言 > Java开发

Spring MVC全局异常处理

2015-11-04 14:47 447 查看
    今天翻看项目发现异常类中有一个CommonExceptionHandler,却在配置文件中找不到任何有配置的地方,于是搜了一把资料,整理一下。

    Spring3.0中有两种异常处理机制,一种是实现HandlerExceptionResolver接口,一种是在Controller类中使用@ExceptionHandler注解,第一种方法可以实现全局异常控制,第二种方法更加灵活,个性化,但是不统一,我之前看的项目中就是用的第一种方法。

1. 基于HandlerExceptionResolver接口的异常处理:

   使用这种方法只需要复写 resolveException方法就可以了,该方法返回一个ModelAndView对象,该方法内部对异常的类型做判断,然后返回合适的ModelAndView对象,如果该方法返回了null,则spring会继续寻找其他实现了HandlerExceptionResolver接口的bean,就是说spring会搜索所有注册在其环境中的实现了HandlerExceptionResolver接口的Bean,逐个执行,直到返回了一个ModelAndView对象。(注意该自定义全局异常类一般用注解
@Component,表示模糊不好分层的注入,或者在配置文件xml中使用<bean/>结点声明。)

   举例:

@Component
public class CommonExceptionHandler implements HandlerExceptionResolver {
private static final Logger logger = LoggerFactory.getLogger(CommonExceptionHandler.class);

@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {

try {
response.reset();
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
if (ex instanceof UnAuthenticatedException || ex instanceof NoAuthorityException
|| ex instanceof TimeoutException || ex instanceof ServiceException) {
logger.warn("hander Exception:{}, Message is {}", ex.getClass(), ex.getMessage());

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
writer.print(ex.getMessage());

} else if (ex instanceof SystemShutDownException) {

logger.warn("hander Exception:{}, Message is {}", ex.getClass(), ex.getMessage());
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
writer.print(ex.getMessage());
} else {
// 其他异常,返回500状态码
logger.error(ex.getMessage(), ex);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
writer.print("System error");
}

} catch (Exception e) {
//logger.error(e.getMessage(), e);
return null;
}

return new ModelAndView();
}

}

这种写法,错误码直接返回到前台,前台jsp页面获取到之后,进行相应的判断,给出相对应的提示,如果前台页面没有相应的判断,则会直接输入相应的错误信息在页面上。

也可以用一下写法,出现异常之后跳转到一个写好的提示页面:

public class CustomExceptionHandler implements HandlerExceptionResolver {

@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object object, Exception exception) {
if(exception instanceof IOException){
return new ModelAndView("errors/ioException");
}else if(exception instanceof SQLException){
return new ModelAndView("errors/sqlException");
}
return null;
}
}
4000


其中 errors/ioException  和  errors/sqlException  都是jsp页面。

spring 默认也提供了一个全局异常处理类SimpleMappingExceptionResolver,它也是HandlerExceptionResolver的实现类,如果要使用,只需要在xml中配置即可。

以下转载自此处,点击跳转

例如:

<span style="color:#3333FF;"> <!-- 全局异常配置 start 控制器异常处理-->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">errors/webException</prop>
<prop key="java.lang.Throwable">errors/rmsException</prop>
</props>
</property>
<property name="statusCodes">
<props>
<prop key="errors/webException">500</prop>
<prop key="errors/rmsException">404</prop>
</props>
</property>
<!-- 设置日志输出级别,不定义则默认不输出警告等错误日志信息 -->
<property name="warnLogCategory" value="WARN"></property>
<!-- 默认错误页面,当找不到上面mappings中指定的异常对应视图时,使用本默认配置 -->
<property name="defaultErrorView" value="errors/error"></property>
<!-- 默认HTTP状态码 -->
<property name="defaultStatusCode" value="500"></property>
</bean>
<!-- 全局异常配置 end --> </span>

通过SimpleMappingExceptionResolver我们可以将不同的异常映射到不同的jsp页面(通exceptionMappings属性的配置),同时我们也可以为所有的异常指定一个默认的异常提示页面(通过defaultErrorView属性的配置),如果所抛出的异常在exceptionMappings中没有对应的映射,则Spring将用此默认配置显示异常信息(注意这里配置异常显示界面均仅包括主文件名,至于文件路径和后缀已经在viewResolver中指定) 
<property name="defaultErrorView" value="errors/error"></property>
一个典型的异常显示页面如下:
<span style="color:#3333FF;"><html>
<head><title>Exception!</title></head>
<body>
<% Exception ex = (Exception)request.getAttribute("exception"); %>
<H2>Exception: <%= ex.getMessage();%></H2>
<P/>
<% ex.printStackTrace(new java.io.PrintWriter(out)); %>
</body>
</html> </span>


exception 实在SimpleMappingExceptionResolver 被存放到request中的,具体可以查看源代码。 

如果SimpleMappingExceptionResolver无法满足异常处理的需要,我们可以针对 

HandlerExceptionResolver接口实现自己异常处理类,这同样非常简单(只需要实现一个 

resolveException方法)。 

如果有ViewResolver,则制定的jsp页面必须在那个页面下,到时候如果找不到页面,可以根据错误提示再调整页面路径

2..基于@ExceptionHandler的异常处理

该方法需要定义在Controller内部,然后创建一个方法并用@ExceptionHandler注解来修饰用来处理异常,这个方法基本和 @RequestMapping修饰的方法差不多,只是可以多一个类型为Exception的参数,@ExceptionHandler中可以添加一个或多个异常的类型,如果为空的话则认为可以触发所有的异常类型错误。

示例:

<span style="color:#3333FF;">@Controller
public class ExceptionHandlerController {

@ExceptionHandler(value={IOException.class,SQLException.class})
public String exp(Exception ex,HttpServletRequest request) {
request.setAttribute("exception", ex);
return "/error.jsp";
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息