设为首页 收藏本站
查看: 730|回复: 0

[经验分享] tomcat和jetty对静态资源的处理和客户端缓存的处理

[复制链接]
累计签到:5 天
连续签到:1 天
发表于 2017-2-9 11:13:59 | 显示全部楼层 |阅读模式
  tomcat和jetty对静态资源的处理和客户端缓存的处理
 
原文链接:http://www.javaarch.net/jiagoushi/867.htm
这两个默认servlet名称都是defaultservlet,然后在web.xml中就可以添加下面的配置让应用支持都静态资源的处理,对应的这些静态资源的目录则是在webapp根目录下,这里其实可以不用配置servlet名称,对于名称为default的url,tomcat和jetty都会作为静态资源文件处理
 

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<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>*.swf</url-pattern>
</servlet-mapping>
  

那么我们来看看tomcat和jetty对静态资源的客户端缓存的处理逻辑:


tomcat,tomcat在default的servlet支持一些参数,如果有需要那么就需要配置servlet了,
 

<servlet>  
<servlet-name>default</servlet-name>  
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>  
<init-param>  
<param-name>debug</param-name>  
<param-value>0</param-value>  
</init-param>  
<init-param>  
<param-name>listings</param-name>  
<param-value>false</param-value>  
</init-param>  
<load-on-startup>1</load-on-startup>  
</servlet>
  
在对于静态资源处理的客户端缓存的代码如下
 

// ETag header
response.setHeader("ETag", cacheEntry.attributes.getETag());
// Last-Modified header
response.setHeader("Last-Modified", cacheEntry.attributes.getLastModifiedHttp());
  
这里的etag计算规则如下:
 

long contentLength = getContentLength();
long lastModified = getLastModified();
if ((contentLength >= 0) || (lastModified >= 0)) {
weakETag = "W/\"" + contentLength + "-" +
lastModified + "\"";
}

  

输出的reponse header如下:
 

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"7482-1371188756000"
Last-Modified: Fri, 14 Jun 2013 05:45:56 GMT
Content-Type: text/css;charset=GBK
Content-Length: 7482
Date: Sun, 16 Jun 2013 07:05:37 GMT
  
第二次请求时,会先对reqeust的etag和last-modified进行比对,如果没更新的话则返回304
 

