参考资料
前言
本人菜鸟,入IT只为当鼓励师。本编文章对 Servlet 作简要介绍,其中包括讲解:Servlet是什么、Servlet的功能、Servlet的生命周期、HttpServlet对象。
一、Servlet是什么
- 一门用于开发动态web资源的技术,由sun公司提供。
- java类编写的服务端应用程序
- Servlet程序是由web服务器(tomcat等)调用的
说简单点,就是Sun公司开发出了一套API(java.servlet
、java.sevlet.http
等),你可以用这些api开发Java程序,用来处理客户端请求,并控制输出的响应(向客户端浏览器输出的内容)。
总结起来,你只需要:
① 编写一个实现了servlet接口的java类;
② 把开发好的Java类部署到web服务器中。
所以,有时我们也称实现了servlet接口的java程序为Servlet。
二、Servlet的功能
- 对客户端发送的数据进行读取和拦截
客户端发送一个请求会携带数据(url中的参数,页面表单提交,ajax请求),当一个Servlet接收到请求,java Servlet中的类可以通过提供的方法获得这些参数(request.getParameterName(name)
等)。因此Servlet可以起拦截作用,在请求前先判断该客户端能否做出这些请求 ,若能再从服务器得到请求的资源。
读取客户端的请求的隐含数据
客户端请求的数据可分为:隐含数据,显式数据。
隐含数据:不存在于URL中,而存在于请求的来源,缓存数据(cookie)、客户端类型(在header中)。
显式数据:用户可见的,表单数据(来自于form)或URL参数。
Servlet都可处理。-
运行结果或者生成结果
一个Web应用程序对客户端发出的请求做出响应时,一般有很多中间过程才能得到结果,Servlet就担起了这个中间角色功能。(后面深入学习会知道,javaweb开发中的控制层是由Servlet实现的,就是常说的MVC中的C)
发送响应的数据
Servlet对客户端做出响应并经过处理得出结果后,会对客户端发送响应的数据,让客户端获取请求的结果数据。
三、Servlet的生命周期
Servlet的生命周期包含3个阶段:
1. 初始化阶段
当web服务器收到客户端对某一url地址的访问请求时,若该url配置了对应的Servlet程序,则开始该阶段。
- web服务器检查是否已经装载并创建了该Servlet的实例对象。如果是,则跳过初始化阶段,否则进入下一步。
- 装载(由Servlet容器装载一个Servlet类,把它装在到Java内存中)并创建该Servlet的一个实例对象,与
web.xml
中的配置对应起来。 - 调用Servlet实例对象的
init()
方法。在整个Servlet生命周期中,init()
方法只被调用一次。
2. 运行阶段
该阶段实际响应客户端的请求。
- Servlet创建
HttpServletRequest
和HttpServletResponse
对象,前者与HTTP协议有关,后者与协议无关。 - 调用
service(HttpServletRequest request, HttpServletResponse response)
方法,该方法通过request对象获得请求对象的信息并加以处理,再由response对象给客户端做出响应。
3. 消亡阶段
- web应用程序被停止或重新启动之前,Servlet容器将调用
destroy()
方法,对Servlet对象进行销毁,释放其所占资源。在整个Servlet生命周期中,destory()
方法只被调用一次。
四、创建Servlet的步骤
- 引入相应的包,如:
java.servlet
或java.servlet.http
包,两个包的区别是前者与协议无关,后者与HTTP协议相关。 - 创建一个扩展类,如本例中的 HelloServlet,并继承
HttpServlet
类。(一般的,HttpServlet
类封装了很多基于HTTP协议下的Servlet功能,基本够用,若自己想开发一个协议可继承GenericServlet
类) - override
doGet()
或doPost()
方法,doGet()
响应get请求,doPost()
响应Post请求。或者可以overrideservice()
方法,对所有请求统一处理。欲详细了解service()
,doGet()
,doPost()
等方法,请看:五、关于 Servlet、HttpServlet、GenericServlet。
代码示例:
package com.javaweb.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/* 用注入声明的方式表示这是一个 Servlet 类,不用在web.xml中配置 Servlet */
@WebServlet (
urlPatterns = { "/HelloServlet" },
name = " helloServlet "
)
// 继承HttpServlet类
public class HelloServlet extends HttpServlet {
// 序列化,可以自动生成或者自行定义
private static final long serialVersionUID = 1L;
// 一、初始化阶段的 init() 方法
public void init() throws ServletException {
System.out.println("初始化 init 方法");
}
// 过程二执行的方法有一定的顺序与条件,详细请看: 五、关于 Servlet、HttpServlet、GenericServlet
// 二、调用 public service 方法
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
System.out.println("调用 public service 方法");
// 设定页面的MINE类型和字符集
response.setContentType("text/html;charset=utf-8");
// 输出响应
PrintWriter out = response.getWriter();
out.println("收到 service 请求");
}
// 二、调用 protected service 方法
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
System.out.println("调用 protected service 方法");
}
// 二、调用 doGet() 方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
// 二、调用 doPost() 方法
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用 doPost() 方法");
// 设定页面的MINE类型和字符集
response.setContentType("text/html;charset=utf-8");
// 输出响应
PrintWriter out = response.getWriter();
out.println("收到 HelloServlet doPost() 请求");
}
// 三、消亡阶段的 destory() 方法
public void destory() {
System.out.println("调用 destory() 方法");
}
}
五、关于 Servlet、HttpServlet、GenericServlet
Servlet
来自于 javax.servlet.Servlet
HttpServlet
来自于 javax.servlet.http.HttpServlet
GenericServlet
来自于 javax.servlet.GenericServlet
1. Servlet
servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法。一般开发不会去自己实现该接口,它只提供了一种规范,供 开发者 自己来编写相关的实现
-
可以看出,Servlet接口提供了5个必须实现的方法
2. GenericServlet
-
GenericServlet
定义了一个通用的,无关协议的Servlet。如果要在Web应用中使用Http进行Servlet通信,请扩展HttpServlet
(即继承HttpServlet
) -
在《JSP从零开始》的第100—101页有GenericServlet类的部分源代码,读者有兴趣可研究一下
- 下面是
GenericServlet
中的方法
3. HttpServlet
HttpServlet
是一个抽象类,它继承了 GenericServlet
抽象类,而 GenericServlet
类实现了 Servlet
接口,所以HttpServlet
类也就默认实现了 Servlet
接口。默认实现规范而实用,开发web端的servlet程序,一般我们只需继承 HttpServlet
类就可以了
创建
HttpServlet
的步骤:
①继承HttpServlet
抽象类;
②覆盖HttpServlet
的部分方法,如覆盖doGet()
或doPost()
方法;
③获取HTTP请求信息。通过HttpServletRequest
对象来检索HTML表单所提交的数据或URL上的查询字符串;
④生成HTTP响应结果。通过HttpServletResponse
对象生成响应结果,它有个getWriter()
方法,该方法返回一个PrintWriter
对象。-
它总共有10个方法,其中实现了:
① 2个重载的 service() 方法
- 在servlet中默认情况下,无论是get还是post 提交过来 都会经过
service()
方法来处理,然后转向到doGet()
或doPost()
方法,所以默认情况(没有重写service方法)下,service()
是用来转向的。 - 如果你在自己的servlet类中覆盖了
service()
方法,那么service()
就不是用来转向了,而是用来处理业务,这时不论客户端是用post还是get来请求此servlet,都会执行service()
方法也只能执行servlet()
方法,不会去执行doPost()
或doGet()
方法。
② doGet(),doPost(),doOptions(),doTrace(),doDelete(),doHead(), doPut() 这7个方法
- 最常用的还是
doGet()
和doPost()
,但一般来说我们是用不到doGet()
方法的。doGet()
方法提交表单时会在url后边显示提交内容,并不安全。而且doGet()
方法只能提交256个字符(1024字节),而doPost()
没有限制,因为get方式数据的传输载体是URL(提交方式能form,也可以是任意的URL链接),而POST是HTTP头键值对(只能以form方式提交)。通常我们使用的都是doPost()
方法,你只要在servlet中让这两个方法互相调用就行了。
③ getLastModified(HttpServletRequest req) 方法
- 传入参数为一个
HttpServletRequest
对象 - 返回一个数值,该值为从 1970年1月1日 到 该
HttpServletRequest
对象最近一次修改的那个时刻 走过的毫秒数。
最后,分享我用PowerDesigner创建的面向对象模型的关系图来说明三者的关联:
- 对PowerDesigner有兴趣的读者可以看该文集中的:PowerDesigner入门篇,可初步了解一下这个软件的使用。