一、什么是Servlet

  简单的说,浏览器发出请求到tocat服务器,服务器就会初始化一个servlet实例(servlet采取生命托管的方式实现单例,不存在时才会创建实例),servlet示例会启动一个线程来处理该请求,并进行响应该请求,动态生成web内容

二、什么是Tomcat服务器

  Tomcat是Apache开发的一种servlet容器,实现了对servlet和jsp等的支持,用来处理并响应浏览器发送过来的请求,实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与    Apache 独立的进程单独运行的。

三、web.xml配置文件解析

 1 <servlet>
2 <!-- servlet的内部名称,自定义 -->
3 <servlet-name>login</servlet-name>
4 <!-- servlet的类全名:包名+类名 -->
5 <servlet-class>com.TestServlet.servlet.LoginServlet</servlet-class>
6 <!-- 当servlet对象立即加载时 url?后携带的重要信息, 在加载servlet类是可以直接加载进去
7 可以通过可以在init方法内使用带ServletConfig的参数读取
8 String value = config.getInitParameter("key");//某一个key对应的value
9 Enumeration en = config.getInitParameterNames();//获取全部的key
10 String name = config.getServletName();//获取当前Servlet类名
11 ServletContext application = config.getServletContext();//获取全局上下文对象
12 -->
13 <init-param>
14 <param-name>name1</param-name>
15 <param-value>value1</param-value>
16 <param-name>name2</param-name>
17 <param-value>value2</param-value>
18 </init-param>
19 <!-- servlet对象创建优先级 -->
20 <load-on-startup>1</load-on-startup>
21 </servlet>
22 <!-- servlet的映射配置 -->
23 <servlet-mapping>
24 <!-- servlet的内部名称,和上面的自定义servlet-name对应的标签名称一致 -->
25 <servlet-name>login</servlet-name>
26 <!-- servlet的映射路径(访问serclet的名称) -->
27 <url-pattern>/index</url-pattern>
28 </servlet-mapping>
29 <!-- 整体详情解析 以 http://localhost:8080/index-->
30 <!-- 通过解析url得到 index 去标签 servlet-mapping中的url-pattern标签进行匹配,
31 若是匹配上,得到servlet-name标签中的 login定位符,在通过 login 到
32 servlet标签下的 servlet-name 进行匹配,若是匹配上获取 servlet-class标签的
33 类全名 com.TestServlet.servlet.LoginServlet, 在通过反射技术创建 LoginServlet对象实例
34 -->

四、servlet类的继承关系

  自己定义一个类来继承HttpServlet
 1 public class LoginServlet extends HttpServlet {
2
3 @Override
4 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
5 super.service(req, resp);
6 }
7
8 @Override
9 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
10 super.doGet(req, resp);
11 }
12
13 @Override
14 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
15 super.doPost(req, resp);
16 }
17 }
  由上面代码可以看到,我们重写了三个常用的方法,但上面除了方法名不同,其他全部相同,这是为什么呢,我们带着这个问题,来对源码进行追根溯源
  HttpServlet类继承关系
1 // HtppServlet继承类GenericServlet类
2 public abstract class HttpServlet extends GenericServlet {}
3 /* GenericServlet类,实现了三个接口,分别为
4 Servlet: servlet接口
5 ServletConfig: 封装servlet配置信息
6 Serializable: 序列化接口,在反序列化时进行版本比对
7 */
8 public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {}

  servlet类源码解析

 1 public interface Servlet {
2 /**
3 * servlet声明周期
4 * 1、init() 初始化,仅第一次servlet时执行,同时会携带一个ServletConfig参数
5 * 2、service() 用户处理请求,每次访问servlet时都会执行一次
6 * 3、destory() 重新配置或者重新部署项目时执行,用于销毁servlet对象,销毁后的对象由gc进行回收
7 * */
8 void init(ServletConfig var1) throws ServletException;
9
10 ServletConfig getServletConfig();
11
12 void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
13
14 String getServletInfo();
15
16 void destroy();
17 }
  ServletConfig源码解析
 1 public interface ServletConfig {
2 // 获取当前servlet类名
3 String getServletName();
4 // 获取servlet全局上下文
5 ServletContext getServletContext();
6 // 获取web.xml文件中<init-param>标签下某一个<param-name>标签的值
7 String getInitParameter(String var1);
8 // 获取web.xml文件中<init-param>标签下所有的<param-name>标签的值
9 Enumeration<String> getInitParameterNames();
10 }
  源码解析GenricServlet类
 1 // 序列化
