Insight mvc:resources cache-period 解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tt50335971/article/details/52129213

疑问:springmvc 的配置项中<mvc:resources location="/static/" mapping="/static/**" cache-period="86400" />cache-period属性是怎样生效的?

...

Insight spring源码,按照以往的分析,mvc:xxx配置的解析由MvcNamespaceHandler完成。

/**
 * NamespaceHandler for Spring MVC configuration namespace.
 *
 */
public class MvcNamespaceHandler extends NamespaceHandlerSupport {

	public void init() {
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
	}

}
此时注册了mvc:resources 的解析器为ResourcesBeanDefinitionParser。

...

springmvc 对静态资源提供了特定的RequestHandler: ResourceHttpRequestHandler。解析的cache-period做为Handler的cacheSeconds的值。

private String registerResourceHandler(ParserContext parserContext, Element element, Object source) {
    // ...
    RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class);
    // cache-period parse
    String cacheSeconds = element.getAttribute("cache-period");
    if (StringUtils.hasText(cacheSeconds)) {
    	// see WebContentGenerator.setCacheSeconds(int seconds)
    	resourceHandlerDef.getPropertyValues().add("cacheSeconds", cacheSeconds);
    }
    // ...
    return beanName;
}
...

此时,cache-period解析完毕并且赋值给RequestHandler。那么RequestHandler的cacheSeconds作用是什么?

直接看实现,cacheSeconds体现在response 的header中,Tell browser直接用本地缓存吧。

public class ResourceHttpRequestHandler extends WebContentGenerator implements HttpRequestHandler, InitializingBean {

    /**
     * Processes a resource request.
     */
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) {
        // Checks for supported methods and a required session, and applies the number of cache seconds.
        checkAndPrepare(request, response, true);
        // check whether a matching resource exists
        Resource resource = getResource(request);
        // check the resource's media type
        MediaType mediaType = getMediaType(resource);
        // header phase
        setHeaders(response, resource, mediaType);
        // content phase
        writeContent(response, resource);
    }
    
    /**
     * Apply the given cache seconds and generate respective HTTP headers.
     * That is, allow caching for the given number of seconds in the
     * case of a positive value, prevent caching if given a 0 value, else
     * do nothing (i.e. leave caching to the client).
     */
    protected final void applyCacheSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate) {
        if (seconds > 0) {
            // 我们的cacheSeconds是86400
            cacheForSeconds(response, seconds, mustRevalidate);
        }
        else if (seconds == 0) {
        	preventCaching(response);
        }
        // Leave caching to the client otherwise.
    }
    
    /**
     * Set HTTP headers to allow caching for the given number of seconds.
     * Tells the browser to revalidate the resource if mustRevalidate is True.
     */
    protected final void cacheForSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate) {
        if (this.useCacheControlHeader) {
            // HTTP 1.1 header
            String headerValue = "max-age=" + seconds;
            if (mustRevalidate || this.alwaysMustRevalidate) {
            	headerValue += ", must-revalidate";
            }
            response.setHeader(HEADER_CACHE_CONTROL, headerValue);
        }
    }
	
}


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页