首先所有的请求进入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一下的文件通过缓存的方式性能会比较好。
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 {}
}
默认的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 )
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 {}
}