在乐视风口浪尖的时候,敢于站出来说自己是乐视的而即便被打脸的,也就是自个儿了。固然自己将来不在乐视了,提起来在乐视工作过,我也依旧挺骄傲的。因为这是一个有不错,敢拼敢干的店家。想起复仇者联盟里Fury指挥官的一句话:Until
such time as the world ends, we will act as though it intends to spin
on.
下一周我们去怀柔团建,人家都是两个家长住一间,带小孩的是五个人一间。我带着我家小王子五个人住了1380一晚的别墅,据说是最好的屋子。像本人说过的,每每好事儿都让自身摊上了,所以仍然该干啥干啥。

动用spring MVC,配置DispatcherServlet是率先步。

  我们单位叫基础工作平台部,负责基本管理乐视视频的录像,音频及各地的特辑数据。单台QPS几千,业内人员表示并发量不大,只是集团的汇聚缓存不尽人意。

DispatcherServlet是一个Servlet,所以可以安排两个DispatcherServlet。

  开放平台的序列框架是这么的:

DispatcherServlet是放置控制器,配置在web.xml文件中的。拦截匹配的乞求,Servlet拦截匹配规则要自已定义,把拦截下来的乞求,依照某某规则分发到目的Controller(我们写的Action)来拍卖。

图片 1

 

  这是一个很正规的网站类别框架,基本得以知足当下多数SOA垂直拆分网站架构的需要。项目倚重关系是这么的:

“某某规则”:是基于你拔取了哪个HandlerMapping接口的实现类的不比而各异。

图片 2

 

 客户层ope-web拔取的是正统的spring mvc架构。定义了六个视图解析器:

先来看率先个例证:

  1>InternalResourceViewResolver  那些是UrlBasedViewResolver的便宜子类。因为前端页面使用的是JSP,这么些肯定是首选。

Xml代码 

  2>康芒斯(Commons)MultipartResolver  涉及上传录像和图表,那么些必要。需要注意最大上传大小和最大占用内存大小。

 1   <web-app>  
 2       <servlet>  
 3           <servlet-name>example</servlet-name>  
 4           <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
 5           <load-on-startup>1</load-on-startup>  
 6       </servlet>  
 7       <servlet-mapping>  
 8           <servlet-name>example</servlet-name>  
 9           <url-pattern>*.form</url-pattern>  
10      </servlet-mapping>  
11  </web-app>  

  3>SimpleMappingExceptionResolver  定义统一非凡处理。咱们以此项目中安排的默认跳转页面defaultErrorView是404,相当时指导的属性exceptionAttribute是ex。在exceptionMappings只定义了一个叫AccessException的非常,跳转到errors页面。

<load-on-startup>1</load-on-startup>是启动顺序,让这些Servlet随Servletp容器一起启动。

说到Spring MVC依然先放一张架构图吧

 <url-pattern>*.form</url-pattern>会拦截*.form结尾的伸手。

  图片 3

 

 

 <servlet-name>example</servlet-name>这多少个Servlet的名字是example,可以有四个DispatcherServlet,是通过名字来分此外。每一个DispatcherServlet有协调的WebApplicationContext上下文对象。同时保留的ServletContext中和Request对象中,关于key,未来表达。

 由图中得以见见任何spring
mvc主题是dispatcherServlet,客户端将请求提交给它,它查询web.xml里的mapping定义找到Controller。大家项目mapping定义是

在DispatcherServlet的开头化过程中,框架会在web应用的WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml的配备文件,生成文书中定义的bean。

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

其次个例证:

  所有的乞请都走这多少个dispatcherServlet,按照applicationContext.xml的配置处理,这个中配备了全自动扫描的controller路径和下面提到的视图解释器。来看一眼dispatcherServlet的为主源码:

Xml代码 

protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); //文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
initLocaleResolver(context); //本地化解析
initThemeResolver(context);   //主题解析
initHandlerMappings(context); //通过HandlerMapping,将请求映射到处理器
initHandlerAdapters(context); //通过HandlerAdapter支持多种类型的处理器
initHandlerExceptionResolvers(context); //如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
initRequestToViewNameTranslator(context); //直接解析请求到视图名
initViewResolvers(context); //通过ViewResolver解析逻辑视图名到具体视图实现
initFlashMapManager(context); //flash映射管理器     }
 1 <servlet>  
 2       <servlet-name>springMVC</servlet-name>  
 3       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
 4       <init-param>  
 5           <param-name>contextConfigLocation</param-name>  
 6           <param-value>classpath*:/springMVC.xml</param-value>  
 7      </init-param>  
 8       <load-on-startup>1</load-on-startup>  
 9   </servlet>  
10  <servlet-mapping>  
11      <servlet-name>springMVC</servlet-name>  
12      <url-pattern>/</url-pattern>  
13  </servlet-mapping> 

  从命名就能够看看,那多少个中紧要采用了方针情势,对两样的视图选拔不同的政策。ApplicationContext是一个空洞接口,spring的上下文将框架之中的一一零部件信息都由此一个context透露给外部,是一个门面情势。

指明了配备文件的文本名,不使用默认配置文件名,而采用springMVC.xml配置文件。

  dispatcherServlet在进展呼吁分发的时候还提供了有的服务:

其中<param-value>**.xml</param-value>这里可以使用多种写法
1、不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
3、<param-value>classpath*:springMVC-mvc.xml</param-value>
4、六个值用逗号分隔

  1>保存现场:保存request掌握的快照,以便能在必要时回升。

 

  2>将框架需要的对象放入request中,以便view和handler使用。

Servlet拦截匹配规则足以自已定义,Servlet拦截哪类URL合适? 

  3>在伸手分发后卷土重来现场。