2 private static final long serialVersionUID = 1L;
3 // ServletConfig 属性
4 private transient ServletConfig config;
5 // 无参构造方法
6 public GenericServlet() {
7 }
8 // 实现了servlet中的destroy() 方法
9 public void destroy() {
10 }
11 // 重写了并实现了ServletConfig中的getInitParameter(),便于获取web.xml配置文件中的<init-param>标签下某一个<param-name>标签的值
12 public String getInitParameter(String name) {
13 return this.getServletConfig().getInitParameter(name);
14 }
15 // 重写了并实现了ServletConfig中的getInitParameter(),便于获取web.xml配置文件中的<init-param>标签下所有的<param-name>标签的值
16 // 返回Enumeration 可以采取while循环获取所有key值
17 // hasMoreElements 判断是否还有key
18 // nextElement(); 获取key值
19 public Enumeration<String> getInitParameterNames() {
20 return this.getServletConfig().getInitParameterNames();
21 }
22
23 // 获取当前servlet对象
24 public ServletConfig getServletConfig() {
25 return this.config;
26 }
27
28 // 获取servlet全局上下文
29 //
30 public ServletContext getServletContext() {
31 return this.getServletConfig().getServletContext();
32 }
33
34 public String getServletInfo() {
35 return "";
36 }
37
38 // 实现了init初始化方法,将config对象赋值给自己的config属性中,从而达到在servlet第一此加载时,就拥有config对象
39 public void init(ServletConfig config) throws ServletException {
40 this.config = config;
41 this.init();
42 }
43
44 // 添加了一个Init无参方法,可以提供用户进行重写
45 public void init() throws ServletException {
46 }
47
48 // 增加了自己的log方法,控制台打印日志
49 public void log(String msg) {
50 this.getServletContext().log(this.getServletName() + ": " + msg);
51 }
52
53 public void log(String message, Throwable t) {
54 this.getServletContext().log(this.getServletName() + ": " + message, t);
55 }
56
57 // 该类由用户自己定以 所以没有实现接口方法
58 public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
59
60 // 获取serlet类对象名
61 public String getServletName() {
62 return this.config.getServletName();
63 }
  源码解析HttpServlet类
 1 // doGet方法,未进行任何处理,
