servlet与tomcat
1、servlet与servlet容器
(1)servlet本质
前方高能,请注意、注意、注意。。。重要的事情说三遍,servlet本质就是一个Java接口 ,目的在于定义一套处理网络请求的规范,如下所示:
package javax.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface Servlet {
void init(ServletConfig arg0) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
所有实现servlet接口的类,都要实现接口中的五个方法,其中最主要的是两个生命周期方法 init()和destroy()、处理请求的service(),即:
- 初始化的作用;
- 销毁后的作用;
- 收到请求后需要做什么。
init() 和 destroy()方法只执行一次, 即servlet的生命周期---创建和销毁,而service()方法每次有新请求到达时都会调用,即处理处理实际业务。
(2)servlet容器
全称server applet,意为服务程序。主要作用是给上级容器(Tomcat)提供doGet()和doPost()等方法。其生命周期实例化、初始化、调用、销毁受控于Tomcat容器。
(3)request/response
request:浏览器发起http请求,请求到达tomcat,经tomcat封装成了request对象(将请求头、请求地址、请求参数等进行了封装);
response:浏览器发起http请求到达tomcat容器时,产生一个空的response对象,http请求数据经过servlet处理,将处理后结果封装成response对象,经过tomcat处理后,组装成HTTP响应返回给浏览器。
(4)web容器
可以部署多个WEB应用程序的环境。Tomcat容器属于web容器的一种,web容器还包括weblogic容器、JBoss容器等;而Tcomcat、webLogic等包含servlet容器。

注:三层架构实质是对servlet的拆分,目的在于解耦合。
2、tomcat
(1)tomcat程序入口main()
main方法是启动一个java程序的入口,任何程序都会有自己的main方法,tomcat是一个WEB容器,也不例外:
//TODO 以下为伪代码,目的在于说明tomcat执行原理
public static void main(String args[]) {
//TODO 初始化运行环境,载入需要的jar包,读取conf/server.xml,生成相应的运行对象:
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init();//初始化守护进程
} catch (Throwable t) {
return;
}
daemon = bootstrap;
}
//TODO 装载,开始运行。
try {
String command = "start";
if (command.equals("startd")) {
daemon.load(args);
daemon.start();//启动Tomcat
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();//停止Tomcat守护进程
}
} catch (Throwable t) {
}
}
(2)tomcat创建的resques和response

(3)tomcat对servlet接口的实现
abstract class GenericServlet implements Servlet, ServletConfig,Serializable
abstract class HttpServlet extends GenericServlet
public abstract class HttpServlet extends GenericServlet {
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);
}
}
//TODO doHead doPut doDelete
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
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;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException arg8) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < errMsg / 1000L * 1000L) {
this.maybeSetLastModified(resp, errMsg);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("POST")) {
this.doPost(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);
}
}
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException arg5) {
throw new ServletException(lStrings.getString("http.non_http"));
}
this.service(request, response);
}
}
部署的过程其实就是解析 xml 实例化对象,并触发和处理容器及组件对应生命周期事件的过程。在 Tomcat 中,一个 Context 实例就代表一个 Web 应用程序,所以部署的第一步就是创建一个 StandardContext 对象。在创建时 HostConfig 首先会查找 Context 描述符,它可能在两个位置:
- $CATALINA_BASE/conf/<engine>/<host>/[webappname].xml
- $CATALINA_BASE/webapps/webappname/META_INF/context.xml
如果两个位置都不存在此文件,则使用 conf/context.xml 默认配置。
Context 实例化后会触发 init 和 start 生命周期事件:
- init - 会创建用于解析 context.xml 和 web.xml 的工具 Digester 的实例,并解析context.xml
- start - 则会根据 web.xml 部署描述符实例化 Servlet、Filter、Listener 等 Web 组件
感谢阅读,参考了不少大佬资料,如需转载,请注明出处 https://www.cnblogs.com/huyangshu-fs/p/13173474.html
