How does Spring MVC access static files, such as jpg, js, css, png, gif?

If your DispatcherServlet intercepts URLs such as *.do, there is no problem of not being able to access static resources. If your DispatcherServlet intercepts "/", all requests are intercepted, and access to *.js, *.jpg is also intercepted.

Purpose: You can access static files normally, and do not report 404 when static files are not found.

 

 
Option 1: Activate Tomcat's defaultServlet to process static files

 

Xml code

<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>

To be written in front of DispatcherServlet, let defaultServlet intercept first, this will not enter Spring, I think the performance is the best .

The name of the default servlet that comes with Tomcat, Jetty, JBoss, and GlassFish -- "default"

The name of the default Servlet that comes with Google App Engine -- "_ah_default" The name
of the default Servlet that comes with Resin -- "resin-file"
The name of the default Servlet that comes with WebLogic -- "FileServlet"
The default Servlet that comes with WebSphere Name -- "SimpleFileServlet" 

 

Option 2: The usage of mvc:resources is provided after spring 3.0.4

 

Xml code

 <!-- 对静态资源文件的访问 -->
 <mvc:resources mapping="/images/**" location="/images/" />

/images/** is mapped to ResourceHttpRequestHandler for processing, and location specifies the location of static resources. It can be in the root directory of the web application or in the jar package, so that the static resources can be compressed into the jar package. cache-period can make static resources to be web cached. If the following error occurs, it may be the reason why <mvc:annotation-driven /> is not configured. Error WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

Using the <mvc:resources/> element, the URI of the mapping is registered in the urlMap of SimpleUrlHandlerMapping, the key is the URI pattern value of the mapping, and the value is ResourceHttpRequestHandler, so that the access to static resources is cleverly transferred from HandlerMapping to ResourceHttpRequestHandler for processing and processing. Return, so it supports the access to the classpath directory and static resources in the jar package. Another point to note is that the defaultHandler should not be set for SimpleUrlHandlerMapping. Because the defaultHandler for static uri is ResourceHttpRequestHandler, otherwise static resources request cannot be processed.

 

 

Option 3: Use <mvc:default-servlet-handler/>

 

Xml code

 <mvc:default-servlet-handler/>

The "/**" url will be registered in the urlMap of SimpleUrlHandlerMapping, and the access to static resources will be transferred from HandlerMapping to org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler for processing and return to DefaultServletHttpRequestHandler, which is the default of each Servlet container. Servlet.

Supplementary note: The execution order of multiple HandlerMappings:

The order property value of DefaultAnnotationHandlerMapping is: 0

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

Spring will execute the smaller order value first. When accessing an a.jpg image file, first find the processor through DefaultAnnotationHandlerMapping, it must not be found, we do not have an Action called a.jpg. Then search in ascending order of the order value. Since the last SimpleUrlHandlerMapping matches "/**", it will definitely match, and then respond to the picture.

Note: If DispatcherServlet intercepts URLs such as *.do, the above problem does not exist.

 

 

Option 4: Read the source code of spring carefully and understand it well.

 

17.16.7 Serving of Resources

This option allows static resource requests following a particular URL pattern to be served by a ResourceHttpRequestHandler from any of a list of Resource locations. This provides a convenient way to serve static resources from locations other than the web application root, including locations on the classpath. The cache-period property may be used to set far future expiration headers (1 year is the recommendation of optimization tools such as Page Speed and YSlow) so that they will be more efficiently utilized by the client. The handler also properly evaluates the Last-Modified header (if present) so that a 304 status code will be returned as appropriate, avoiding unnecessary overhead for resources that are already cached by the client. For example,to serve resource requests with a URL pattern of /resources/** from a public-resources directory within the web application root you would use:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/");
    }
}

And the same in XML:

<mvc:resources mapping="/resources/**" location="/public-resources/"/>

To serve these resources with a 1-year future expiration to ensure maximum use of the browser cache and a reduction in HTTP requests made by the browser:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/").setCachePeriod(31556926);
    }
}

And in XML:

<mvc:resources mapping="/resources/**" location="/public-resources/" cache-period="31556926"/>

The mapping attribute must be an Ant pattern that can be used by SimpleUrlHandlerMapping, and the location attribute must specify one or more valid resource directory locations. Multiple resource locations may be specified using a comma-separated list of values. The locations specified will be checked in the specified order for the presence of the resource for any given request. For example, to enable the serving of resources from both the web application root and from a known path of /META-INF/public-web-resources/ in any jar on the classpath use:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/""classpath:/META-INF/public-web-resources/");
    }
}

And in XML:

<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/public-web-resources/"/>

When serving resources that may change when a new version of the application is deployed it is recommended that you incorporate a version string into the mapping pattern used to request the resources so that you may force clients to request the newly deployed version of your application’s resources. Support for versioned URLs is built into the framework and can be enabled by configuring a resource chain on the resource handler. The chain consists of one more ResourceResolver instances followed by one or more ResourceTransformer instances. Together they can provide arbitrary resolution and transformation of resources.

The built-in VersionResourceResolver can be configured with different strategies. For example a FixedVersionStrategy can use a property, a date, or other as the version. A ContentVersionStrategy uses an MD5 hash computed from the content of the resource (known as "fingerprinting" URLs).

ContentVersionStrategy is a good default choice to use except in cases where it cannot be used (e.g. with JavaScript module loaders). You can configure different version strategies against different patterns as shown below. Keep in mind also that computing content-based versions is expensive and therefore resource chain caching should be enabled in production.

Java config example;

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public-resources/")
                .resourceChain(true).addResolver(
                    new VersionResourceResolver().addContentVersionStrategy("/**"));
    }
}

XML example:

<mvc:resources mapping="/resources/**" location="/public-resources/">
<mvc:resource-chain>
<mvc:resource-cache />
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>

In order for the above to work the application must also render URLs with versions. The easiest way to do that is to configure the ResourceUrlEncodingFilter which wraps the response and overrides its encodeURL method. This will work in JSPs, FreeMarker, Velocity, and any other view technology that calls the response encodeURL method. Alternatively, an application can also inject and use directly the ResourceUrlProvider bean, which is automatically declared with the MVC Java config and the MVC namespace.

17.16.8 Falling Back On the "Default" Servlet To Serve Resources

This allows for mapping the DispatcherServlet to "/" (thus overriding the mapping of the container’s default Servlet), while still allowing static resource requests to be handled by the container’s default Servlet. It configures a DefaultServletHttpRequestHandler with a URL mapping of "/**" and the lowest priority relative to other URL mappings.

This handler will forward all requests to the default Servlet. Therefore it is important that it remains last in the order of all other URL HandlerMappings. That will be the case if you use <mvc:annotation-driven> or alternatively if you are setting up your own customized HandlerMapping instance be sure to set its order property to a value lower than that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.

To enable the feature using the default setup use:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

Or in XML:

<mvc:default-servlet-handler/>

The caveat to overriding the "/" Servlet mapping is that the RequestDispatcher for the default Servlet must be retrieved by name rather than by path. The DefaultServletHttpRequestHandler will attempt to auto-detect the default Servlet for the container at startup time, using a list of known names for most of the major Servlet containers (including Tomcat, Jetty, GlassFish, JBoss, Resin, WebLogic, and WebSphere). If the default Servlet has been custom configured with a different name, or if a different Servlet container is being used where the default Servlet name is unknown, then the default Servlet’s name must be explicitly provided as in the following example:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable("myCustomDefaultServlet");
    }
}

Or in XML:

<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327055664&siteId=291194637