1. Servlet的service方法与doGet/doPost方法的关系
service方法与doGet/doPost方法都是HttpServlet类的方法
1.service(ServletRequest req, ServletResponse resp)---来自于Servlet接口
2.service(HttpServletRequest req, HttpServletResponse resp)---自己定义的
3.doGet(HttpServletRequest req, HttpServletResponse resp)----自己定义的
4.doPost(HttpServletRequest req, HttpServletResponse resp)----自己定义的
在具体处理请求的时候Servlet容器会默认调用来自于Servlet接口的.service(ServletRequest req, ServletResponse resp)方法来处理请求。HttpServlet类中会在用来自于Servlet接口的.service(ServletRequest req, ServletResponse resp)方法中调用HttpServlet自己定义的service(HttpServletRequest req, HttpServletResponse resp),这是处理请求的时候,HttpServlet自己定义的service(HttpServletRequest req, HttpServletResponse resp)就执行了,此时HttpServlet自己定义的service(HttpServletRequest req, HttpServletResponse resp)方法中用过HttpServletRequest 对象得到请求提交方式,判断请求提交方式调用对应的doGet/doPost方法处理请求。
2. Servlet配置虚拟路径映射
Servlet 的多重映射指同一个 Servlet 可以被映射成多条虚拟路径。也就是说,客户端可以通过多条路径实现对同一个 Servlet 的访问。
Servlet 多重映射的实现方式有以下两种。
2.1 配置多个 <servlet-mapping> 元素
http://localhost:8080/servletweb2/mydemo2
http://localhost:8080/servletweb2/mydemo1
两个地址均可以访问到页面
2.2 配置多个 <url-pattern> 子元素
<!-- 告知服务器有一个Servlet的处理程序-->
<servlet>
<servlet-name>my</servlet-name>
<servlet-class>com.wangxing.testservlet.MyServlet</servlet-class>
</servlet>
<!-- 配置多个<url-pattern> 元素 -->
<servlet-mapping>
<servlet-name>my</servlet-name>
<url-pattern>/mydemo1</url-pattern>
<url-pattern>/mydemo2</url-pattern>
</servlet-mapping>
注意:[有错误提示但不影响程序运行]
2.3 Servlet映射路径中使用通配符
在实际开发过程中,开发者有时会希望某个目录下的所有路径都可以访问同一个 Servlet,这时,可以在 Servlet 映射的路径中使用通配符“*”。
通配符的格式有两种,具体如下。
1.格式为“*.扩展名”,例如 *.my 匹配以 .my 结尾的所有 URL 地址。
<servlet-mapping>
<servlet-name>my</servlet-name>
<url-pattern>*.my</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.test</url-pattern>
</servlet-mapping>
2. 格式为 /*,例如 /abc/* 匹配以 /abc 开始的所有 URL 地址。
<servlet-mapping>
<servlet-name>my</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
注意:需要注意的是,这两种通配符的格式不能混合使用,例如,/abc/*.do 是不合法的映射路径。
另外,当客户端访问一个 Servlet 时,如果请求的 URL 地址能够匹配多条虚拟路径,那么 Tomcat 将采取最具体匹配原则查找与请求 URL 最接近的虚拟映射路径。
例如,对于如下所示的一些映射关系:
/abc/* Servlet1
/* Servlet2
/abc Servlet3
*.do Servlet4
当请求 URL 为 /abc/a.html----/abc/* 和 /* 都可以匹配这个 URL,Tomcat 会调用 Servlet1.
当请求 URL 为 /abc----/*、/abc/* 和 /abc 都可以匹配这个URL,Tomcat 会调用 Servlet3。
当请求 URL 为 /abc/a.do-----/*、*.do 和 /abc/*都可以匹配这个URL,Tomcat 会调用 Servlet1。
当请求 URL 为 /a.do--------/* 和 *.do 都可以匹配这个URL,Tomcat 会调用 Servlet2。
当请求 URL 为 /xxx/yyy/a.do----*.do 和 /* 都可以匹配这个URL,Tomcat 会调用 Servlet2。
3. 默认Servlet
如果某个 Servlet 的映射路径仅仅是一个正斜线(/),那么这个 Servlet 就是当前 Web 应用的默认 Servlet。Servlet 服务器在接收到访问请求时,如果在 web.xml 文件中找不到匹配的 <servlet-mapping> 元素的 URL,则会将访问请求交给默认 Servlet 处理,也就是说,默认 Servlet 用于处理其他 Servlet 都不处理的访问请求。
需要注意的是,在 Tomcat 安装目录下的conf文件夹中 web.xml 文件中也配置了一个默认的 Servlet,配置信息如下所示:
<servlet>
<servlet-name>default</servlet-name>
<serlet-class>org.apache.catalina.servlets.DefaultServlet</serlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在上面的配置信息中,org.apache.catalina.servlets.DefaultServlet 被设置为默认的 Servlet,它对 Tomcat 服务器上所有的 Web 应用都起作用。
当 Tomcat 服务器中的某个 Web 应用没有默认 Servlet 时,都会将 DefaultServlet 作为默认的 Servlet。当客户端访问 Tomcat 服务器中的某个静态 HTML 文件时,DefaultServlet 会判断 HTML 是否存在,如果存在,则会将数据以流的形式回送给客户端,否则会报告 404 错误。
4.servlet处理用户请求的完整流程
针对 Servlet 的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象。其中,HttpServletRequest 对象用于封装 HTTP 请求消息,简称 request 对象。HttpServletResponse 对象用于封装 HTTP 响应消息,简称 response 对象。浏览器访问 Servlet 的交互过程如图所示。
在图中,首先浏览器向 Web 服务器发送了一个 HTTP 请求,Web 服务器根据收到的请求,会先创建一个 HttpServletRequest 和 HttpServletResponse 对象,然后再调用相应的 Servlet 程序。在 Servlet 程序运行时,它首先会从 HttpServletRequest 对象中读取数据信息,然后通过 service() 方法处理请求消息,并将处理后的响应数据写入到 HttpServletResponse 对象中。最后,Web 服务器会从 HttpServletResponse 对象中读取到响应数据,并发送给浏览器。
需要注意的是,在 Web 服务器运行阶段,每个 Servlet 都只会创建一个实例对象,针对每次 HTTP 请求,Web 服务器都会调用所请求 Servlet 实例的 service(HttpServletRequest request,HttpServletResponse response)方法,并重新创建一个 request 对象和一个 response 对象。