Spring MVC全局异常处理和单元测试_动力节点Java学院整理
在springMVC的配置文件中:
/error/error 500 org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
这里主要的类是SimpleMappingExceptionResolver类,和他的父类AbstractHandlerExceptionResolver类。
具体可以配置哪些属性,我是通过查看源码知道的。
你也可以实现HandlerExceptionResolver接口,写一个自己的异常处理程序。spring的扩展性是很好的。
通过SimpleMappingExceptionResolver我们可以将不同的异常映射到不同的jsp页面(通过exceptionMappings属性的配置)。
同时我们也可以为所有的异常指定一个默认的异常提示页面(通过defaultErrorView属性的配置),如果所抛出的异常在exceptionMappings中没有对应的映射,则Spring将用此默认配置显示异常信息。
注意这里配置的异常显示界面均仅包括主文件名,至于文件路径和后缀已经在viewResolver中指定。如/error/error表示/error/error.jsp
显示错误的jsp页面:
<%@pagelanguage="java"contentType="text/html;charset=GBK" pageEncoding="GBK"%> <%@pageimport="java.lang.Exception"%>错误页面 出错了
<% Exceptione=(Exception)request.getAttribute("exception"); out.print(e.getMessage()); %>
其中一句:request.getAttribute("exception"),key是exception,也是在SimpleMappingExceptionResolver类默认指定的,是可能通过配置文件修改这个值的,大家可以去看源码。
如何把全局异常记录到日志中?
在前的配置中,其中有一个属性warnLogCategory,值是“SimpleMappingExceptionResolver类的全限定名”。我是在SimpleMappingExceptionResolver类父类AbstractHandlerExceptionResolver类中找到这个属性的。查看源码后得知:如果warnLogCategory不为空,spring就会使用apache的org.apache.commons.logging.Log日志工具,记录这个异常,级别是warn。值:“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”,是“SimpleMappingExceptionResolver类的全限定名”。这个值不是随便写的。 因为我在log4j的配置文件中还要加入log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN,保证这个级别是warn的日志一定会被记录,即使log4j的根日志级别是ERROR。
如何给spring3MVC中的Action做JUnit单元测试?
使用了spring3MVC后,给action做单元测试变得很方便,我以前从来不给action写单元测试的,现在可以根据情况写一些了。 不用给每个Action都写单元测试吧,自己把握。
JUnitActionBase类是所有JUnit的测试类的父类
packagetest; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.junit.BeforeClass; importorg.springframework.mock.web.MockServletContext; importorg.springframework.web.context.WebApplicationContext; importorg.springframework.web.context.support.XmlWebApplicationContext; importorg.springframework.web.servlet.HandlerAdapter; importorg.springframework.web.servlet.HandlerExecutionChain; importorg.springframework.web.servlet.HandlerMapping; importorg.springframework.web.servlet.ModelAndView; importorg.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; importorg.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; /** *说明:JUnit测试action时使用的基类 * * * */ publicclassJUnitActionBase{ privatestaticHandlerMappinghandlerMapping; privatestaticHandlerAdapterhandlerAdapter; /** *读取spring3MVC配置文件 */ @BeforeClass publicstaticvoidsetUp(){ if(handlerMapping==null){ String[]configs={"file:src/springConfig/springMVCxml"}; XmlWebApplicationContextcontext=newXmlWebApplicationContext(); context.setConfigLocations(configs); MockServletContextmsc=newMockServletContext(); context.setServletContext(msc);context.refresh(); msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,context); handlerMapping=(HandlerMapping)context .getBean(DefaultAnnotationHandlerMapping.class); handlerAdapter=(HandlerAdapter)context.getBean(context.getBeanNamesForType(AnnotationMethodHandlerAdapter.class)[0]); } } /** *执行request对象请求的action * *@paramrequest *@paramresponse *@return *@throwsException */ publicModelAndViewexcuteAction(HttpServletRequestrequest,HttpServletResponseresponse) throwsException{ HandlerExecutionChainchain=handlerMapping.getHandler(request); finalModelAndViewmodel=handlerAdapter.handle(request,response, chain.getHandler()); returnmodel; } }
这是个JUnit测试类,我们可以newRequest对象,来参与测试,太方便了。给request指定访问的URL,就可以请求目标Action了。
packagetest.com.app.user; importorg.junit.Assert; importorg.junit.Test; importorg.springframework.mock.web.MockHttpServletRequest; importorg.springframework.mock.web.MockHttpServletResponse; importorg.springframework.web.servlet.ModelAndView; importtestJUnitActionBase; /** *说明:测试OrderAction的例子 * * * */ publicclassTestOrderActionextendsJUnitActionBase{ @Test publicvoidtestAdd()throwsException{ MockHttpServletRequestrequest=newMockHttpServletRequest(); MockHttpServletResponseresponse=newMockHttpServletResponse(); request.setServletPath("/order/add"); request.addParameter("id","1002"); request.addParameter("date","2010-12-30"); request.setMethod("POST"); //执行URI对应的action finalModelAndViewmav=this.excuteAction(request,response); //Assertlogic Assert.assertEquals("order/add",mav.getViewName()); Stringmsg=(String)request.getAttribute("msg"); System.out.println(msg); } }
需要说明一下 :由于当前最想版本的Spring(Test)3.0.5还不支持@ContextConfiguration的注解式contextfile注入,所以还需要写个setUp处理下,否则类似于Tiles的加载过程会有错误,因为没有ServletContext。3.1的版本应该有更好的解决方案。