SpringMVC注解(三)

十一、如何实现全局的异常处理?

spring MVC的配置文件中:

 

 <!-- 总错误处理-->

 <beanid="exceptionResolver"class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

 <propertyname="defaultErrorView">

 <value>/error/error</value>

 </property>

 <propertyname="defaultStatusCode">

 <value>500</value>

 </property>

 <propertyname="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>

<metahttp-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")keyexception,也是在SimpleMappingExceptionResolver类默认指定的,是可能通过配置文件修改这个值的,大家可以去看源码。

参考文章:

http://www.blogjava.net/wuxufeng8080/articles/191150.html

http://fangjunai.blog.163.com/blog/static/1124970520108102013839/

十二、如何把全局异常记录到日志中?

在前的配置中,其中有一个属性warnLogCategory,值是“SimpleMappingExceptionResolver类的全限定名。我是在SimpleMappingExceptionResolver类父类AbstractHandlerExceptionResolver类中找到这个属性的。查看源码后得知:如果warnLogCategory不为空,spring就会使用apacheorg.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中的ActionJUnit单元测试?

使用了spring3 MVC后,给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时使用的基类
 * 
 *
 * 
 * @author 赵磊
 * 
 * @version 创建时间:2011-2-2 下午10:27:03
 */

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/springMVC.xml" };

            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 test.JUnitActionBase;

/**
 * 
 * 说明:测试OrderAction的例子
 * 
 *
 * 
 * @author 赵磊
 * 
 * @version 创建时间:2011-2-2 下午10:26:55
 */

public class TestOrderAction extends JUnitActionBase {

    @Test
    public void testAdd() throws Exception {

        MockHttpServletRequest request = new MockHttpServletRequest();

        MockHttpServletResponse response = new MockHttpServletResponse();

        request.setRequestURI("/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的加载过程会有错误,因为没有ServletContext3.1的版本应该有更好的解决方案,参见: https://jira.springsource.org/browse/SPR-5243

参考http://www.iteye.com/topic/828513

十四、转发与重定向

可以通过redirect/forward:url方式转到另一个Action进行连续的处理。

可以通过redirect:url 防止表单重复提交

写法如下:

return "forward:/order/add";

return "redirect:/index.jsp";

十五、处理ajax请求

1、引入下面两个jar包,我用的是1.7.2,好像1.4.2版本以上都可以,下载地址: http://wiki.fasterxml.com/JacksonDownload

jackson-core-asl-1.7.2.jar

jackson-mapper-asl-1.7.2.jar

2spring的配置文件中要有这一行,才能使用到spring内置支持的json转换。如果你手工把POJO转成json就可以不须要使用spring内置支持的json转换。

<mvc:annotation-driven />

3、使用@ResponseBody注解

 

/**

* ajax测试

* http://127.0.0.1/mvc/order/ajax

*/



@RequestMapping("/ajax")

@ResponseBody

public Object ajax(HttpServletRequest request){

    List<String> list=new ArrayList<String>();
    
    list.add("电视");
    
    list.add("洗衣机");
    
    list.add("冰箱");
    
    list.add("电脑");
    
    list.add("汽车");
    
    list.add("空调");
    
    list.add("自行车");
    
    list.add("饮水机");
    
    list.add("热水器");
    
    return list; 
}

 

posted @ 2016-08-25 13:45  星火spark  阅读(226)  评论(0)    收藏  举报