当映射为@RequestMapping(“/user/add”)时:
1、拦截*.do,例如:/user/add.do,弊端:所有的url都要以.do结尾。不会影响访问静态文件。
2、拦截/app/*,例如:/app/user/add,弊端:请求的url都要含有/app,@RequestMapping(“/user/add”)中不须要包含/app。
3、拦截/,例如:/user/add,弊端:对jpg,js,css静态文件的访问也被拦截不可能健康呈现。前面有解决办法。
4、拦截/*,可以走到Action中,但转发到jsp时再次被堵住,无法访问到jsp。

  提出我们看看DispatcherServlet的源码,平常做spring
mvc项目以来,相信源码不难看懂。我们可能时时遇上的题材,比如看了<Java并发编程实践>这本书,感觉那些事物品种中用不到啊。其实不是这么,这本书很基础,里面的事物都用到了,只是封装在框架里了,很多个人没仔细讨论而已。记得书里讲安全宣布的时候讲到使用Collections.unmodifiableMap来发表一个只读的map。这多少个在DispatcherServlet源码里对它的行使相当的出众:将flashmap的一个快照保存在request的习性里以备查看用。

 

    FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
    if (inputFlashMap != null) {
      request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
    }

 

  从源码到原理,最基础的,比如:调用构造器来创制一个Java类的时候,要明了这几个构造器实际上是一个静态方法。所以率先次调用构造器创设对象的时候,或者访问这么些类的静态方法或者静态成员的时候,Java解释器先要定位其字节码(class)文件,加载了字段文件后,要开展具有的静态起始化工作,这些工作只举办一回。

五、双亲上下文的辨证

  多研商,从编码到排查问题,相信都不会无从动手。

 

  下边说了在spring里可以安排不行处理页面,那个不经过spring直接走servlet也足以,只要在web.xml里安排一下:

设若您采用了listener监听器来加载配置,一般在Struts+Spring+hibernate的系列中都是使用listener监听器的。如下

图片 4

1 <listener>   
2     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
3   </listener> 

  DispatcherServlet还落实了一个很重大的法力:拦截器,我们项目中至关首要用它来做用户身份验证。用户身份验证要走乐视网统一的SSO,在隔着自身工位4,5排的用户核心组这边。只是一个表面接口的调用,然则总不可以每一遍用户发一个呼吁就调一回sso啊,外部调用network
hops延时很要紧的,所以那时就用到了集中式缓存。取了一回之后将表明身份的token存于redis里,有效期24刻钟。

Spring会成立一个大局的WebApplicationContext上下文,称为根上下文 ,保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性的值。可以拔取工具类取出上下文:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

  我们组和SSO组中间隔着前端组。JSP的静态页和JS都是前者提供的。为了更加解耦前后端的工作,数据的加载都走的是js异步调用,数据由前端去渲染。为了酬答前端的修改,jSP中大量引入静态分片。这些静态分片由一个后台服务定时将流行的分红刷新到当地。路径保存在该地缓存中。本地缓存用的google的guava工具包。

 

  再说拦截器,拦截器和servlet的过滤器很像,它们都是AOP变成思想的反映。这地方要注意:在web.xml配置的都是servlet的功能,在applicationContext里布置的是spring
mvc的功能。它们的区别也在那个地点。因为Filter是Servlet的科班,仅能在Servlet前后起功用。而interceptor和spring可以接近互动,可以深切到方法前后,非凡抛出上下等,可以访问Action上下文,值栈里的对象,可反复被调用。

DispatcherServlet是一个Servlet,可以同时配备两个,每个 DispatcherServlet有一个融洽的 WebApplicationContext上下文,那多少个上下文继承了 根上下文 中兼有东西。 保存在 ServletContext中,key是”org.springframework.web.servlet.FrameworkServlet.CONTEXT”+Servlet名称。当一个Request对象发生时,会把这么些WebApplicationContext上下文保存在Request对象中,key是DispatcherServlet.class.getName()+
“.CONTEXT”。可以利用工具类取出上下文:RequestContextUtils.getWebApplicationContext(request);

一般项目中用过滤器的就是utf8字符过滤器,在web.xml的配置如下:

 

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Spring中的 ApplicationContext实例可以被限制在不同的功能域(scope)中。
在web
MVC框架中,每个DispatcherServlet有它自己的WebApplicationContext ,这么些context继承了根 WebApplicationContext 的装有bean定义。
那多少个后续的bean也足以在各种serlvet自己的所属的域中被遮住(override),覆盖后的bean 可以被装置上只有这多少个servlet实例自己行使的性能。

  Servlet规范中还定义了一种非常类,监听器,用于监听域对象的开创与销毁,以及这个域对象属性的改动事件。大家项目中它来部署logback日志的监听。

 

  

小结:不选择listener监听器来加载spring的配置,改用DispatcherServlet来加载spring的配备,不要双亲上下文,只行使一个DispatcherServlet,事情就大概了,什么麻烦事儿也绝非了。

 

 

六、springMVC-mvc.xml配置文件片段讲解 (未利用默认配置文件名)

 

Xml代码 

 1 <!-- 自动扫描的包名 -->  
 2      <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan>  
 3        
 4      <!-- 默认的注解映射的支持 -->  
 5      <mvc:annotation-driven />  
 6        
 7      <!-- 视图解释类 -->  
 8      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
 9       <property name="prefix" value="/WEB-INF/jsp/"/>  
10      <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->  
11      <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />  
12     </bean>  
13       
14  <!-- 拦截器 -->  
15     <mvc:interceptors>  
16      <bean class="com.core.mvc.MyInteceptor" />  
17  </mvc:interceptors>       
18    
19      <!-- 对静态资源文件的访问  方案一 (二选一) -->  
20      <mvc:default-servlet-handler/>  
21        
22      <!-- 对静态资源文件的访问  方案二 (二选一)-->  
23  <mvc:resources mapping="**" location="" cache-period="31556926"/>  
24  <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>  
25  <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/>  

<context:component-scan/> 扫描指定的包中的类上的诠释,常用的诠释有:

@Controller 声明Action组件
@Service    声明Service组件   @Service(“myMovieLister”) 
@Repository 声明Dao组件
@Component   泛指组件, 当不好归类时. 
@RequestMapping(“/menu”)  请求映射
@Resource  用于注入,(
j2ee提供的 ) 默认按名称装配,@Resource(name=”beanName”) 
@Autowired 用于注入,(srping提供的) 默认按类型装配 
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope(“prototype”)   设定bean的作用域

 

<mvc:annotation-driven
/> 是一种简写模式,完全能够手动配置替代这种简写形式,简写模式得以让初学都很快利用默认配置方案。<mvc:annotation-driven
/> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter四个bean,是spring
MVC为@Controllers分发请求所必须的。
并提供了:数据绑定补助,@NumberFormatannotation襄助,@Date提姆(Tim)eFormat补助,@Valid补助,读写XML的支撑(JAXB),读写JSON的支撑(杰克逊)。
末端,我们处理响应ajax请求时,就应用到了对json的支撑。
后面,对action写JUnit单元测试时,要从springIOC容器中取DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter六个bean,来形成测试,取的时候要知道是<mvc:annotation-driven/>这一句注册的那六个bean。

 

<mvc:interceptors/> 是一种简写格局。通过看眼前的大图,知道,大家可以配备两个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也足以手动配置为各样HandlerMapping注入一个拦截器。

 

<mvc:default-servlet-handler/> 使用默认的Servlet来响应静态文件。

 

<mvc:resourcesmapping=”**”
location=””cache-period=”31556926″/> 匹配URL 
**  的URL被当作静态资源,由Spring读出到内存中再响应http。

 

 
七、怎么样访问到静态的文件,如jpg,js,css?

 

哪些你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的题目。假使您的DispatcherServlet拦截“/”,拦截了具有的央浼,同时对*.js,*.jpg的造访也就被堵住了。

 

目标:能够健康访问静态文件,不要找不到静态文件报404。
 
方案一:激活Tomcat的defaultServlet来拍卖静态文件

Xml代码 

 1 <servlet-mapping>   
 2       <servlet-name>default</servlet-name>  
 3       <url-pattern>*.jpg</url-pattern>     
 4   </servlet-mapping>    
 5   <servlet-mapping>       
 6       <servlet-name>default</servlet-name>    
 7       <url-pattern>*.js</url-pattern>    
 8   </servlet-mapping>    
 9   <servlet-mapping>        
10      <servlet-name>default</servlet-name>       
11      <url-pattern>*.css</url-pattern>      
12  </servlet-mapping> 

要部署五个,每种文件配置一个   

要写在DispatcherServlet的面前,让 defaultServlet先阻止,这一个就不会进入Spring了,我想性能是最好的呢。

 

Tomcat, Jetty, JBoss, and GlassFish  默认 Servlet的名字 — “default”
Google App Engine 默认 Servlet的名字 — “_ah_default”
Resin 默认 Servlet的名字 — “resin-file”
WebLogic 默认 Servlet的名字  — “FileServlet”
WebSphere  默认 Servlet的名字 — “SimpleFileServlet” 

 

 

方案二:在spring3.0.4将来版本提供了mvc:resources 
mvc:resources 的行使方法:

1 <mvc:resources mapping="**" location="" />

**照耀到ResourceHttpRequestHandler进行拍卖,location指定静态资源的地方.可以是web
application根目录下、jar包里面,这样能够把静态资源缩小到jar包中。cache-period 能够使得静态资源开展web
cache 
 
即便出现下边的失实,可能是没有布置<mvc:annotation-driven
/>的来由。 
报错WARNING: Nomapping found for HTTP request with URI
[/mvc/user/findUser/lisi/770] inDispatcherServlet with name
‘springMVC’

 

使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,
key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,
这么就高明的把对静态资源的走访由HandlerMapping转到ResourceHttpRequestHandler处理并回到,所以就补助classpath目录,jar包内静态资源的访问.
除此以外索要注意的少数是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对static
uri的defaultHandler就是ResourceHttpRequestHandler,
不然无法处理staticresources request.

 

 

方案三,使用<mvc:default-servlet-handler/>

 

Xml代码 

1 <mvc:default-servlet-handler/>

会把”/**”url,注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的走访由HandlerMapping转到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler处理并再次回到.
DefaultServletHttpRequestHandler使用就是逐一Servlet容器自己的默认Servlet.

 

 

补给表明:六个HandlerMapping的实践各样问题:

DefaultAnnotationHandlerMapping的order属性值是:0

<mvc:resources/ >自动注册的 SimpleUrlHandlerMapping的order属性值是: 2147483646

 

<mvc:default-servlet-handler/>自动注册 的SimpleUrlHandlerMapping 的order属性值是: 2147483647

 

spring会先执行order值相比较小的。当访问一个a.jpg图片文件时,先经过 DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,我们没有叫a.jpg的Action。再 按order值升序找,由于最后一个 SimpleUrlHandlerMapping 是匹配 “/**”的,所以肯定会配合上,再响应图片。

 

走访一个图纸,还要走层层匹配。真不知性能如何?改天做一下压力测试,与Apache比一比。

 

最后再作证一下,咋样你的DispatcherServlet拦截 *.do这样的URL,就不存上述问题了。

 

 

八、请求什么映射到现实的Action中的方法? 方案一:基于xml配置映射,可以采用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping举办Url映射和阻碍请求。
配备模式略。
 
方案二:基于讲明映射,可以使用DefaultAnnotationHandlerMapping。

Xml代码 

1 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">  </bean>

但前边大家安排了<mvc:annotation-driven/>,他会活动注册这多少个bean,就不须要我们体现的挂号这多少个bean了。  

 

 
如上都得以注入interceptors,实现权力决定等前置工作。
大家运用第2种,基于声明来行使springMVC

 

 

 并在action类上使用:

1 @Controller
2 @RequestMapping("/user")

九、Spring中的拦截器: Spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口,

org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,
贯彻这多少个接口或延续此类,可以丰盛便于的兑现团结的拦截器。
 
有以下五个艺术:
 
Action在此之前实施:

1 public boolean preHandle(HttpServletRequest request,
2    HttpServletResponse response, Object handler);

变迁视图在此之前实施

1 public void postHandle(HttpServletRequest request,
2    HttpServletResponse response, Object handler,
3    ModelAndView modelAndView);

终极执行,可用以释放资源

1 public void afterCompletion(HttpServletRequest request,
2    HttpServletResponse response, Object handler, Exception ex)

各自实现预处理、后甩卖(调用了瑟维斯(Service)并重临ModelAndView,但未开展页面渲染)、再次回到处理(已经渲染了页面) 
在preHandle中,可以展开编码、安全控制等拍卖; 
在postHandle中,有时机修改ModelAndView; 
在afterCompletion中,可以依照ex是否为null判断是否爆发了异常,举办日志记录。 
参数中的Objecthandler是下一个拦截器。
 

十、怎么着使用拦截器? 自定义一个拦截器,要兑现HandlerInterceptor接口:

Java代码 

1 public class MyInteceptor implements HandlerInterceptor { 
2 ////////
3 }

Spring MVC并没有总的拦截器,无法对富有的伸手举行前后拦截。
Spring
MVC的拦截器,是属于HandlerMapping级此外,可以有四个HandlerMapping ,每个HandlerMapping可以有协调的拦截器。
当一个请求按Order值从小到大,顺序执行HandlerMapping接口的实现类时,哪一个先有重临,这就足以终结了,前面的HandlerMapping就不走了,本道工序就形成了。就转到下一道工序了。
拦截器会在怎样时候实施吗?一个呼吁提交一个HandlerMapping时,那么些HandlerMapping先找有没有总括机来拍卖这么些请求,咋样找到了,就推行拦截器,执行完拦截后,交给目的电脑。
假如没有找到电脑,那么这些拦截器就不会被实施。

 

在spring MVC的部署文件中配备有两种情势:

方案一,(近似)总拦截器,拦截所有url

Java代码 

1 <mvc:interceptors>  
2      <bean class="com.app.mvc.MyInteceptor" />  
3   </mvc:interceptors>  

怎么叫“近似”,前边说了,Spring没有总的拦截器。

<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是能够找到电脑的,最多也只找到一个处理器,所以这一个拦截器总会被执行的。起到了总拦截器的功力。

 

 
方案二, (近似) 总拦截器, 拦截匹配的URL。

Xml代码 

1  <mvc:interceptors >    
2    <mvc:interceptor>    
3           <mvc:mapping path="/user/*" /> <!-- /user/*  -->    
4           <bean class="com.mvc.MyInteceptor"></bean>    
5       </mvc:interceptor>    
6   </mvc:interceptors> 

就是比 方案一多了一个URL匹配。

 

 

 

方案三,HandlerMappint上的拦截器

Xml代码 

1 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">       
2   <property name="interceptors">       
3        <list>       
4            <bean class="com.mvc.MyInteceptor"></bean>      
5        </list>       
6    </property>       
7   </bean>   

假设采用了<mvc:annotation-driven
/>, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这几个bean,所以就一贯不机会再给它注入interceptors属性,就无法指定拦截器。

自然我们得以经过人为配置方面的三个Bean,不行使 <mvc:annotation-driven/>,就足以 给interceptors属性 注入拦截器了。

 

实在自己也不提出采纳<mvc:annotation-driven/>,而提议手动写配置文件,来代表 <mvc:annotation-driven
/>,这就控制力就强了。

 

 

 

 

十一、怎样落实全局的充分处理?

在spring MVC的布置文件中:

Xml代码 

 1 <!-- 总错误处理-->  
 2   <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
 3       <property name="defaultErrorView">    
 4           <value>/error/error</value>  
 5       </property>  
 6       <property name="defaultStatusCode">    
 7           <value>500</value>  
 8       </property>     
 9   <property name="warnLogCategory">    
10         <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>  
11      </property>     
12  </bean>   

此地关键的类是SimpleMappingExceptionResolver类,和他的父类AbstractHandlerExceptionResolver类。

实际可以安排怎么着属性,我是透过翻看源码知道的。

你也得以实现HandlerExceptionResolver接口,写一个要好的分外处理程序。spring的扩大性是很好的。

 

 

因而SimpleMappingExceptionResolver大家可以将不同的百般映射到不同的jsp页面(通过exceptionMappings属性的配置)。

 

而且我们也得以为保有的不行指定一个默认的可怜提醒页面(通过defaultErrorView属性的配置),如果所抛出的相当在exceptionMappings中从不对号入座的炫耀,则Spring将用此默认配置显示相当信息。

注意这里配置的不胜突显界面均仅包括主文件名,至于文件路径和后缀已经在viewResolver中指定。如/error/error表示/error/error.jsp

 

 

展现错误的jsp页面:

Html代码 

 1 <%@ page language="java" contentType="text/html; charset=GBK"  
 2       pageEncoding="GBK"%>  
 3   <%@ page import="java.lang.Exception"%>  
 4  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
 5   <html>  
 6   <head>  
 7  <meta http-equiv="Content-Type" content="text/html; charset=GBK">  
 8   <title>错误页面</title>  
 9   </head>  
10  <body>  
11  <h1>出错了</h1>  
12  <%  
13  Exception e = (Exception)request.getAttribute("exception");  
14  out.print(e.getMessage());  
15  %>  
16  </body>  
17  </html> 

里面一句:request.getAttribute(“exception”),key是exception,也是在SimpleMappingExceptionResolver类默认指定的,是唯恐由此安排文件修改这么些值的,我们可以去看源码。

 

 参考著作:

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

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

 

 

 

十二、如何把全局万分记录到日志中?

在前的布局中,其中有一个特性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写单元测试的,再在不同了,方便了,所以肯定要写。

 

 JUnitActionBase类是拥有JUnit的测试类的父类

 

Java代码 

 1 package test;  
 2   import javax.servlet.http.HttpServletRequest;  
 3   import javax.servlet.http.HttpServletResponse;  
 4   import org.junit.BeforeClass;  
 5   import org.springframework.mock.web.MockServletContext;  
 6   import org.springframework.web.context.WebApplicationContext;  
 7   import org.springframework.web.context.support.XmlWebApplicationContext;  
 8   import org.springframework.web.servlet.HandlerAdapter;  
 9   import org.springframework.web.servlet.HandlerExecutionChain;  
10  import org.springframework.web.servlet.HandlerMapping;  
11  import org.springframework.web.servlet.ModelAndView;  
12  import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;  
13  import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;  
14  /**  
15  * 说明: JUnit测试action时使用的基类 
16  *  
17  * @author  赵磊 
18  * @version 创建时间:2011-2-2 下午10:27:03   
19  */   
20  public class JUnitActionBase {  
21      private static HandlerMapping handlerMapping;  
22      private static HandlerAdapter handlerAdapter;  
23      /** 
24       * 读取spring3 MVC配置文件 
25       */  
26      @BeforeClass  
27   public static void setUp() {  
28          if (handlerMapping == null) {  
29              String[] configs = { "file:src/springConfig/springMVC.xml" };  
30              XmlWebApplicationContext context = new XmlWebApplicationContext();  
31              context.setConfigLocations(configs);  
32              MockServletContext msc = new MockServletContext();  
33              context.setServletContext(msc);         context.refresh();  
34              msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);  
35              handlerMapping = (HandlerMapping) context  
36                      .getBean(DefaultAnnotationHandlerMapping.class);  
37              handlerAdapter = (HandlerAdapter) context.getBean(context.getBeanNamesForType(AnnotationMethodHandlerAdapter.class)[0]);     
38          }  
39     }  
40   
41     /** 
42       * 执行request对象请求的action 
43       *  
44       * @param request 
45       * @param response 
46       * @return 
47       * @throws Exception 
48       */  
49      public ModelAndView excuteAction(HttpServletRequest request, HttpServletResponse response)  
50   throws Exception {  
51          HandlerExecutionChain chain = handlerMapping.getHandler(request);  
52          final ModelAndView model = handlerAdapter.handle(request, response,  
53                  chain.getHandler());  
54         return model;  
55      }  
56  }  

