欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring MVC全局异常处理和单元测试_动力节点Java学院整理

程序员文章站 2024-03-31 11:38:16
在spring mvc的配置文件中:

在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的版本应该有更好的解决方案。