protected ArrayList<Range> parseRange(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes) throws IOException {
// Checking If-Range
String headerValue = request.getHeader("If-Range");
if (headerValue != null) {
long headerValueTime = (-1L);
try {
headerValueTime = request.getDateHeader("If-Range");
} catch (IllegalArgumentException e) {
// Ignore
}
String eTag = resourceAttributes.getETag();
long lastModified = resourceAttributes.getLastModified();
if (headerValueTime == (-1L)) {
// If the ETag the client gave does not match the entity
// etag, then the entire entity is returned.
if (!eTag.equals(headerValue.trim()))
return FULL;
} else {
// If the timestamp of the entity the client got is older than
// the last modification date of the entity, the entire entity
// is returned.
if (lastModified > (headerValueTime + 1000))
return FULL;
}
}

  
第二次返回:
 

HTTP/1.1 304 Not Modified
Server: Apache-Coyote/1.1
ETag: W/"2640-1371187966000"
Date: Sun, 16 Jun 2013 07:23:27 GMT
  
那么这里对静态资源浏览器就自动能够缓存起来了。当然tomcat和jetty服务器也会对静态资源进行缓存。


jetty对这个处理也差不多,不过jetty对于静态资源的缓存策略可以做更多参数设置,这些参数都是在web.xml配置servlet的时候可以进行设置的。
 

_cacheControl=getInitParameter("cacheControl");
String resourceCache = getInitParameter("resourceCache");
int max_cache_size=getInitInt("maxCacheSize", -2);
int max_cached_file_size=getInitInt("maxCachedFileSize", -2);
int max_cached_files=getInitInt("maxCachedFiles", -2);
if (resourceCache!=null)
{
if (max_cache_size!=-1 || max_cached_file_size!= -2 || max_cached_files!=-2)
LOG.debug("ignoring resource cache configuration, using resourceCache attribute");
if (_relativeResourceBase!=null || _resourceBase!=null)
throw new UnavailableException("resourceCache specified with resource bases");
_cache=(ResourceCache)_servletContext.getAttribute(resourceCache);
LOG.debug("Cache {}={}",resourceCache,_cache);
}
_etags = getInitBoolean("etags",_etags);
  

处理代码:


写header
 

    /* ------------------------------------------------------------ */
protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
throws IOException
{        
if (content.getContentType()!=null && response.getContentType()==null)
response.setContentType(content.getContentType().toString());
if (response instanceof Response)
{
Response r=(Response)response;
HttpFields fields = r.getHttpFields();
if (content.getLastModified()!=null)
fields.put(HttpHeader.LAST_MODIFIED,content.getLastModified());
else if (content.getResource()!=null)
{
long lml=content.getResource().lastModified();
if (lml!=-1)
fields.putDateField(HttpHeader.LAST_MODIFIED,lml);
}
if (count != -1)
r.setLongContentLength(count);
writeOptionHeaders(fields);
if (_etags)
fields.put(HttpHeader.ETAG,content.getETag());
}
else
{
long lml=content.getResource().lastModified();
if (lml>=0)
response.setDateHeader(HttpHeader.LAST_MODIFIED.asString(),lml);
if (count != -1)
{
if (count<Integer.MAX_VALUE)
response.setContentLength((int)count);
else
response.setHeader(HttpHeader.CONTENT_LENGTH.asString(),Long.toString(count));
}
writeOptionHeaders(response);
if (_etags)
response.setHeader(HttpHeader.ETAG.asString(),content.getETag().toString());
}
}

  
判断静态资源是否修改过
 

/* ------------------------------------------------------------ */
/* Check modification date headers.
*/
protected boolean passConditionalHeaders(HttpServletRequest request,HttpServletResponse response, Resource resource, HttpContent content)
throws IOException
{
try
{
if (!HttpMethod.HEAD.is(request.getMethod()))
{
if (_etags)
{
String ifm=request.getHeader(HttpHeader.IF_MATCH.asString());
if (ifm!=null)
{
boolean match=false;
if (content!=null && content.getETag()!=null)
{
QuotedStringTokenizer quoted = new QuotedStringTokenizer(ifm,", ",false,true);
while (!match && quoted.hasMoreTokens())
{
String tag = quoted.nextToken();
if (content.getETag().toString().equals(tag))
match=true;
}
}
if (!match)
{
Response r = Response.getResponse(response);
r.reset(true);
r.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
return false;
}
}
String ifnm=request.getHeader(HttpHeader.IF_NONE_MATCH.asString());
if (ifnm!=null && content!=null && content.getETag()!=null)
{
// Look for GzipFiltered version of etag
if (content.getETag().toString().equals(request.getAttribute("o.e.j.s.GzipFilter.ETag")))
{
Response r = Response.getResponse(response);
r.reset(true);
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
r.getHttpFields().put(HttpHeader.ETAG,ifnm);
return false;
}

// Handle special case of exact match.
if (content.getETag().toString().equals(ifnm))
{
Response r = Response.getResponse(response);
r.reset(true);
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
r.getHttpFields().put(HttpHeader.ETAG,content.getETag());
return false;
}
// Handle list of tags
QuotedStringTokenizer quoted = new QuotedStringTokenizer(ifnm,", ",false,true);
while (quoted.hasMoreTokens())
{
String tag = quoted.nextToken();
if (content.getETag().toString().equals(tag))
{
Response r = Response.getResponse(response);
r.reset(true);
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
r.getHttpFields().put(HttpHeader.ETAG,content.getETag());
return false;
}
}
// If etag requires content to be served, then do not check if-modified-since
return true;
}
}
// Handle if modified since
String ifms=request.getHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
if (ifms!=null)
{
//Get jetty's Response impl
Response r = Response.getResponse(response);
if (content!=null)
{
String mdlm=content.getLastModified();
if (mdlm!=null)
{
if (ifms.equals(mdlm))
{
r.reset(true);
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
r.flushBuffer();
return false;
}
}
}
long ifmsl=request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
if (ifmsl!=-1)
{
if (resource.lastModified()/1000 <= ifmsl/1000)
{
r.reset(true);
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
r.flushBuffer();
return false;
}
}
}
// Parse the if[un]modified dates and compare to resource
long date=request.getDateHeader(HttpHeader.IF_UNMODIFIED_SINCE.asString());
if (date!=-1)
{
if (resource.lastModified()/1000 > date/1000)
{
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
return false;
}
}
}
}
catch(IllegalArgumentException iae)
{
if(!response.isCommitted())
response.sendError(400, iae.getMessage());
throw iae;
}
return true;
}

  
第一次访问的response header头:
 

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"7482-1371188756000"
Last-Modified: Fri, 14 Jun 2013 05:45:56 GMT
Content-Type: text/css;charset=GBK
Content-Length: 7482
Date: Sun, 16 Jun 2013 07:05:37 GMT

第二次访问:

 

HTTP/1.1 304 Not Modified
Server: Jetty(6.1.26)
  


不过处理静态资源大型网站肯定不是tomcat或者jetty,基本都是用apache或者nginx等来处理静态处理,性能更好。这里只是列出tomcat和jetyy对静态资源的处理和客户端缓存的支持。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-339701-1-1.html 上篇帖子: TOMCAT 下中文乱码问题解决集锦/Java/JSP中文乱码问题解决 下篇帖子: tomcat+comet实现终端与服务端同步的小例子
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表