SpringMVC注解(二)

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

 

如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题。如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg的访问也就被拦截了。

目的:可以正常访问静态文件,不要找不到静态文件报404
方案一:激活TomcatdefaultServlet来处理静态文件

 

 1  <servlet-mapping>
 2 
 3 <servlet-name>default</servlet-name>
 4 
 5 <url-pattern>*.jpg</url-pattern>
 6 
 7  </servlet-mapping>
 8 
 9 <servlet-mapping>
10 
11  <servlet-name>default</servlet-name>
12 
13  <url-pattern>*.js</url-pattern>
14 
15  </servlet-mapping>
16 
17  <servlet-mapping>
18 
19 <servlet-name>default</servlet-name>
20 
21 <url-pattern>*.css</url-pattern>
22 
23 </servlet-mapping>

 

 

 

13.要配置多个,每种文件配置一个

要写在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 的使用方法:

Xml代码

1. <!-- 对静态资源文件的访问 -->

2. <mvc:resourcesmapping="/images/**"location="/images/"/>
/images/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache
如果出现下面的错误,可能是没有配置<mvc:annotation-driven />的原因。
报错WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

使用<mvc:resources/>元素,mappingURI注册到SimpleUrlHandlerMappingurlMap,
keymappingURI pattern,valueResourceHttpRequestHandler,
这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问.
另外需要注意的一点是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对static uridefaultHandler就是ResourceHttpRequestHandler,
否则无法处理static resources request.

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

Xml代码

1. <mvc:default-servlet-handler/>

会把"/**" url,注册到SimpleUrlHandlerMappingurlMap,把对静态资源的访问由HandlerMapping转到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler处理并返回.
DefaultServletHttpRequestHandler使用就是各个Servlet容器自己的默认Servlet.

补充说明:多个HandlerMapping的执行顺序问题:

DefaultAnnotationHandlerMappingorder属性值是:0
<mvc:resources/ >自动注册的SimpleUrlHandlerMappingorder属性值是:2147483646

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

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

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

最后再说明一下,如何你的DispatcherServlet拦截 *.do这样的URL,就不存上述问题了。
八、请求如何映射到具体的Action中的方法?
方案一:基于xml配置映射,可以利用SimpleUrlHandlerMappingBeanNameUrlHandlerMapping进行Url映射和拦截请求。
配置方法略。
方案二:基于注解映射,可以使用DefaultAnnotationHandlerMapping

Xml代码

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

但前面我们配置了<mvc:annotation-driven />,他会自动注册这个bean,就不须要我们显示的注册这个bean了。
以上都可以注入interceptors,实现权限控制等前置工作。
我们使用第2种,基于注解来使用spring MVC

并在action类上使用:
@Controller
@RequestMapping("/user")
九、Spring中的拦截器:
Spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口,

org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,
实现这个接口或继承此类,可以非常方便的实现自己的拦截器。
有以下三个方法
Action之前执行:
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler);
生成视图之前执行
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView);
最后执行,可用于释放资源
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
preHandle中,可以进行编码、安全控制等处理;
postHandle中,有机会修改ModelAndView
afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
参数中的Object handler是下一个拦截器。
十、如何使用拦截器?
自定义一个拦截器,要实现HandlerInterceptor接口:

Java代码

1. publicclass 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

 

 <mvc:interceptors>

 <mvc:interceptor>

 <mvc:mappingpath="/user/*"/><!-- /user/* -->

 <beanclass="com.mvc.MyInteceptor"></bean>

 </mvc:interceptor>

</mvc:interceptors>

 

 

 

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

方案三,HandlerMappint上的拦截器

 

 <beanclass="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">

 <propertyname="interceptors">

 <list>

 <beanclass="com.mvc.MyInteceptor"></bean>

 </list>

 </property>

 </bean>

 

 

 

如果使用了<mvc:annotation-driven />它会自动注册DefaultAnnotationHandlerMapping AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。

当然我们可以通过人工配置上面的两个Bean,不使用<mvc:annotation-driven />,就可以interceptors属性注入拦截器了。

其实我也不建议使用<mvc:annotation-driven />,而建议手动写配置文件,来替代<mvc:annotation-driven />,这就控制力就强了。

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