2 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
3 String protocol = req.getProtocol();
4 String msg = lStrings.getString("http.method_get_not_supported");
5 if (protocol.endsWith("1.1")) {
6 resp.sendError(405, msg);
7 } else {
8 resp.sendError(400, msg);
9 }
10
11 }
12
13 // doPost方法,未进行任何处理,
14 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
15 String protocol = req.getProtocol();
16 String msg = lStrings.getString("http.method_post_not_supported");
17 if (protocol.endsWith("1.1")) {
18 resp.sendError(405, msg);
19 } else {
20 resp.sendError(400, msg);
21 }
22
23 }
24
25 // 提供了自己的受保护的service方法,便于子类访问,类中未进行具体操作,而是通过获取请求类型来定位调用方法来处理
26 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
27 String method = req.getMethod();
28 long lastModified;
29 if (method.equals("GET")) {
30 lastModified = this.getLastModified(req);
31 if (lastModified == -1L) {
32 this.doGet(req, resp);
33 } else {
34 long ifModifiedSince;
35 try {
36 ifModifiedSince = req.getDateHeader("If-Modified-Since");
37 } catch (IllegalArgumentException var9) {
38 ifModifiedSince = -1L;
39 }
40
41 if (ifModifiedSince < lastModified / 1000L * 1000L) {
42 this.maybeSetLastModified(resp, lastModified);
43 this.doGet(req, resp);
44 } else {
45 resp.setStatus(304);
46 }
47 }
48 } else if (method.equals("HEAD")) {
49 lastModified = this.getLastModified(req);
50 this.maybeSetLastModified(resp, lastModified);
51 this.doHead(req, resp);
52 } else if (method.equals("POST")) {
53 this.doPost(req, resp);
54 } else if (method.equals("PUT")) {
55 this.doPut(req, resp);
56 } else if (method.equals("DELETE")) {
57 this.doDelete(req, resp);
58 } else if (method.equals("OPTIONS")) {
59 this.doOptions(req, resp);
60 } else if (method.equals("TRACE")) {
61 this.doTrace(req, resp);
62 } else {
63 String errMsg = lStrings.getString("http.method_not_implemented");
64 Object[] errArgs = new Object[]{method};
65 errMsg = MessageFormat.format(errMsg, errArgs);
66 resp.sendError(501, errMsg);
67 }
68
69 }
70
71 // 实现了接口servlet类中的service()方法,但没有将具体处理,仅仅将ServletRequest和ServletResponse进行
72 // 此处体现了面向对象思想,也体现了适配器模式的应用。
73 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
74 HttpServletRequest request;
75 HttpServletResponse response;
76 try {
77 request = (HttpServletRequest)req;
78 response = (HttpServletResponse)res;
79 } catch (ClassCastException var6) {
80 throw new ServletException("non-HTTP request or response");
81 }
82
83 // 调用该类的受保护类
84 this.service(request, response);
85 }
  servlet生命周期
    servlet对象是单实例管理,底层采用生命周期托管方式实现
    Servlet对象是延迟加载的机制,在第一次访问时创建对象,且只加载一次
    Servlet对象的创建 使用 销毁的三个方法分别是:
    init() 第一次访问servlet时执行
    service() 每一次访问servlet都会调用一次
    destroy() 重新配置或者部署项目时,调用该方法进行销毁servlet对象,销毁的对象由GC垃圾回收机制进行回收
  Servlet管理机制总结
    1、我们自己的类继承了HttpServlet
    2、HttpServlet继承了GenericServlet
    3、GenericServlet实现了三个接口
      Servlet接口 ServletConfig接口 Serializable接口
      ServletConfig接口拥有四个方法,但都是抽象方法
        String = getInitParamName(String v) // 初始化servlet类
        Enumeration<String> = getInitParamNames() // 获取所有key
        String = getServetName // 获取类对象名称
        ServletContext = getServletContext() // 获取类对象上下文
      Servlet接口提供了五个方法,全部都是抽象
        void init(ServletConfig sc); // 初始化servlet类
        void service(ServletRequest req, ServletResponse res) throw ServletException, IOException
        void destroy() //servlet对象销毁方法
      ServletConfig getServletConfig() // 获取servlet类对象
        String getServletInfo() // 获取servlet类信息 若版本,作者,版权等
      Serializable接口 没有提供任何方法
    4、GenericServlet类
      将9个抽象方法实现了8个,还有一个service()没有实现,此处体现了缺省适配器模式
      自己添加了 init() 无参数方法 和 log() 方法
    5、HttpServlet 类,体现了面向对象的思想,跟HTTP有关
      该类中实现了service(),但仅对方法中的形参ServletRequset和ServletResponse进行了强制转换成HttpServletRequset和HttpServletResponse
      同时添加了一个protect修饰的service方法,即最终方法,但是该方法即通过 request.getMethod()来获取请求类型,并进行方法调用
      添加一些属于自己的且和请求方式对应的具体方法,如
        doGet(HttpServletRequset req, HttpServletResponse res) throw ServletException, IOException
        doGet(HttpServletRequset req, HttpServletResponse res) throw ServletException, IOException
      添加了一些属于自己的属性
      get post put等
    6、 我们自己的servlet类继承HttpServlet,重写service方法,或者doGet/doPost等方法
      若是我们自己类没有重写service方法,那么会从父类GenericServlet中的service去查找doGet/doPost等方法,抛出405
 

