Tomcat 静态资源处理(图片==)

首先所有的请求进入tomcat,都会流经servlet,如果没有匹配到任何应用指定的servlet,那么就会流到默认的servlet。
默认的servlet是配置在$catalina/conf/web.xml里面的。
tomcat初始化一个context的时候就会初始化context下面所有的 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><!--listings:如果没有welcome file的话,directory listing是否显示 可能的值true,false -->
    <load-on-startup>1</load-on-startup>  
</servlet>  
 
<servlet>  
    <servlet-name>jsp</servlet-name>  
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>  
    <init-param>  
        <param-name>fork</param-name>  
        <param-value>false</param-value>  
    </init-param>  
    <init-param>  
        <param-name>xpoweredBy</param-name>  
        <param-value>false</param-value>  
    </init-param>  
    <load-on-startup>3</load-on-startup>  
</servlet>

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>  
    <servlet-name>jsp</servlet-name>  
    <url-pattern>*.jsp</url-pattern>  
</servlet-mapping>  

<servlet-mapping>  
    <servlet-name>jsp</servlet-name>  
    <url-pattern>*.jspx</url-pattern>  
</servlet-mapping>

1.Tomcat如何处理静态资源?处理静态资源很简单,只需根据URI定位到文件,然后读取文件,写到response的 outputstream中去,但tomcat是如何处理,是不是通过servlet container统一处理,还有另有其他方式?最终我发现是由DefaultServlet来处理。
2.APR/NIO Connecter不仅能提高吞吐量,而且使用sendFile使用内核IO,而不是java通过封装以后的IO提高对静态文件的处理。
3.是不是所有的文件都交给sendFile来处理呢?不是,在DefaultServlet中有一个sendFileSize,默认为48k,也就是说只有48k以上的文件才能通过sendFile方式来处理。
4.如有修改DefaultServlt的默认参数,只在web.xml中重新配置DefaultServlet,并修改 initParameter。
5.Tomcat代码研究:Tomcat对静态资源提供缓存提高了性能
try {  
   response.setBufferSize(output);  
} catch (IllegalStateException e) {  
   // Silent catch  
}  
if (ostream != null) {  
   //是否满足使用sendFile的条件,如满足则使用  
   if (!checkSendfile(request, response, cacheEntry, contentLength, null))  
      //不满足,则copy文件到response中的outputStream中
       copy(cacheEntry, renderResult, ostream);  
} else {  
   copy(cacheEntry, renderResult, writer);  
}
tomcat的三种connector中只有NIO和APR模式支持sendFile。sendFile避免用户态和内核之间的四次copy,直接在内核态将文件流写入tcp栈。tomcat自己定了一个界限是48k,他认为48k一下的文件通过缓存的方式性能会比较好。

(用户态/内核态 http://www.cnblogs.com/bakari/p/5520860.html   http://www.cnblogs.com/zemliu/p/3695503.html )


Tomcat在处理静态资源上面有一定的能力缺陷,所以通常我们会通过Apache与Tomcat集成,让Apache处理所有的静态内容来进行优化。但其实,我们可以直接使用tomcat的本地connector来解决这个问题。APR(Apache portable Run-time libraries,Apache可移植运行库)是Apache提供的一组通用的JNI接口,通过本地化的方法来提高应用与系统的交互,比如磁盘io,网络io等。主要提高web容器(Tomcat,Jboss等)对静态文件的处理性能,同时也可以提升SSL的处理性能。
APR 是用 C/C++写的,对静态资源(HTML,图片等)进行了优化。

tomcat下的静态资源文件压缩
在server.xml的connector里面配置以下信息 compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"   compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/jpeg,image/gif"


配置以后是这样的:
<Connector port="8088" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on"
               compressionMinSize="2048"
               noCompressionUserAgents="gozilla, traviata"
               compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/jpeg,image/gif"/>

自定义替换Tomcat 处理图片
Web.xml:
<servlet>
    <servlet-name>ImageServlet</servlet-name>
    <servlet-class>com.camps.images.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ImageServlet</servlet-name>
    <url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>ImageServlet</servlet-name>
    <url-pattern>*.png</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>ImageFilter</filter-name>
    <filter-class>com.camps.images.ImageFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ImageFilter</filter-name>
    <url-pattern>*.bmp</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>ImageFilter</filter-name>
    <url-pattern>*.jpg</url-pattern>
</filter-mapping>

html:
<body>
    <img alt="test" src="/imagex/images/bluearrow.gif">
    <br>
    <img alt="test" src="/imagex/images/bluearrow.gif?size=10_10">
    <br>
    <img alt="test" src="/imagex/images/blue-arrow-down.png?size=10_10">
    <br>
    <img alt="test" src="/imagex/images/bmp.bmp">
    <br>
    <img alt="test" src="/imagex/images/jpg.jpg">
    <br>
    <img alt="test" src="/imagex/images/jpg.jpg?size=10_10">
</body>

Class:
public class ImageServlet extends HttpServlet{
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        BufferedInputStream in = null;
        try{
            String path = req.getServletPath();
            String size = req.getParameter("size"); // 10_10
            String rp = super.getServletConfig().getServletContext().getRealPath("/");
            File file = null;
            if("10_10".equals(size)){
                file = new File(rp + "/images/bg-message.gif");
            }else{
                file = new File(rp + path);
            }
            in = new BufferedInputStream(new FileInputStream(file));
            byte[] bts = new byte[1024];
            while(in.read(bts) != -1){
                resp.getOutputStream().write(bts);
            }
            resp.getOutputStream().flush();
        }finally{
            if(in != null)
                in.close();
        }
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        doGet(req, resp);
    }
}

public class ImageFilter implements Filter{
    public void destroy() {}

    public void doFilter(ServletRequest req1, ServletResponse resp,FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) req1;
        BufferedInputStream in = null;
        try{
            String path = req.getServletPath();
            String size = req.getParameter("size"); // 10_10
            String rp = req.getSession().getServletContext().getRealPath("/");
            File file = new File(rp + path);
            if("10_10".equals(size)){
                file = new File(rp + "/images/bg-message.gif");
            }else{
                file = new File(rp + path);
            }
            in = new BufferedInputStream(new FileInputStream(file));
            byte[] bts = new byte[1024];
            while(in.read(bts) != -1){
                resp.getOutputStream().write(bts);
            }
            resp.getOutputStream().flush();
        }finally{
            if(in != null)
                in.close();
        }
    }

    public void init(FilterConfig arg0) throws ServletException {}

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值