Spring MVC 静态资源的访问

HappyHeng 2013-10-23

问题描述:

我们在springmvc框架中为了是URL更符合RESTful风格,通常在web.xml中会配置spring框架servlet的url拦截为"/",也就是拦截所有资源的url请求,这样一来,所有的资源包括,js|css|图片|所有静态资源都将经过框架的servlet拦截。不应该是这样的。所以有了对应servlet的url拦截为“/”的时候,对静态资源访问不应该经过servlet拦截的问题处理。如果servlet-mapping的url-pattern为“*.do”,就是只拦截有一定后缀的url,那么就不会有静态资源访问的问题了。

一、springmvc下默认访问的三种方式

1>.第一种访问tomcat容器的默认页面

<welcome-file-list> 
  <welcome-file>/index.html</welcome-file> 
</welcome-file-list>

这种方式通常用来访问我们的初始页面

2>.第二种spirngmvc默认indexcontroller方式

(如果在tomcat容器没有配置默认页面,怎springmvc会主动去寻找/index的controller,如果有则会调用,没有则会显示404页面)

@RequestMapping(value="/index")
public ModelAndView index(HttpServletRequest request, HttpServletResponse response){
       return new ModelAndView("index");
}

3>.第三种spirngmvc配置根节点访问“/”方式

@RequestMapping(value="/") 
public ModelAndView index(HttpServletRequest request,HttpServletResponse response){ 
         return new ModelAndView("index"); 
}

或者

<mvc:view-controller path="/" view-name="home"/>

ThisisashortcutfordefiningaParameterizableViewControllerthatimmediatelyforwardstoaviewwheninvoked.

※三种方法优先级别是1>3>2

二、springmvc使用RESTFull的url风格拦截所有资源请求时的静态资源的访问配置,避免被springmvc框架的匹配,因为这是没有必要的,可恶的。

※.如果springmvc框架的servlet-mapping的url-pattern为“/”,若我们没有处理静态资源,就会造成静态资源的访问出现404

解决方案:

1>.激活web应用服务器(如Tomcat)的defaultServlet来处理静态文件

<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.jpg</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.js</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.css</url-pattern>
	</servlet-mapping>

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

要写在DispatcherServlet的前面,让defaultServlet先拦截,这个就不会进入Spring了,可能性能是最好的。

Tomcat,Jetty,JBoss,andGlassFish默认Servlet的名字--"default"

GoogleAppEngine默认Servlet的名字--"_ah_default"

Resin默认Servlet的名字--"resin-file"

WebLogic默认Servlet的名字--"FileServlet"

WebSphere默认Servlet的名字--"SimpleFileServlet"

2>.在spring3.0.4以后版本提供了<mvc:resources/>

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

/static/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是webapplication根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period可以使得静态资源进行webcache

如果出现下面的错误,可能是没有配置<mvc:annotation-driven/>的原因。

报错WARNING:NomappingfoundforHTTPrequestwithURI[/mvc/user/findUser/lisi/770]inDispatcherServletwithname'springMVC'

使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,

key为mapping的URIpattern值,而value为ResourceHttpRequestHandler,

这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问.

另外需要注意的一点是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对staticuri的defaultHandler就是ResourceHttpRequestHandler,

否则无法处理staticresourcesrequest.

3>.使用<mvc:default-servlet-handler/>

<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是匹配"/**"的,所以一定会匹配上,再响应图片。

※加载一个静态资源是却要经过框架servlet的层层pattern,不必要的性能开销。

最后还是特别强调,像一开始说的,如果框架servlet的url-pattern是指定后缀的,如“*.go”,那么框架的url拦截就只会匹配后缀带.go的request,就不会有静态资源访问的问题了。

相关推荐

itjavashuai / 0评论 2020-07-27