目录
一.Servlet简介:
1.1 什么是Servlet:
Servlet全称Java Servlet 是用Java编写在服务端程序,主要是动态生成Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
下图:
1.2.Servlet的主要任务:
- 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
- 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
- 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
二.Servlet接口:
2.1 Servlet简介:
我们讲的Servlet就是一个所有的Servlet类直接或者间接必须实现的接口。而实现Servlet有三种方式:
当我们实现Servlet时,Servlet容器(服务器,现阶段Tomcat)会将Servlet类加载,并且产生一个Servlet实例以及调用具体的方法,Servlet实现类不需要程序员自己创建对象,在Servlet容器就已经创建好对象了。
实现javax.servlet.Servlet接口;
继承javax.servlet.GenericServlet类;
继承javax.servlet.http.HttpServlet类;(这个是我们主要用的)
注意点:
1.每一个Servlet类只能有一个实例对象(由容器创建)。
2.2 Servlet的工作流程:
当客户端发送请求到服务端时,服务器都会创建一个request对象,response对象,并把请求数据封装到request中,response对象用来对客户端进行响应,然后在调用Servlet.service()方法时传递给service()方法 ,调用sevice()方法之后把进行数据处理,形成动态数据,之后通过response对象对客户端进行响应。
request的主要功能:
-
封装了请求头数据;
-
封装了请求正文数据,如果是GET请求,那么就没有正文;
-
request是一个域对象,可以把它当成Map来添加获取数据;
-
request提供了请求转发和请求包含功能。
response的主要功能:
-
设置响应头信息;
-
发送状态码;
-
设置响应正文;
-
重定向;
2.3 Servlet接口的方法:
Servlet接口定义了五种方法:
* 实现Servlet的第一种方式
* 实现javax.servlet.Servlet接口
public class AServlet implements Servlet {
private ServletConfig servletConfig; //默认null
/**
* 初始化方法 生命周期方法, 由Tomcat调用 做初始化操作
* 在Servlet创建之后调用, 调用一次
* @param servletConfig
* @throws ServletException
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("555~~555,我出生了...");
this.servletConfig = servletConfig;
}
/**
* 得到ServletConfig对象 (Servlet的配置)
*
* @return
*/
@Override
public ServletConfig getServletConfig() {
return servletConfig;
}
/**
* 最重要的方法, 接收用户请求,处理用户请求, 响应结果
* Tomcat调用: 生命周期方法 , 每请求一次,执行一次
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("AServlet 正在服务...");
//获取Servlet配置
//System.out.println("Servlet的名字:"+servletConfig.getServletName());
//获取初始化参数
//根据初始化参数名获取值
String name = servletConfig.getInitParameter("name");
System.out.println("name:"+name);
//获取所有的初始化参数名
Enumeration<String> names = servletConfig.getInitParameterNames();
//遍历
while(names.hasMoreElements()){
String key = names.nextElement(); //参数名
String value = servletConfig.getInitParameter(key);
System.out.println("key:"+key+"--value:"+value);
}
}
/**
* 没什么意义
* 得到Servlet的描述
* @return
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 销毁方法, 释放资源
* 生命周期方法, Tomcat调用,
* 在Servlet销毁之前调用, 只执行一次
*/
@Override
public void destroy() {
System.out.println("555~555~我走了...");
}
}
这五个方法描述了Servlet的生命周期,从生到死的过程:
出生:默认情况下,第一次请求时,由Tomcat创建。
调用init方法。
运行:用户每请求一次这个Servlet, tomcat调用一次service()方法。
死亡:当Tomcat服务器关闭之前, 销毁它创建的所有对象,包含创建Servlet, 在Servlet销毁之前, 调用destroy()
2.4 ServletConfig接口:
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象。 ServletConfig对象,由服务器创建。
主要方法:
String getServletName():获取Servlet在web.xml文件中的配置名称,即<servlet-name>指定的名称;
ServletContext getServletContext():用来获取ServletContext对象,
String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
Enumeration getInitParameterNames():用来获取在web.xml中配置的所有初始化参数名称;
2.5 ServletContext对象:
ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
ServletContext对象的作用是在整个Web应用的动态资源之间共享数据!例如在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了。
通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。
在HttpServlet中可以直接调用 getServletConfig()方法,因为HttpServlet继承了GenericServlet,而GenericServlet实现了ServletConfig,并且GenericServlet有 getServletConfig(),所以在HttpServlet中可以直接调用得到ServletContext对象。
ServletContext servletContext = getServletConfig().getServletContext();
三.Servlet的抽象实现类:
3.1 GenericServlet抽象类 :
我们编写Servlet一直是通过实现Servlet接口来编写的,但是,使用这种方法,则必须要实现Servlet接口中定义的所有的方法,即使有一些方法中没有任何东西也要去实现,并且还需要自己手动的维护ServletConfig这个对象的引用。因此,这样去实现Servlet是比较麻烦的。
而GenericServlet抽象类则有三个好处:1.为Servlet接口中的所有方法提供了默认的实现,则程序员需要什么就直接改什么,不再需要把所有的方法都自己实现了。
2.并且提供方法,包围ServletConfig对象中的方法。
3.将init( )方法中的ServletConfig参数赋给了一个内部的ServletConfig引用从而来保存ServletConfig对象,不需要程序员自己去维护ServletConfig了。
注:但是我们很少用 GenericServlet抽象类,因为主要使用HttpServlet
以下是 GenericServlet抽象类代码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package javax.servlet;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
}
public void destroy() {
}
public String getInitParameter(String name) {
return this.getServletConfig().getInitParameter(name);
}
public Enumeration<String> getInitParameterNames() {
return this.getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
public String getServletInfo() {
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public void log(String message) {
this.getServletContext().log(this.getServletName() + ": " + message);
}
public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
public String getServletName() {
return this.config.getServletName();
}
}
3.2 HttpServlet抽象类:
HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以HttpServlet抽象类覆盖了GenericServlet抽象类中的Service( )方法,并且添加了一个自己独有的Service(HttpServletRequest request,HttpServletResponse方法。
HttpServlet中的service方法把接收到的ServletRequsest类型的对象转换成了HttpServletRequest类型的对象,把ServletResponse类型的对象转换成了HttpServletResponse类型的对象。之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。
转换之后,service方法把两个转换后的对象传入了另一个service方法,那么我们再来看看这个方法是如何实现的:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
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 errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
这个service方法的参数是HttpServletRequest对象和HttpServletResponse对象,刚好接收了上一个service方法传过来的两个对象。我们会发现在service方法中还是没有任何的服务逻辑,但是却在解析HttpServletRequest中的方法参数,并调用以下方法doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。所以,如果我们需要实现具体的服务逻辑,不再需要覆盖service方法了,只需要覆盖doGet或者doPost就好了。所以我们只需要写doget和doPost方法了。这样使代码更加简洁。
public class aServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}