目录

一:ServletConfig接口

二:ServletContext接口

三:补充缓冲机制


一:ServletConfig接口

(1)ServletConfig是什么?

javax.servlet.ServletConfig,显然ServletConfig是Servlet规范中的一员。
ServletConfig是一个接口。(javax.servlet.Servlet是一个接口。)

(2)谁去实现了这个接口? WEB服务器实现了

public class org.apache.catalina.core.StandardWrapperFacade implements ServletConfig {}

结论:Tomcat服务器实现了ServletConfig接口。
思考:如果把Tomcat服务器换成jetty服务器,输出ServletConfig对象的时候,还是这个结果吗?不一定一样,包名类名可能和Tomcat不一样。但是他们都实现了ServletConfig这个规范。

(3)一个Servlet对象中有一个ServletConfig对象。

Servlet和ServletConfig对象是一对一,100个Servlet,就应该有100个ServletConfig对象。

(4)ServletConfig对象是谁创建的?在什么时候创建的?

Tomcat服务器(WEB服务器)创建了ServletConfig对象。
在创建Servlet对象的时候,同时创建ServletConfig对象,然后才能调用init方法把ServletConfig对象传进去。

(5)ServletConfig接口有什么用?

Config是哪个单词的缩写?Configuration(配置),所以ServletConfig对象被翻译为:Servlet对象的配置信息对象。一个Servlet对象就有一个对应的配置信息对象!

(6)ServletConfig对象中包装了什么信息?

ServletConfig对象中包装的信息是:web.xml文件中<servlet></servlet>标签的配置信息。
Tomcat解析web.xml文件,将web.xml文件中<servlet></servlet>标签中的配置信息自动包装到ServletConfig对象中。

(7)ServletConfig接口中有哪些方法?ServletConfig接口中有4个方法:

方法1:public String getServletName()

可以获取到web.xml配置文件中<servlet-name></servlet-name>里面的名字

方法2: public Enumeration<String> getInitParameterNames()

获取所有的初始化参数的name,返回一个集合

实际上通过上面两种方法的联合使用:可以获取到web.xml文件中Servlet对象的初始化参数配置信息

方法3:public String getInitParameter(String name)

遍历集合,拿到每一个name,然后根据name获取value
方法4:public ServletContext getServletContext(); 后面会重点讲解

             ServletConfig对象对应整个web.xml文件
以上的4个方法,有两种方法可以进行调用:

第一种:调用getServletConfig()方法获取到ServletConfig对象,然后进行方法的调用

第二种:在自己编写的Servlet类当中也可以使用this去调用。因为通过原码发现GenericServlet也实现了ServletConfig接口, 而自己编写的Servlet类又要实现GenericServlet类,所以直接用this调用也行!

public abstract class GenericServlet implements
Servlet, ServletConfig, Serializable {}

 ConfigTestServlet类继承GenericServlet

