什么是Servlet
Java Servlet是运行在web服务器或应用服务器上的程序,它是作为Web浏览器或者是其他的Http客户端的请求和Http服务器上的数据库或应用程序之间的中间件。
Servlet的工作模式
一开始,客户端发送请求给服务器
服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器。
服务器将响应返回客户端。
Servlet工作原理以及流程
Servlet接口定义了Servlet与Servlet容器之间的契约,(Servlet容器例如Tomcat)。Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它的具体方法。
用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个对象。
ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http数据。ServletResponse表示当前用户的Http响应,程序员只需直接操作ServletResponse对象就能把响应轻松的发回给用户。
Servlet接口中定义的方法
第一次在idea中使用Servlet的话是调用不了,java没有引入这个jar包
需要在Project Structure中引入
新建一个MyFirstServlet的一个类
查看一下源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package javax.servlet;
import java.io.IOException;
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
init
service
destroy
servlet的生命周期
其中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:
1.init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用,就像人只能“出生”一次一样。我们可以利用init( )方法来执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化
2.service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。就像人一样,需要不停的接受老板的指令并且“工作”。第一次请求时,
在这里插入代码片
Servlet容器会先调用init()方法初始化一个Servlet对象出来,然后会调用它的service()方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。
3.destory,当要销毁Servlet时,Servlet容器就会调用这个方法,就如人一样,到时期了就得死亡。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。
重写MyFirstServlet方法
import javax.servlet.*;
import java.io.IOException;
/**
* @Classname MyFirstServlet
* @Description TODO
* @Date 2020/4/21 20:40
* @Created by mmz
*/
public class MyFirstServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("Servlet正在被初始化");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Servlet正在调用服务");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("数据库正在被销毁");
}
}
**GenericServlet抽象类 **
前面我们一直继承Servlet这个接口来完成编写,但是这种方法,我们必须要实现Servlet接口中定义的所有方法,即使有一些方法中没有任何想要去实现的东西。
GenericServlet抽象类的出现很好的解决了这个问题
HttpServlet
HttpServlet是由GenericServlet抽象类扩展而来的。
里面我们可以看到两个类HttpServletRequest和HttpServletResponse,这两个类都是继承与ServletRequest与ServletResponse
HttpServlet的service方法
看图我们可知,HttpServelt,将传递过来的ServletResponse/Request对象转换成为了HttpServletRequest/Response对象,然后再调用自己的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);
}
}
我们可以仔细的看一下代码的逻辑
相当于解析了HttpServletRequest中的方法参数,用method.equals在去调用下面的doGet/doPost等等方法
这样我们只需要对doGet与doPost方法进行重写覆盖即可。
HttpServletRequest接口
图没有截全,主要是HttpServletRequest通过这些函数来解析这个http请求到底是来做什么的。
HttpServletResponse接口
是如何发送回去reponse,也是通过这些函数来进行返回的。
Response的工作流程
Servlet的工作流程