这是个JUnit测试类,我们得以new
Request对象,来参加测试,太方便了。给request指定访问的URL,就能够请求目的Action了。

 

Java代码 

 1  package test.com.app.user;  
 2   import org.junit.Assert;  
 3   import org.junit.Test;  
 4   import org.springframework.mock.web.MockHttpServletRequest;  
 5   import org.springframework.mock.web.MockHttpServletResponse;  
 6   import org.springframework.web.servlet.ModelAndView;  
 7     
 8   import test.JUnitActionBase;  
 9     
10  /**  
11  * 说明: 测试OrderAction的例子 
12  *  
13  * @author  赵磊  
14  * @version 创建时间:2011-2-2 下午10:26:55   
15  */   
16    
17  public class TestOrderAction extends JUnitActionBase {  
18      @Test  
19      public void testAdd() throws Exception {  
20      MockHttpServletRequest request = new MockHttpServletRequest();  
21          MockHttpServletResponse response = new MockHttpServletResponse();  
22          request.setRequestURI("/order/add");  
23          request.addParameter("id", "1002");  
24          request.addParameter("date", "2010-12-30");  
25          request.setMethod("POST");  
26          // 执行URI对应的action  
27          final ModelAndView mav = this.excuteAction(request, response);  
28          // Assert logic  
29          Assert.assertEquals("order/add", mav.getViewName());  
30          String msg=(String)request.getAttribute("msg");  
31          System.out.println(msg);  
32      }  
33  }  

