Servlet喂饭级教程
目录很重要^。^
全局Servlet可用的配置信息ServletContext
Servlet含义及作用
含义:
Servlet是运行在 Web 服务器或应用服务器上的Java小程序。
作用:
1.通过Http接收客户端传来的显式的或隐式的数据。显示数据如HTML表单,隐式数据如cookies。
2.处理数据,可能涉及访问数据库,执行RMI等。
3.通过Http向客户端返回显式或隐式的数据。显式数据如HTML文本文件,图片等。隐式数据如cookies等。
下面简单地演示Servlet:
*不涉及Tomcat等环境配置。
*细节部分将在下面讲解。
1.创建Servlet
2.配置DD文件
*DD文件:Deployment Descriptor,部署描述文件,即web.xml。
3.启动服务器,在网页中输入http://localhost:8080/WebDemo/FirstServlet.do,得到响应。
Servlet的三种实现方式
1.实现Servlet接口,并重写其中的5个方法,包括service、init、getServletConfig、getServletInfo、destroy。
2.继承GenericServlet类,并重写service方法。
3.继承HttpServlet类,并重写doPost或doGet方法。
为什么这三种方法的要求不同呢?他们之间有关系吗?平常我们更应该使用哪一种呢?
其实他们之间的关系是这样子的:
由下往上,HttpServlet抽象类继承了GenericServlet抽象类,而GenericServlet又实现了Servlet接口。
这也解释了为什么如果我们直接实现Servlet接口要重写那5种方法,因为它是个接口。
这也解释了为什么如果我们继承GenericServlet抽象类要实现service方法,因为它实现了Servlet接口除了service之外的方法。
这也解释了为什么如果我们继承HttpServlet抽象类,Servlet的5个方法我们就不用动手写了,因为HttpServlet把GenericServlet的service方法也实现了。
因此我们最常用的应该是继承HttpServlet类。
但是别忘了写doGet或者doPost方法。因为对于一个Servlet,每次被调用都会执行其service方法,而HttpServlet实现的service方法中调用了这两种方法。但是它自身所提供的doGet、doPost等方法都是直接返回错误信息,所以我们需要在自己定义的Servlet类中override这些方法。
//HttpServlet实现的service方法源码
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long errMsg;
if(method.equals("GET")) {
errMsg = this.getLastModified(req);
if(errMsg == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if(ifModifiedSince < errMsg / 1000L * 1000L) {
this.maybeSetLastModified(resp, errMsg);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if(method.equals("HEAD")) {
errMsg = this.getLastModified(req);
this.maybeSetLastModified(resp, errMsg);
this.doHead(req, resp);
} else if(method.equals("POST")) {
this.doPost(req, resp);
} else if(method.equals("PUT")) {
this.doPut(req, resp);
} else if(method.equals("DELETE")) {
this.doDelete(req, resp);
} else if(method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if(method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg1 = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg1 = MessageFormat.format(errMsg1, errArgs);
resp.sendError(501, errMsg1);
}
}
//doGet源码、其他doPost等方法也类似
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if(protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
Servlet的生命周期
先说结论:
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
想要了解Servlet的生命周期,我们直接实现Servlet接口来看比较直观。
照例,写好自己的Servlet,配置好DD文件。
然后让我们来运行看看!
在浏览器输入网址:http://localhost:8080/WebDemo/ServletDemo1.do
可以看到虽然什么也显示(因为我们没写),但是控制台打印了调用init()与调用service()的信息。
那么接下来重复进入这个网址:
再次重复被调用后只调用了service()。
说明Servlet在第一次被调用的时候才初始化,之后再被调用直接运行service方法。
而关于destroy(),是当服务器停止时,Servlet 容器需要回收 Servlet 对象所占用的内存,在回收之前,会自动调用该对象的 destroy() 方法做好回收内存前的准备,辟如关闭后台线程。所以destroy()与init()一样只执行一次。
自身Servlet可用的配置信息ServletConfig
ServletConfig是可以调用自身Servlet在web.xml中的配置信息的接口。
先来看看怎么用吧:
1.在web.xml中的<servlet>标签下写好<init-param>标签。
2.在Servlet中调用ServletConfig对象来使用这些初始化的信息。
3.查看
因此,ServletConfig的使用就是那么简单。
我们也可以从DD文件的配置中知道这些初始化变量的使用范围都是仅局限与自身Servlet里的!
另附上ServletConfig接口的常见方法:
String getServletName() 获取当前Servlet在web.xml中配置的名字
String getInitParameter(String name) 获取当前Servlet指定名称的初始化参数的值
Enumeration getInitParameterNames() 获取当前Servlet所有初始化参数的名字组成的枚举ServletContext getServletContext() 获取代表当前web应用的ServletContext对象
全局Servlet可用的配置信息ServletContext
ServletContext,即Servlet上下文,即代表整个Web应用对象。工程内部的所有Servlet共享这个对象。其生命周期是从Web应用加载到Web应用销毁。
类似ServletConfig,也是配置web.xml后在Servlet中调用。细节区别在图中,请瞪大5.3的眼睛。
web.xml中配置:
Servlet中调用:
网页查看:
注意,每个Servlet中都可以使用这个全局key:sayHello来查看它的value:Hello。这里只演示了一个。
水平有限,欢迎勘误抓虫~