Spring MVC全局异常处理和单元测试_动力节点Java学院整理
在spring mvc的配置文件中:
<!-- 总错误处理--> <bean id="exceptionresolver" class="org.springframework.web.servlet.handler.simplemappingexceptionresolver"> <property name="defaulterrorview"> <value>/error/error</value> </property> <property name="defaultstatuscode"> <value>500</value> </property> <property name="warnlogcategory"> <value>org.springframework.web.servlet.handler.simplemappingexceptionresolver</value> </property> </bean>
这里主要的类是simplemappingexceptionresolver类,和他的父类abstracthandlerexceptionresolver类。
具体可以配置哪些属性,我是通过查看源码知道的。
你也可以实现handlerexceptionresolver接口,写一个自己的异常处理程序。spring的扩展性是很好的。
通过simplemappingexceptionresolver我们可以将不同的异常映射到不同的jsp页面(通过exceptionmappings属性的配置)。
同时我们也可以为所有的异常指定一个默认的异常提示页面(通过defaulterrorview属性的配置),如果所抛出的异常在exceptionmappings中没有对应的映射,则spring将用此默认配置显示异常信息。
注意这里配置的异常显示界面均仅包括主文件名,至于文件路径和后缀已经在viewresolver中指定。如/error/error表示/error/error.jsp
显示错误的jsp页面:
<%@ page language="java" contenttype="text/html; charset=gbk" pageencoding="gbk"%> <%@ page import="java.lang.exception"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=gbk"> <title>错误页面</title> </head> <body> <h1>出错了</h1> <% exception e = (exception)request.getattribute("exception"); out.print(e.getmessage()); %> </body> </html>
其中一句: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。
如何给spring3 mvc中的action做junit单元测试?
使用了spring3 mvc后,给action做单元测试变得很方便,我以前从来不给action写单元测试的,现在可以根据情况写一些了。 不用给每个action都写单元测试吧,自己把握。
junitactionbase类是所有junit的测试类的父类
package test; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.junit.beforeclass; import org.springframework.mock.web.mockservletcontext; import org.springframework.web.context.webapplicationcontext; import org.springframework.web.context.support.xmlwebapplicationcontext; import org.springframework.web.servlet.handleradapter; import org.springframework.web.servlet.handlerexecutionchain; import org.springframework.web.servlet.handlermapping; import org.springframework.web.servlet.modelandview; import org.springframework.web.servlet.mvc.annotation.annotationmethodhandleradapter; import org.springframework.web.servlet.mvc.annotation.defaultannotationhandlermapping; /** * 说明: junit测试action时使用的基类 * * * */ public class junitactionbase { private static handlermapping handlermapping; private static handleradapter handleradapter; /** * 读取spring3 mvc配置文件 */ @beforeclass public static void setup() { if (handlermapping == null) { string[] configs = { "file:src/springconfig/springmvcxml" }; xmlwebapplicationcontext context = new xmlwebapplicationcontext(); context.setconfiglocations(configs); mockservletcontext msc = new mockservletcontext(); 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 * * @param request * @param response * @return * @throws exception */ public modelandview excuteaction(httpservletrequest request, httpservletresponse response) throws exception { handlerexecutionchain chain = handlermapping.gethandler(request); final modelandview model = handleradapter.handle(request, response, chain.gethandler()); return model; } }
这是个junit测试类,我们可以new request对象,来参与测试,太方便了。给request指定访问的url,就可以请求目标action了。
package test.com.app.user; import org.junit.assert; import org.junit.test; import org.springframework.mock.web.mockhttpservletrequest; import org.springframework.mock.web.mockhttpservletresponse; import org.springframework.web.servlet.modelandview; import testjunitactionbase; /** * 说明: 测试orderaction的例子 * * * */ public class testorderaction extends junitactionbase { @test public void testadd() throws exception { mockhttpservletrequest request = new mockhttpservletrequest(); mockhttpservletresponse response = new mockhttpservletresponse(); request.setservletpath("/order/add"); request.addparameter("id", "1002"); request.addparameter("date", "2010-12-30"); request.setmethod("post"); // 执行uri对应的action final modelandview mav = this.excuteaction(request, response); // assert logic assert.assertequals("order/add", mav.getviewname()); string msg=(string)request.getattribute("msg"); system.out.println(msg); } }
需要说明一下 :由于当前最想版本的spring(test) 3.0.5还不支持@contextconfiguration的注解式context file注入,所以还需要写个setup处理下,否则类似于tiles的加载过程会有错误,因为没有servletcontext。3.1的版本应该有更好的解决方案。
推荐阅读
-
Spring MVC入门_动力节点Java学院整理
-
Spring MVC全局异常处理和单元测试_动力节点Java学院整理
-
Spring MVC之WebApplicationContext_动力节点Java学院整理
-
Spring MVC访问静态文件_动力节点Java学院整理
-
Spring mvc工作原理_动力节点Java学院整理
-
Spring MVC的优点与核心接口_动力节点Java学院整理
-
spring mvc常用注解_动力节点Java学院整理
-
Spring MVC简介_动力节点Java学院整理
-
Spring MVC拦截器_动力节点Java学院整理
-
Java中struts2和spring MVC的区别_动力节点Java学院整理