package com.bjpowernode.javaweb.servlet;import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;public class ConfigTestServlet extends GenericServlet {@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {// 设置响应的内容类型response.setContentType("text/html");// 设置输出的位置PrintWriter out = response.getWriter();// 获取ServletConfig对象ServletConfig config = this.getServletConfig();// 输出该对象// org.apache.catalina.core.StandardWrapperFacade@7d72f398、out.print("ServletConfig对象是:"+config.toString());out.print("<br>");// 获取<servlet-name></servlet-name>String servletName = config.getServletName();out.print("<servlet-name>"+servletName+"</servlet-name>"); // configTestout.print("<br>");// <servlet></servlet>标签中的<init-param></init-param>是初始化参数。// 这个初始化参数信息会自动被Tomcat封装到ServletConfig对象当中。下面就进行获取// 通过ServletConfig对象的两个方法,可以获取到web.xml文件中的初始化参数配置信息。// java.util.Enumeration<java.lang.String> getInitParameterNames() 获取所有的初始化参数的name// java.lang.String  getInitParameter(java.lang.String name) 通过初始化参数的name获取valueEnumeration<String> initParameterNames = config.getInitParameterNames();// 遍历集合while(initParameterNames.hasMoreElements()){ // 是否有更多元素// 取元素(每一个name)String parameterName = initParameterNames.nextElement();// 通过name获取valueString parameterVal = config.getInitParameter(parameterName);// 进行输出打印out.print(parameterName+"="+parameterVal );out.print("<br>");/*password=root1234driver=com.mysql.jdbc.Driveruser=rooturl=jdbc:mysql://localhost:3306/bjpowernode*/}// 重点:通过原码发现GenericServlet也实现了ServletConfig接口,// 而ConfigTestServlet类又实现了GenericServlet类,所以直接用this掉用也行Enumeration<String> names = this.getInitParameterNames();while(names.hasMoreElements()){String name = names.nextElement();// 通过name获取valueString value = this.getInitParameter(name);// 输出到控制台System.out.println(name +"="+value);}}
}

web.xml配置信息

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>configTest</servlet-name><servlet-class>com.bjpowernode.javaweb.servlet.ConfigTestServlet</servlet-class><!--这里是可以配置一个Servlet对象的初始化信息--><init-param><param-name>driver</param-name><param-value>com.mysql.jdbc.Driver</param-value></init-param><init-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/bjpowernode</param-value></init-param><init-param><param-name>user</param-name><param-value>root</param-value></init-param><init-param><param-name>password</param-name><param-value>root1234</param-value></init-param></servlet><servlet-mapping><servlet-name>configTest</servlet-name><url-pattern>/test</url-pattern></servlet-mapping>
</web-app>

总结:

  • 什么是ServletConfig?

    • Servlet对象的配置信息对象,一个Servlet对象就有一个ServletConfig(配置信息)。

    • ServletConfig对象中封装了<servlet></servlet>标签中的配置信息。(web.xml文件中servlet的配置信息)

  • 一个Servlet对应一个ServletConfig对象。

  • Servlet对象是Tomcat服务器创建,并且ServletConfig对象也是Tomcat服务器创建。并且默认情况下,他们都是在用户发送第一次请求的时候创建。

  • Tomcat服务器调用Servlet对象的init方法的时候需要传一个ServletConfig对象的参数给init方法。

  • ServletConfig接口的实现类是Tomcat服务器给实现的。(Tomcat服务器就是WEB服务器)

  • ServletConfig接口有哪些常用的方法?

  • public String getInitParameter(String name); // 通过初始化参数的name获取value
    public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name
    public ServletContext getServletContext(); // 获取ServletContext对象
    public String getServletName(); // 获取Servlet的name
  • 以上四个方法在Servlet类当中,都可以使用this去调用。因为我们自己编写的类继承了GenericServlet,而GenericServlet又实现了ServletConfig接口。

二:ServletContext接口

获取ServletContext对象的两种方式:

// 第一种方式:通过ServletConfig对象获取ServletContext对象。
ServletContext application = config.getServletContext();
//org.apache.catalina.core.ApplicationContextFacade@f0fa019
out.print("<br>" + application); // 第二种方式:通过this也可以获取ServletContext对象。
ServletContext application2 = this.getServletContext();
//org.apache.catalina.core.ApplicationContextFacade@f0fa019
out.print("<br>" + application2); 

(1)ServletContext是什么?

ServletContext是一个接口,Tomcat服务器对ServletContext接口进行了实现。

(2)ServletContext是谁实现的?

Tomcat服务器(WEB服务器)实现了ServletContext接口。

一个Servlet对象对应一个ServletConfig。100个Servlet对象则对应100个ServletConfig对象。但是只要在同一个webapp当中,只要在同一个应用当中,所有的Servlet对象都是共享同一个ServletContext对象的。

  public class org.apache.catalina.core.ApplicationContextFacade
implements ServletContext {}

(3)ServletContext对象是谁创建的?在什么时候创建的?

ServletContext对象是WEB服务器创建的。

ServletContext对象WEB服务器启动的时候创建,在服务器关闭的时候销毁!

这就是ServletContext对象的生命周期,ServletContext对象是应用级对象。
Tomcat服务器中有一个webapps,这个webapps下可以存放webapp,可以存放多个webapp,假设有100个webapp,那么就有100个ServletContext对象。但是总之一个应用,一个webapp肯定是只有一个ServletContext对象。 

(4)ServletContext怎么理解?

context是什么意思:Servlet对象的环境对象。(Servlet对象的上下文对象
一个ServletContext对象其实对应的就是整个web.xml文件。
理解:50个学生,每个学生都是一个Servlet,这50个学生都在同一个教室当中。那么这个教室就相当于ServletContext对象。并且放在ServletContext对象当中的数据,所有Servlet一定是共享的。
例如:一个教室中的空调是所有学生共享的,一个教室中的语文老师是所有学生共享的。
Tomcat是一个容器,一个容器当中是可以放多个webapp,但是一个webapp只对应一个ServletContext对象。

(5)验证ServletContext对象是共享的!

定义一个Aservlet和一个Bservlet,通过这两个类都继承GenericServlet,然后调用getServletContext()方法获得ServletContext对象,发现是同一个对象。

Aservlet

package com.bjpowernode.javaweb.servlet;import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;public class Aservlet extends GenericServlet {@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {// 设置响应代码类型response.setContentType("text/html");PrintWriter out = response.getWriter();// 获取ServletContext对象ServletContext application = this.getServletContext();// 输出打印// org.apache.catalina.core.ApplicationContextFacade@3d8fcad7out.print(application);}
}

Bservlet

package com.bjpowernode.javaweb.servlet;import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;public class Bservlet extends GenericServlet {@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {// 设置响应代码类型response.setContentType("text/html");PrintWriter out = response.getWriter();// 获取ServletContext对象ServletContext application = this.getServletContext();// 输出打印// org.apache.catalina.core.ApplicationContextFacade@3d8fcad7out.print(application);}
}

 配置文件web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>aservlet</servlet-name><servlet-class>com.bjpowernode.javaweb.servlet.Aservlet</servlet-class></servlet><servlet-mapping><servlet-name>aservlet</servlet-name><url-pattern>/a</url-pattern></servlet-mapping><servlet><servlet-name>bservlet</servlet-name><servlet-class>com.bjpowernode.javaweb.servlet.Bservlet</servlet-class></servlet><servlet-mapping><servlet-name>bservlet</servlet-name><url-pattern>/b</url-pattern></servlet-mapping>
</web-app>

执行结果

(6)ServletContext接口中有哪些常用的方法?

①public String getInitParameter(String name)  通过初始化参数的name获取value
②public Enumeration<String> getInitParameterNames() 获取所有的初始化参数的name

ServletContext对象中也有这两个方法,这个两个方法获取的是上下文的初始化参数配置信息<context-param></context-param>;这些配置信息用ServletContext对象来获取。

增加配置信息

注意:

①以下的配置信息属于应用级的配置信息(相当于全局的配置信息),一般一个项目中共享的配置信息会放到以下的<context-param>标签当中,使用ServletContext对象来获取
②如果你的配置信息只是想给某一个servlet作为参考,那么你配置到 <init-param>标签当中即可,使用ServletConfig对象来获取

 <context-param><param-name>pageSize</param-name><param-value>10</param-value></context-param><context-param><param-name>startIndex</param-name><param-value>0</param-value></context-param>

增加通过方法调用获取到配置信息

 // 获取上下文的初始化参数Enumeration<String> initParameterNames = application.getInitParameterNames();while(initParameterNames.hasMoreElements()){// 获取每一个对象String name = initParameterNames.nextElement();// 通过name获取valueString value = application.getInitParameter(name);out.print(name+"="+value);out.print("<br>");}
/*startIndex=0pageSize=10
*/

③public String getContextPath() 获取应用的根路径,相当于拿到了项目名!

// 动态获取context path (获取应用上下文的根)
String contextPath = application.getContextPath();
out.print(contextPath+"<br>"); // "/servlet04"

④public String getRealPath(String path) 获取文件的绝对路径(真实路径)

例如:我们都知道web是根目录,那么就在web根目录下面创建一个common目录;然后在common目录下在创建一个common.html文件。

后面的这个路径,加了一个“/”,这个“/”代表的是web的根;不加“/”,默认也是从根下开始找

// 获取文件的绝对路径,“/”加不加都行,默认都是从web的根下开始找的
String realPath = application.getRealPath("/common/commom.html");
String realPath = application.getRealPath("commom.html");
//C:\Users\86177\IdeaProjects\JavaWeb\out\artifacts\servlet04_war_exploded\common\commom.html
out.print(realPath);

⑤通过ServletContext对象调用下面两个无参方法也是可以记录日志的

public void log(String message) 记录日志的方法
public void log(String message, Throwable t) 记录日志的方法

注意:如果使用文本编译器,这个日志会自动记录到CATALINA_HOME/logs目录下。

如果使用IDEA,IDEA可以创建多个Tomcat服务器;所以日志文件肯定是和IDEA相关的目录下;启动Tomcat找到下面这句话:Using CATALINA_BASE:   "C:\Users\86177\.IntelliJIdea2018.3\system\tomcat\Tomcat_9_0_68_JavaWeb"; 这些是参照CATALINA_HOME下的资源生成的一个Tomcat副本:

启动Tomcat服务器会生成两个日志文件:

catalina.2022-11-03.log 服务器端的java程序运行的控制台信息。

catalina.2022-11-03.log 客户端发出请求的访问日志。

客户端发出请求又生成一个日志文件:

localhost.2022-11-03.log ServletContext对象的log方法记录的日志信息存储到这个文件中。

也可以多传一个处理异常的参数!

  int age = 17; // 17岁// 当年龄小于18岁的时候,表示非法,记录日志if(age < 18) {application.log("对不起,您未成年,请绕行!", new RuntimeException("小屁孩,快走开,不适合你!"));}

(7)ServletContext对象还有另一个名字:应用域(后面还有其他域,例如:请求域、会话域)

如果所有的用户共享一份数据,并且这个数据很少的被修改,并且这个数据量很少,可以将这些数据放到ServletContext这个应用域中:

①为什么是所有用户共享的数据?

不是共享的没有意义。因为ServletContext这个对象只有一个。只有共享的数据放进去才有意义。

②为什么数据量要小?

因为数据量比较大的话,太占用堆内存,并且这个对象的生命周期比较长,服务器关闭的时候,这个对象才会被销毁。大数据量会影响服务器的性能。占用内存较小的数据量可以考虑放进去。

③为什么这些共享数据很少的修改,或者说几乎不修改?
所有用户共享的数据,如果涉及到修改操作,必然会存在线程并发所带来的安全问题。所以放在ServletContext对象中的数据一般都是只读的。数据量小、所有用户共享、又不修改,这样的数据放到ServletContext这个应用域当中,会大大提升效率。因为应用域相当于一个缓存,放到缓存中的数据,下次在用的时候,不需要从数据库中再次获取,大大提升执行效率。

(8)怎么向ServletContext应用域中存数据、取数据、删数据?

①存(怎么向ServletContext应用域中存数据)
        public void setAttribute(String name, Object value);
②取(怎么从ServletContext应用域中取数据)
        public Object getAttribute(String name); 
③删(怎么删除ServletContext应用域中的数据)
        public void removeAttribute(String name);

注:很像Map集合(key,value);分别对应着:map.put(k, v)方法、Object v = map.get(k)方法、map.remove(k)方法。

// 准备数据
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 向ServletContext应用域当中存储数据
application.setAttribute("nowDate",sdf.format(date));
// 取出来,输出到浏览器
Object nowDate = application.getAttribute("nowDate");
out.print(nowDate); // 2022-11-03 20:24:23
// 删除数据
application.removeAttribute("nowDate");
out.print(application.getRealPath("nowDate"));

总结

以后编写Servlet类的时候,实际上是不会去直接继承GenericServlet类的,因为B/S结构的系统是基于HTTP超文本传输协议的,在Servlet规范当中,提供了一个类叫做HttpServlet,它是专门为HTTP协议准备的一个Servlet类。编写的Servlet类要直接继承HttpServlet(HttpServlet是HTTP协议专用的)使用HttpServlet处理HTTP协议更便捷。但是需要知道它的继承结构:

jakarta.servlet.Servlet(接口)【爷爷】
jakarta.servlet.GenericServlet implements Servlet(抽象类)【儿子】
jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)【孙子】

三:补充缓冲机制

到目前为止都接触过的缓存机制!

  • 堆内存当中的字符串常量池

    • "abc" 先在字符串常量池中查找,如果有,直接拿来用。如果没有则新建,然后再放入字符串常量池。

  • 堆内存当中的整数型常量池

    • [-128 ~ 127] 一共256个Integer类型的引用,放在整数型常量池中。没有超出这个范围的话,直接从常量池中取。

  • 连接池(Connection Cache)

    • 这里所说的连接池中的连接是java语言连接数据库的连接对象:java.sql.Connection对象。

    • JVM是一个进程,MySQL数据库是一个进程。进程和进程之间建立连接,打开通道是很耗费资源的。怎么办?可以提前先创建好N个Connection连接对象,将连接对象放到一个集合当中,我们把这个放有Connection对象的集合称为连接池。每一次用户连接的时候不需要再新建连接对象,省去了新建的环节,直接从连接池中获取连接对象,大大提升访问效率。

    • 连接池

      • 设置最小连接数

      • 设置最大连接数

      • 连接池可以提高用户的访问效率。当然也可以保证数据库的安全性。

  • 线程池

    • Tomcat服务器本身就是支持多线程的。

    • Tomcat服务器是在用户发送一次请求,就新建一个Thread线程对象吗?

      • 当然不是,实际上是在Tomcat服务器启动的时候,会先创建好N多个线程Thread对象,然后将线程对象放到集合当中,称为线程池。用户发送请求过来之后,需要有一个对应的线程来处理这个请求,这个时候线程对象就会直接从线程池中拿,效率比较高。

      • 所有的WEB服务器,或者应用服务器,都是支持多线程的,都有线程池机制。

  • redis

    • 比如:NoSQL数据库、非关系型数据库、缓存数据库。

  • 向ServletContext应用域中存储数据,也等于是将数据存放到缓存cache当中。

Servlet | ServletConfig接口、ServletContext接口详解相关推荐

  1. 支付接口教程,详解支付宝接口(二)

    支付宝的接口向来集成过程都让人觉得比较舒服,只有APP支付相对复杂,但也只是配置上复杂一些,只要清楚原理相信也不是什么难事.下面是以前介绍双钥加密原理的传送门: 支付接口教程特别篇,公钥与私钥,双钥加 ...

  2. PHP支付接口教程,详解微信支付(二)

    PC扫码支付 扫码支付首先是要分清楚两种模式: [模式一]:商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号).[模式二]:商户后台系统调用微信 ...

  3. c# WebApi之接口返回类型详解

    c# WebApi之接口返回类型详解 https://blog.csdn.net/lwpoor123/article/details/78644998 转载于:https://www.cnblogs. ...

  4. python rpc_对python调用RPC接口的实例详解

    要调用RPC接口,python提供了一个框架grpc,这是google开源的 rpc相关文档: 需要安装的python包如下: 1.grpc安装 pip install grpcio 2.grpc的p ...

  5. (转)web.xml 中的listener、 filter、servlet 加载顺序及其详解

    转: https://www.cnblogs.com/Jeely/p/10762152.html web.xml 中的listener. filter.servlet 加载顺序及其详解 一.概述 1. ...

  6. java day29【DBC基本概念 、快速入门 、对JDBC中各个接口和类详解】

    第一章   JDBC 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 * JDBC本质:其实是官方(sun公司)定义的一套操作所有关系 ...

  7. 服务器和网页接口,WebApi架构详解,WebApi接口搭建与部署WebApi服务器

      WebApi架构详解,WebApi接口搭建与部署WebApi服务器 本文关键词:WebApi架构, WebApi接口搭建, WebApi部署 1. Api是什么? API(Application ...

  8. HUAWEI交换机的Hybrid接口(混杂模式)详解与实验配置演示

    前言: 本篇文章,本人结合自己所学以及上网查阅相关资料,总结出关于Hybrid接口的产生,作用,优点以及工作流程,附带与Cisco的比较.篇幅较长,还需读者耐心阅读:由于牵扯到过多的交换知识,但并不是 ...

  9. Android实战:CoolWeather酷欧天气(加强版数据接口)代码详解(上)

    -----------------------------------该文章代码已停更,可参考浩比天气(更新于2019/6/25)----------------------------------- ...

  10. VGA/DVI/HDMI/DP接口知识全详解

    VGA接口知识详解 VGA(Video Graphics Array)视频图形阵列,是IBM在1987年推出的一种视频传输标准,具有分辨率高.显示速率快.颜色丰富等优点,在彩色显示器领域得到了广泛的应 ...

最新文章

  1. Yahoo网站性能优化的34条规则
  2. python培训好学吗-Python爬虫培训好学吗?
  3. VTK:几何对象之ParametricSuperToroid
  4. 关于 XIB 和 NIB
  5. (9)How to take a picture of a black hole
  6. react学习(58)--this.props进行父子传值
  7. 数学建模overleaf模板_数学建模论文怎么写?快来pick最优万能模板,一文格式全搞定!...
  8. OSChina 周三乱弹 ——找女朋友都是双胞胎
  9. java过来emoji手机表情,mysql入库
  10. 基于BM1684移植YOLOV7
  11. MMKV的原理与实现(一)
  12. Ali,Tencent遭反垄断罚款!巨头们的蛮长时代要结束了?
  13. crh寄存器_牛人的STM32学习笔记(寄存器版本).doc
  14. vue自适应企业门户模板
  15. 什么是DDoS高防?
  16. Linux系统USB驱动目录,Linux那些事儿之我是USB 目录
  17. 静态图编程框架keras-学习心得以及知识点总结之keras的回调函数API
  18. 课表排班java_初学OptaPlanner-02- 基于Spring Boot实现一个简单课程表排班的实例
  19. html5+canvas+九宫格,HTML5+canvas一箭穿心
  20. 封装自己专属的真正的纯净版Windows系统过程记录(1)——封装环境准备

热门文章

  1. (算法篇)Java实现删除链表倒数第n个节点
  2. pynq 环境搭建_PYNQ系列学习(一): Pynq开发环境配置
  3. 解除Word文档保护方法汇总
  4. 消除Word文档被加密、限制编辑的解决方法
  5. RecyclerView添加表格分割线
  6. C:1134字符串转换
  7. 微软office即点即用服务能关闭吗?_技术贴:关于OFFICE各版本的下载安装卸载以及激活方法大全...
  8. 运用图像处理解决基于MRI的脑肿瘤图像分割问题
  9. 商汤科技发布新一代SensePass工业级可视人脸识别门禁全新升级
  10. 上海都有哪些牛逼的互联网公司?