Tomcat 有两个默认的 Servlet,你的 Web 项目会『无意中』用到它们。JSPServlet 和 DefaultServlet 。
JSPServlet 用于响应 .jsp
请求;DefaultServlet 则是默认的『兜底』的 Servlet 。
其实 JSPServlet 并非一个,应该是整个项目有多少个 JSP 页面,就会有对应的多少个 JSPServlet 。
JSPServlet 的工作大家都很清楚了,它涉及到 .jsp
文件的工作原理。
当你第一次访问一个 .jsp
页面时,Tomcat 会根据你的 jsp 页面『帮』你写一个 Servlet,即此处的 JSPServlet 。
访问 jsp 页面最终触发的是这个 Servlet 的执行。在这个 Servlet 中会生成一个页面的内容(html格式字符串),并发回给客户端浏览器。
DefaultServlet 是 Tomcat 提供的默认的『兜底』的 Servlet,相当于它的
配置的是 /
。
DefaultServlet 中的 doPost 方法交由 doGet 方法进行处理。而 doGet 方法兜兜转转最后执行了一个 copy 方法,在 copy 方法中把找到静态资源文件,将其内容读出并写入 Response 对象的输出流,这样你的浏览器就看到静态数据了。
结合我们自定义的 Servlet,和 JSPServlet、DefaultServlet,会让初学者造成一些不知所以的 bug :
将 HelloServlet 的 urlpattern 配置为 *.do
,此时项目中的各个 Servlet 的分工如下:
Tomcat 默认的 JSPServlet 负责响应 .jsp
请求。
我们自己的 HelloServlet 负责响应 .do
请求。
凡是没有 Servlet 响应的请求,都被『漏给』DefaultServlet 处理。
将 HelloServlet 的 urlpattern 配置为 /
,此时项目中的各个 Servlet 的分工如下:
Tomcat 默认 JSPServlet 负责响应 .jsp
请求。
HelloServlet 负责响应所有的其它请求。
注意,你的 HelloServlet 就替代了 Tomcat 默认的 DefaultServlet 在做「兜底」的工作。
此时,你就无法访问静态资源!
除非你的 HelloServlet 实现了 Tomcat 的 DefaultServlet 同样的功能。
将 HelloServlet 的 urlpattern 配置为 /*
,此时项目中的各个 Servlet 的分工如下:
所有的请求都由你的 HelloServlet 处理。
/*
是路径匹配,它的优先级高于 .jsp
。所以当用户输入 xxx.jsp
时,是 HelloServlet『先』响应了这个请求,轮不到 Tomcat 的 JSPServlet 来响应这个 .jsp
请求。
此时,在静态资源无法访问的基础上,jsp 也无法访问了。
逻辑上,用户所访问的资源分为 3 种:
Servlet
JSP
静态资源(例如:html、css、js、png 等)
Tomcat 判断请求的资源的类型,也是按照上述顺序在判断:先判断是否是请求 Servlet(.do
请求),再判断是否是 JSP(.jsp
请求)。要是都不是,那么就是静态资源(.png
等请求)。
通过配置,进行合理安排,我们应该/预期达到如下效果:
对于 Servlet 的请求的处理,由我们自定义的 Servlet
进行处理。
对于 JSP 的请求的处理,由 Tomcat 中的 JspServlet
自动处理。
对于 静态资源 的处理,由 Tomcat 中的 DefaultServlet
自动处理。
[!attention] 注意
从本质上来讲,DefaultServlet 并不是『专门』处理静态资源的工具。而是说,既不是由我们自定义的 Servlet 处理的资源,又不是由 JspServlet 处理的资源,最后统统都交由 DefaultServlet 处理。
DefaultServlet 作为『兜底』的 Servlet ,它的 url-pattern 是 /
,注意,并非 /*
。
毫无疑问,web.xml
中 不需要 显示地配置 DefaultServlet(否则,它也就不会叫 Default Servlet 了)。
同样的道理,其实我们也从未在(也不需要在) web.xml
中显示地配置过 JspServlet 。
当要访问静态资源时,可以在 web.xml
中明确指定什么样的请求(即对静态资源的请求)交由 DefaultServlet 进行处理(逻辑上,以下配置也可以省略不写,默认既是如此):
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.htmlurl-pattern>
<url-pattern>*.cssurl-pattern>
<url-pattern>*.jsurl-pattern>
<url-pattern>*.jpgurl-pattern>
<url-pattern>*.pngurl-pattern>
servlet-mapping>
注意
WEB-INF
目录下内容不允许直接公共访问,所以静态资源通常是放到与WEB-INF
同级的目录下面。- 如果是 SpringMVC 项目,对于静态资源的访问有其他的操作。