需要验证一下 :由于最近最想版本的Spring(Test)
3.0.5还不匡助@ContextConfiguration的注脚式context
file注入,所以还需要写个setUp处理下,否则类似于Tiles的加载过程会有不当,因为尚未ServletContext。3.1的版本应该有更好的缓解方案,参见: https://jira.springsource.org/browse/SPR-5243 

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

 

 

 

 

 十四、转发与重定向

可以透过redirect/forward:url模式转到另一个Action举办连续的处理。

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

写法如下:

1 return "forward:/order/add";
2 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

 

2、spring的安排文件中要有这一行,才能选用到spring内置援助的json转换。假若您手工把POJO转成json就足以不须要使用spring内置辅助的json转换。

<mvc:annotation-driven />

 

3、使用@ResponseBody注解

Java代码 

 1   /** 
 2    * ajax测试 
 3   * http://127.0.0.1/mvc/order/ajax 
 4    */  
 5     
 6   @RequestMapping("/ajax")  
 7   @ResponseBody  
 8   public Object ajax(HttpServletRequest request){  
 9       List<String> list=new ArrayList<String>();  
10      list.add("电视");  
11  nbsp;       list.add("洗衣机");  
12      list.add("冰箱");  
13      list.add("电脑");  
14      list.add("汽车");  
15      list.add("空调");  
16      list.add("自行车");  
17      list.add("饮水机");  
18      list.add("热水器");  
19      return list;  
20  }  

 

相关文章