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

首先所有的请求进入tomcat,都会流经servlet,如果没有匹配到任何应用指定的servlet,那么就会流到默认的servlet。
默认的servlet是配置在$catalina/conf/web.xml里面的。
tomcat初始化一个context的时候就会初始化context下面所有的 servlet,包括默认的servlet

 
    default  
    org.apache.catalina.servlets.DefaultServlet  
     
        debug  
        0  
   
 
     
        listings  
        false  
   

    1  
 
 
 
    jsp  
    org.apache.jasper.servlet.JspServlet  
     
        fork  
        false  
   
 
     
        xpoweredBy  
        false  
   
 
    3  



    default
    /

 
    jsp  
    *.jsp  
 

 
    jsp  
    *.jspx  


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"


配置以后是这样的:
               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:

    ImageServlet
    com.camps.images.ImageServlet


    ImageServlet
    *.gif


    ImageServlet
    *.png



    ImageFilter
    com.camps.images.ImageFilter


    ImageFilter
    *.bmp


    ImageFilter
    *.jpg


html:

    test
    

    test
    

    test
    

    test
    

    test
    

    test


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

}

你可能感兴趣的:(技术)