首先所有的请求进入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:
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 {}
}