JavaWeb之servlet管理机制的更多相关文章

  1. Tomcat的Session管理机制

    >>Session和Cookie请求的过程 Http连接本身是无状态的,即前一次发起的连接跟后一次没有任何关系,是属于两次独立的连接请求,但是互联网访问基本上都是需要有状态的,即服务器需要 ...

  2. web状态管理机制

    引入:b/s(浏览器/服务器模式)区别于winform的是winform中只加载一次页面构造函数,而b/s中只要点击按钮或者其他涉及后台的操作都会调用后台代码.一般情况下为了防止服务器过载,b/s不会 ...

  3. Tomcat中session的管理机制

    1.       请求过程中的session操作: 简述:在请求过程中首先要解析请求中的sessionId信息,然后将sessionId存储到request的参数列表中.然后再从 request获取s ...

  4. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  5. ARC内存管理机制详解

    ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...

  6. 深入了解C#系列:谈谈C#中垃圾回收与内存管理机制

    今天抽空来讨论一下.Net的垃圾回收与内存管理机制,也算是完成上个<WCF分布式开发必备知识>系列后的一次休息吧.以前被别人面试的时候问过我GC工作原理的问题,我现在面试新人的时候偶尔也会 ...

  7. 【Cocos2d-x 3.x】内存管理机制与源码分析

    侯捷先生说过这么一句话 :  源码之前,了无秘密. 要了解Cocos2d-x的内存管理机制,就得阅读源码. 接触Cocos2d-x时, Cocos2d-x的最新版本已经到了3.2的时代,在学习Coco ...

  8. Spark 1.6以后的内存管理机制

     Spark 内部管理机制 Spark的内存管理自从1.6开始改变.老的内存管理实现自自staticMemoryManager类,然而现在它被称之为"legacy". " ...

  9. Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制

    在<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>中,我介绍了获取AccessToken(通用接口)的方法. 在实际的开发过程中,所有的高级接口都需 ...

随机推荐

  1. TcaplusDB常见问题-数据库原理类

    gameserver 如何剔除某个无效的 tcaproxy(接入层)节点? TcaplusDB API 在这里对 tcaproxy 异常做了容灾的处理,API 剔除无效的 tcaproxy 进程的方式 ...

  2. 烧录失败导致boot无法加载的解决措施,再也不怕烧成砖了

    目录: 1.usb烧录时出现的问题截图 2.重新擦除boot发现失败的情况 3.解决措施 烧录失败导致boot无法加载的解决措施在烧录系统的时候经常会遇到烧录失败的情况,如果能通过再次执行烧录能烧上肯 ...

  3. Angular写一个Form组件-TagInput

    前端开发少不了和表单打交道; Angular中, 提供了强大的表单的支持, 响应式表单(Reactive Form) 和 模板驱动的表单(Template-driven Form) 的双向数据流给我们 ...

  4. 从零开始教你安装Oracle数据库

    1.数据库安装 1.1下载 根据自己的操作系统位数,到oracle官网下载(以oracle 11g 为例) 之后把两个压缩包解压到同一个文件夹内(需要注意的是,这个文件夹路径名称中最好不要出现中文.空 ...

  5. CF 1288 E. Messenger Simulator

    CF 1288 E. Messenger Simulator 题目传送门 官方题解 题意想必大家都明白了这里就不赘述了,这里只想重点记录一下几种实现方法 分析 设向前移动的序列为\(a\)序列 对于没 ...

  6. AtCoder Beginner Contest 178

    比赛链接:https://atcoder.jp/contests/abc178/tasks A - not 题意 给出一个整数 $0 \le x \le 1$,如果 $x$ 是 $0$ 就输出 $1$ ...

  7. Educational Codeforces Round 21

    Educational Codeforces Round 21  A. Lucky Year 个位数直接输出\(1\) 否则,假设\(n\)十进制最高位的值为\(s\),答案就是\(s-(n\mod ...

  8. 哈尔滨理工大学软件与微电子学院程序设计竞赛(同步赛) C.Coronavirus (BFS)

    题意:有一个图,要求从\(S\)走到\(E\),\(.\)表示可以走的路径,\(*\)周围的八个方向均不能走,要求判断是否能走到\(E\),若能,输出最小路径长度,否则输出\(Impossible\) ...

  9. c语言实现链表增、删、改、查及文件读写 && 链表实现程序

    一.链表实现增删改查 1.链表定义 1 #include<stdio.h> 2 #include<string.h> 3 #include<windows.h> 4 ...

  10. HTTP的传输编码(Transfer-Encoding:chunked) / net::ERR_INVALID_CHUNKED_ENCODING

    https://blog.csdn.net/m0_37668842/article/details/89138733 https://www.cnblogs.com/jamesvoid/p/11297 ...