服务器在接收到浏览器的请求后,会自动调用对应的逻辑代码进行请求处理。但是逻辑代码是由程序员编写并放到服务器中,那么服务器怎么知道该怎么调用并调用哪个类和哪个方法来进行请求处理?
程序员在编写代码的时候如果能够按照服务器能够识别的规则进行编写, 浏览器按照指定的规则进行发送请求,那么服务器就可以调用并执行响应的逻辑代码进行请求处理了。
1 Servlet 技术
狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指任何实现了这个 Servlet 接口的类,一般情况下,人们将 Servlet 理解为后者。Servlet 运行于支持 Java 的应用服务器中。从原理上讲,Servlet 可以响应任何类型的请求,但绝大多数情况下 Servlet 只用来扩展基于 HTTP 协议的 Web 服务器。
1.1 特点
- 运行在支持 java 的应用服务器上
- Servlet 的实现遵循了服务器能够识别的规则,也就是服务器会自动的根据请求调用对应的servlet 进行请求处理。
- 简单方便,可移植性强
1.2 使用
- 创建普通的 java 类并继承 HttpServlet
- 覆写 service 方法
- 在 service 方法中书写逻辑代码即可
1.3 URL 组成
服务器地址:端口号/虚拟项目名 /servlet注解的路径(配置的路径)
URI:虚拟项目名 /servlet 的别名
浏览器发送请求到服务器,服务器根据请求 URL 地址中的 URI 信息在 webapps 目录下找到对应的项目文件夹,然后在 web.xml 中检索对应的 Servlet,找到后调用并执行 Servlet。
- DoGet 方法用于 GET 请求
- DoPost 方法用于 POST 请求
2 Servlet 路径配置
通过对 Servlet 的调用流程学习,我们知道 web.xml 文件的配置是为了保护servlet。其实服务器应该调用哪个 servlet 进行请求的处理, 在浏览器的请求地址中写的很清楚。
2.1 注解配置
通过修改 Servlet 类上的注解,配置访问路径
- 精确匹配,一般作用于站点独特的几个路径,首页、登录、注册等等
java @WebServlet("/hello")
- 路径匹配,一般用于产品页,新闻页面,百科页面一般用于大量相类似的页面
java @WebServlet("/product/*")
- 扩展名匹配
java @WebServlet("*.json")
- 匹配多个路径
java @WebServlet(urlPatterns= {"/morepath","*.do","/more/*"})
2.2 web.xml 配置
web.xml 配置的作用是保护 Servlet。web.xml 位于 WebContent/WEB-INF/ 下。
- 配置方式一: 精确匹配
my3 MyServlet3 my3 /my3
配置方式二: 路径匹配
my3 MyServlet3 my3 /news/*
配置方式三: 扩展名匹配
my3 MyServlet3 my3 *.do
一个 Servlet 可有拥有多个 url-pattern 配置,但是一个 url-pattern 配置只能对应一个 servlet。 路径和扩展名匹配无法同时设置,比如 <url-pattern>/kata/*.jsp</url-pattern>
是非法的,如果设置,启动tomcat服务器会报错。
2.3 加载时机
服务器启动的时候会将 webapps 中部署好的项目统一进行加载,并完成对每个项目的 web.xml 文件的加载。
当一个 url 与多个 servlet 的匹配规则可以匹配时,则按照 "精确路径 > 最长路径>扩展名" 这样的优先级匹配到对应的servlet。
3 Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
最后,servlet 是由 JVM 的垃圾回收器进行垃圾回收的。接着让我们详细讨论生命周期的方法。
3.1 init() 方法
init() 方法被设计成只调用一次。它在第一次创建 servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
servlet 创建于用户第一次调用对应于该 servlet 的 URL 时,但是您也可以指定 servlet 在服务器第一次启动时被加载。
当用户调用一个 servlet 时,就会创建一个 servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 servlet 的整个生命周期。
1 public void init() throws ServletException {2 // 初始化代码...3 }
3.2 service() 方法
service() 方法是执行实际任务的主要方法。servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
1 public void service(ServletRequest request, 2 ServletResponse response) 3 throws ServletException, IOException{4 5 }
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
3.3 doGet()
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
1 public void doGet(HttpServletRequest request,2 HttpServletResponse response)3 throws ServletException, IOException {4 // Servlet 代码5 }
3.4 doPost()
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
1 public void doPost(HttpServletRequest request,2 HttpServletResponse response)3 throws ServletException, IOException {4 // Servlet 代码5 }
3.5 destroy() 方法
destroy() 方法只会被调用一次,在 servlet 生命周期结束时被调用。destroy() 方法可以让您的 servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:
1 public void destroy() {2 // 终止化代码...3 }
3.6 构架图
下图显示了一个典型的 servlet 生命周期方案。
第一个到达服务器的 HTTP 请求被委派到 servlet 容器。servlet 容器在调用 service() 方法之前加载 servlet。然后 servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 servlet 实例的 service() 方法。