译者说明:不同浏览器运行效果不同,在Eclipse的浏览器中就没效果。建议用chrome.
这个帖子描述spring mvc3处理异常的另类技术。源码在github的spring-mvc-error-handling目录下。它是以带注释的sprimg mvc的例子为基础的。
spring3之前如何处理异常在spring3之前,异常是用HandlerExceptionResolvers来处理的。这个接口定义的一个方法:
ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex)
注意它返回了一个ModelAndView对象。因此,碰到异常意味着被定向到一个特别的页面。然而,这种方法不适合REST Ajax访问JSONs.在这种情况下,我们并不想返回一个页面,而只是想返回一个http状态码。下面就描述一种可行的解决方案。
为了本例,设计了2个假的异常:CustmoziedException1和CustomizedException2.为了把这2个异常映射到视图,我们仍然可以使用SimpleMappingExceptionResolver.
SimpleMappingExceptionResolver getSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver result
= new SimpleMappingExceptionResolver();
// Setting customized exception mappings
Properties p = new Properties();
p.put(CustomizedException1.class.getName(), "Errors/Exception1");
result.setExceptionMappings(p);
// Un-mapped exceptions will be directed there
result.setDefaultErrorView("Errors/Default");
// Setting a default HTTP status code
result.setDefaultStatusCode(HttpStatus.BAD_REQUEST.value());
return result;
}
我们把CustomizedException1映射到Errors/Exception1 jsp页面(视图).我们同样为没有映射的异常设置了一个默认错误页面,在此例中就是CusomizedException2.我们同样设置了默认的http状态码。
下面是Exeption1 jsp页面。默认页面与此相似。
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;" charset=UTF-8">
<title>Welcome To Exception I !!!</title>
</head>
<body>
<h1>Welcome To Exception I !!!</h1>
Exception special message:<br/><br/>
${exception.specialMsg}<br /><br/>
<a href="<c:url value='/'/>">Home</a>
</body>
</html>
为触发这些异常,我们创建一个假的异常控制器:
@Controller
public class TriggeringErrorsController {
@RequestMapping(value = "/throwCustomizedException1")
public ModelAndView throwCustomizedException1(
HttpServletRequest request,HttpServletResponse response)
throws CustomizedException1 {
throw new CustomizedException1(
"Houston, we have a problem!");
}
@RequestMapping(value = "/throwCustomizedException2")
public ModelAndView throwCustomizedException2(
HttpServletRequest request,HttpServletResponse response)
throws CustomizedException2 {
throw new CustomizedException2(
"Something happened on the way to heaven!");
}
@ExceptionHandler(Customized4ExceptionHandler.class)
@ResponseStatus(value=HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleCustomized4Exception(
Customized4ExceptionHandler ex) {
return ex.getSpecialMsg();
}
@RequestMapping(value = "/throwCustomized4ExceptionHandler")
public ModelAndView throwCustomized4ExceptionHandler(
HttpServletRequest request,HttpServletResponse response)
throws Customized4ExceptionHandler {
throw new Customized4ExceptionHandler(
"S.O.S !!!!");
}
}
在spring3之前,你必须在web.xml中把SimpleMappingExceptionResolver声明成@Bean,我们用HandlerExceptionResolverComposite,后面对此将有所描述。
在web.xml中,我们配置一个http状态吗目标页面,这是处理这种问题的另一种方法。
译者注:访问http://localhost:8080/sprErrorHand/piaji.html就可以调用该页面。
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/pages/Errors/My404.jsp</location>
</error-page>
spring 3.x以来有什么新特性?
@ResponseStatus这个注释是一个新方法,用来设置一个http状态吗,当被注释的方法被调用时。这些都由ResponseStatusExceptionResolver来处理。@ExceptionHandler注释用来在spring中方便地处理异常。这些注释被AnnotationMethodHandlerExeptionResolver来处理。
下面代码表明这些注释如何被用来设置http状态码,当一个自定义的异常被触发时。这条信息会返回到响应的正文中。
@ExceptionHandler(Customized4ExceptionHandler.class)
@ResponseStatus(value=HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleCustomized4Exception(
Customized4ExceptionHandler ex) {
return ex.getSpecialMsg();
}
@RequestMapping(value = "/throwCustomized4ExceptionHandler")
public ModelAndView throwCustomized4ExceptionHandler(
HttpServletRequest request,HttpServletResponse response)
throws Customized4ExceptionHandler {
throw new Customized4ExceptionHandler(
"S.O.S !!!!");
}
在用户端这边,如果用Ajax调用,错误信息可以用下面JQuery代码:
var prefix = "/spring-mvc-error-handling";
var ExceptionHandler = function() {
$.ajax({
type: 'GET',
url: prefix + "/throwCustomized4ExceptionHandler",
dataType: 'json',
async: true,
success: function(result) {
alert('Unexpected success !!!');
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status + " " + jqXHR.responseText);
}
});
}
有些人喜欢用Ajax返回一个JSON对象,带有错误码和某种信息来处理异常。我觉得没必要这样。一个简单的带有信息的错误码使得它很简单。
因为我们用了几个resolver,我们需要一个综合的resolver:
@Bean
HandlerExceptionResolverComposite getHandlerExceptionResolverComposite() {
HandlerExceptionResolverComposite result
= new HandlerExceptionResolverComposite();
List<HandlerExceptionResolver> l
= new ArrayList<HandlerExceptionResolver>();
l.add(new AnnotationMethodHandlerExceptionResolver());
l.add(new ResponseStatusExceptionResolver());
l.add(getSimpleMappingExceptionResolver());
l.add(new DefaultHandlerExceptionResolver());
result.setExceptionResolvers(l);
return result;
}
DefaultHandlerExceptionResolver处理标准的spring异常并把它们翻译成相应的http状态码。
程序运行截图(chrome中)
原文:http://technotes.tostaky.biz/2012/11/spring-mvc-error-handling.html
github:https://github.com/JVerstry/Web-Related-Examples
源代码:http://pan.baidu.com/share/link?shareid=590269867&uk=3878681452