分析DispatcherServlet拦截"/"造成静态文件404
来源:互联网 发布:返利平台源码 编辑:程序博客网 时间:2024/05/20 20:43
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
这里以html为例,如果需要多种静态资源类型,就需要配置多个以上。
为什么配置这个就能访问了呢?default是哪个servlet?为什么要使用这个servlet处理静态资源?我的脑海中产生这样一系列的问题。
总的来说,是因为配置了spring MVC的DispatcherServlet拦截“/”,为了实现REST风格,拦截了所有的请求,同时,静态文件也被拦截。 所以激活Tomcat的defaultServlet来处理静态文件。
我们接着刚刚的疑问继续探究。
先在项目里面找了default,没有找到。很好,百度吧!百度说这是他tomcat默认的serlvet,那这个servlet是干什么用的呢?我们已经知道它的一个用处了,就是处理静态资源。从这个网址可以看到官方文档里面对DefaultServlet的解释。http://tomcat.apache.org/tomcat-7.0-doc/default-servlet.html#what
1. What is the DefaultServlet?
DefaultServlet是用来处理静态资源,就像处理目录列表一样。
2. Where is it declared?
DefaultServlet是在$CATALINA_BASE/conf/web.xml里面做全局声明的,默认情况下是这样子的
<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>... <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>所以通常情况下,DefaultServlet是在web项目启动时加载的,同时debug调试和文件目录都是禁用的。这里的listings是指文件目录,可是文件目录又是什么呢?别着急,我们继续往下看。
3. What can I change?
DefaultServlet允许下面这些初始化参数
- debug 这个参数对tomcat的开发者用处比较大,对我们而言用处不大。可选的值有0,1,11,1000.[0]
- listings 如果没有设置欢迎页,那么当我们访问项目名时,会显示文件目录吗?这个参数的值是true或者false.[false].(这里我把值设置成了true,并且删除了欢迎文件,访问项目时,显示了文件目录可以对比我的项目目录) 欢迎文件也是servlet api的一部分。警告:包含很多实体的文件目录是非常珍贵的。大量的对大文件列表的请求,十分消耗服务器资源。
- readmeFile 如果设置了显示文件列表,readme文件可能也会显示在列表里面。这个文件是插入的,它可能包含html.
- globalXsltFile 如果你想定制你的文件目录,你可以使用XSL来转换。这个的值也是一个相对文件的名称($CATALINA_BASE/conf/ or $CATALINA_HOME/conf/),这个将会给所有的文件目录使用。但是这个可以被每一个context或者directory覆盖。具体的请看下面的contextXsltFile和localXsltFile.
- contextXsltFile 你可以通过配置contextXsltFile来定制你的文件目录。但是一定要使用上下文的相对路径,并且是一.xsl或者.xslt为扩展名的文件(例如:/path/to/context.xslt)。这个会覆盖globalXsltFile的值. 如果配置的文件路径不存在,仍然会使用globalXsltFile的配置。如果默认的globalXsltFile文件也不存在,那会直接显示文件目录。
- localXsltFile 你同样可以通过配置localXsltFile来定制你的文件目录。它一定是以.xsl或.xslt为扩展名的在目录列表里面的文件。并且这个配置能覆盖globalXsltFile和contextXsltFile的配置。如果配置的这个值找不到对应文件,就会使用contextXsltFile的配置,如果contextXsltFile也找不到,就会使用globalXsltFile的配置,如果都找不到,那么就会展示默认的文件目录。
- input 当读取资源文件时,服务器写入缓冲区的大小,单位为bytes.[2048]
- output 当写入资源文件时,服务器输出缓冲区大小,单位为bytes.[2048]
- readonly 上下文是否是只读的,HTTP的命令,像PUT,DELETE这些是不是被拒绝的。[true]
- fileEncoding 读取静态资源时的文件编码。[platform default]
- sendfileSize 如果使用的连接器支持sendfile,这意味着以KB大小的小文件将会被使用。通常使用负数来禁止sendfile.[48]
- useAcceptRanges 如果设置为true,当响应时请求头的Accept-Ranges将会被设置。[true]
- showServerInfo 当展示文件列表是,服务器信息是否在响应时一起发送给客户端。[true]
<listing> <entries> <entry type='file|dir' urlPath='aPath' size='###' date='gmt date'> fileName1 </entry> <entry type='file|dir' urlPath='aPath' size='###' date='gmt date'> fileName2 </entry> ... </entries> <readme></readme> </listing>
- 如果设置type='dir',就不用设置size
- Readme是一个CDATA,不由xml解析器解析
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:output method="html" html-version="5.0" encoding="UTF-8" indent="no" doctype-system="about:legacy-compat"/> <xsl:template match="listing"> <html> <head> <title> Sample Directory Listing For <xsl:value-of select="@directory"/> </title> <style> h1 {color : white;background-color : #0086b2;} h3 {color : white;background-color : #0086b2;} body {font-family : sans-serif,Arial,Tahoma; color : black;background-color : white;} b {color : white;background-color : #0086b2;} a {color : black;} HR{color : #0086b2;} table td { padding: 5px; } </style> </head> <body> <h1>Sample Directory Listing For <xsl:value-of select="@directory"/> </h1> <hr style="height: 1px;" /> <table style="width: 100%;"> <tr> <th style="text-align: left;">Filename</th> <th style="text-align: center;">Size</th> <th style="text-align: right;">Last Modified</th> </tr> <xsl:apply-templates select="entries"/> </table> <xsl:apply-templates select="readme"/> <hr style="height: 1px;" /> <h3>Apache Tomcat/8.0</h3> </body> </html> </xsl:template> <xsl:template match="entries"> <xsl:apply-templates select="entry"/> </xsl:template> <xsl:template match="readme"> <hr style="height: 1px;" /> <pre><xsl:apply-templates/></pre> </xsl:template> <xsl:template match="entry"> <tr> <td style="text-align: left;"> <xsl:variable name="urlPath" select="@urlPath"/> <a href="{$urlPath}"> <pre><xsl:apply-templates/></pre> </a> </td> <td style="text-align: right;"> <pre><xsl:value-of select="@size"/></pre> </td> <td style="text-align: right;"> <pre><xsl:value-of select="@date"/></pre> </td> </tr> </xsl:template></xsl:stylesheet>
我们可以看到DefaultServlet继承了HttpServlet,刚刚那些参数都是DefaultServlet里面的属性,并且在构造器里面设置了默认值。
/* */ private static final long serialVersionUID = 1L;/* */ private static final DocumentBuilderFactory factory;/* */ private static final SecureEntityResolver secureEntityResolver;/* */ protected int debug;/* */ protected int input;/* */ protected boolean listings;/* */ protected boolean readOnly;/* */ protected int output;/* */ protected static final URLEncoder urlEncoder;/* */ protected String localXsltFile;/* */ protected String contextXsltFile;/* */ protected String globalXsltFile;/* */ protected String readmeFile;/* */ protected transient ProxyDirContext resources;/* */ protected String fileEncoding;/* */ protected int sendfileSize;/* */ protected boolean useAcceptRanges;/* 227 */ protected static final ArrayList<Range> FULL = new ArrayList();/* */ protected boolean showServerInfo;/* */ protected static final String mimeSeparation = "CATALINA_MIME_BOUNDARY";/* */ protected static final String RESOURCES_JNDI_NAME = "java:/comp/Resources";/* */ protected static final StringManager sm;/* */ protected static final int BUFFER_SIZE = 4096;/* *//* */ public DefaultServlet()/* */ {/* 144 */ this.debug = 0;/* *//* 150 */ this.input = 2048;/* *//* 156 */ this.listings = false;/* *//* 162 */ this.readOnly = true;/* *//* 168 */ this.output = 2048;/* *//* 180 */ this.localXsltFile = null;/* *//* 186 */ this.contextXsltFile = null;/* *//* 192 */ this.globalXsltFile = null;/* *//* 198 */ this.readmeFile = null;/* *//* 204 */ this.resources = null;/* *//* 211 */ this.fileEncoding = null;/* *//* 217 */ this.sendfileSize = 49152;/* *//* 222 */ this.useAcceptRanges = true;/* *//* 232 */ this.showServerInfo = true;/* */ }接着就是destroy()和init()方法。init()在服务器启动时执行,destroy()方法在服务器停止时执行。在init()方法里面,我们可以看到它是去读取配置文件的这些属性值,并赋值。
/* */ public void init()/* */ throws ServletException/* */ {/* 305 */ if (getServletConfig().getInitParameter("debug") != null) {/* 306 */ this.debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));/* */ }/* 308 */ if (getServletConfig().getInitParameter("input") != null) {/* 309 */ this.input = Integer.parseInt(getServletConfig().getInitParameter("input"));/* */ }/* 311 */ if (getServletConfig().getInitParameter("output") != null) {/* 312 */ this.output = Integer.parseInt(getServletConfig().getInitParameter("output"));/* */ }/* 314 */ this.listings = Boolean.parseBoolean(getServletConfig().getInitParameter("listings"));/* *//* 316 */ if (getServletConfig().getInitParameter("readonly") != null) {/* 317 */ this.readOnly = Boolean.parseBoolean(getServletConfig().getInitParameter("readonly"));/* */ }/* 319 */ if (getServletConfig().getInitParameter("sendfileSize") != null) {/* 320 */ this.sendfileSize = (Integer.parseInt(getServletConfig().getInitParameter("sendfileSize"))* 1024);/* */ }/* *//* 323 */ this.fileEncoding = getServletConfig().getInitParameter("fileEncoding");/* *//* 325 */ this.globalXsltFile = getServletConfig().getInitParameter("globalXsltFile");/* 326 */ this.contextXsltFile = getServletConfig().getInitParameter("contextXsltFile");/* 327 */ this.localXsltFile = getServletConfig().getInitParameter("localXsltFile");/* 328 */ this.readmeFile = getServletConfig().getInitParameter("readmeFile");/* *//* 330 */ if (getServletConfig().getInitParameter("useAcceptRanges") != null) {/* 331 */ this.useAcceptRanges = Boolean.parseBoolean(getServletConfig().getInitParameter("useAcceptRanges"));/* */ }/* *//* 334 */ if (this.input < 256)/* 335 */ this.input = 256;/* 336 */ if (this.output < 256) {/* 337 */ this.output = 256;/* */ }/* 339 */ if (this.debug > 0) {/* 340 */ log(new StringBuilder().append("DefaultServlet.init: input buffer size=").append(this.input).append(", output buffer size=").append(this.output).toString());/* */ }/* *//* 345 */ this.resources = ((ProxyDirContext) getServletContext().getAttribute("org.apache.catalina.resources"));/* *//* 347 */ if (this.resources == null) {/* */ try {/* 349 */ this.resources = ((ProxyDirContext) new InitialContext().lookup("java:/comp/Resources"));/* */ }/* */ catch (NamingException e)/* */ {/* 354 */ throw new ServletException("No resources", e);/* */ }/* */ }/* *//* 358 */ if (this.resources == null) {/* 359 */ throw new UnavailableException("No resources");/* */ }/* *//* 362 */ if (getServletConfig().getInitParameter("showServerInfo") != null)/* 363 */ this.showServerInfo = Boolean.parseBoolean(getServletConfig().getInitParameter("showServerInfo"));/* */ }我猜测getServletConfig().getInitParameter("debug")这两个方法就是读取在web.xml里面配置的default的参数的值的。
那么文件拦截后,交到doGet(),doPost方法处理。我们来看下。。在doGet()里面调用了serveResource(request, response, true)方法。我看了一下这个方法,不是所有的代码都能看懂,但是大致就是获取请求地址,然后处理跳转响应页面。和我们普通的servlet差不多。
最后就是要把这个default的servlet配置到springMVC跳转器的前面,这样请求就会走DefaultServlet了。
以上便是我的理解,欢迎指教!!
- 分析DispatcherServlet拦截"/"造成静态文件404
- 6. web.xml中DispatcherServlet排除静态资源的拦截
- spring 静态文件拦截问题
- spingMVC静态文件拦截问题
- 解决Spring MVC DispatcherServlet拦截“/”时,无法访问静态资源的问题
- SpringMVC在web.xml中配置DispatcherServlet拦截了静态资源访问
- SpringMVC拦截器-------拦截静态文件的问题
- Spring MVC静态资源拦截(No mapping found for HTTP request with URI in DispatcherServlet with name ' ')问题
- web.xml中DispatcherServlet排除静态资源的拦截 / 图片上传到了WEB-INF目录下,应该如何显示?
- 【Spring】DispatcherServlet源码分析
- 【Spring】DispatcherServlet源码分析
- 【Spring】DispatcherServlet源码分析
- springmvc配置DispatcherServlet拦截url注意事项
- springmvc DispatcherServlet和拦截器详解
- Spring MVC拦截器DispatcherServlet详解
- spring boot 修改DispatcherServlet默认拦截路径
- SpringMVC DispatcherServlet重写、自定义拦截器拦截器(一)
- SpringMVC DispatcherServlet重写、自定义拦截器拦截器(二)
- Paramiko的艰难安装之路(所有雷都蹚了一边)
- UVA10305 Ordering Tasks(拓扑排序)
- HDU 2859 Phalanx(二维dp)
- 【编程思想】自顶向下 逐步求精
- 用PHP程序来查询数据库内容并以表格的形式输出
- 分析DispatcherServlet拦截"/"造成静态文件404
- hdu 1178
- hashMap工作原理和hash碰撞
- 指针与引用的区别
- Luogu P2687 [NOIp提高组2015]跳石头
- Python的序列(1)-列表
- 看视频可以倍速播放的(主流播放器都可以)
- 设置CC2540 TX Power
- spring cache 中guava CacheBuilder的个性实例化