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

声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。