GenericServlet
自己写的GenericServlet
让实现Servlet的GenericServlet 类变成适配器
类上加上abstract关键字
GenericServlet.java
/**
* GenericServlet 改造成适配器Adapter(把常用的方法(service()方法)变成抽象方法,让子类继承这个类,只实现抽象方法)
* 优点:子类代码变简介美观
*/
public abstract class GenericServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 抽象方法,这个方法最常用。要求子类必须实现service方法
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
子类LoginServlet .java
public class LoginServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("正在处理用户请求,请稍后。。。");
ServletConfig servletConfig = this.getServletConfig();
System.out.println("service方法中获取到ServletConfig对象:" + servletConfig);
}
}
改造GenericServlet
GenericServlet.java
/**
* GenericServlet 改造成适配器Adapter(把常用的方法(service()方法)变成抽象方法,让子类继承这个类,只实现抽象方法)
* 优点:子类代码变简介美观
*/
public abstract class GenericServlet implements Servlet {
// 成员变量
private ServletConfig servletConfig;
/**
* servletConfig 目前是局部对象,要想在service方法中使用,需要把他变成成员变量
* @param servletConfig Tomcat创建好的servletConfig对象
* @throws ServletException
*/
@Override
public final void init(ServletConfig servletConfig) throws ServletException { // 加final关键字防止init方法被子类重写
System.out.println("Tomcat创建好的servletConfig对象:" + servletConfig);
this.servletConfig = servletConfig;
//调用init()方法
this.init();
}
/**
* 这个init方法是供子类重写的
*/
public void init(){
}
@Override
public ServletConfig getServletConfig() {
return servletConfig;
}
/**
* 抽象方法,这个方法最常用。要求子类必须实现service方法
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
子类LoginServlet .java
public class LoginServlet extends GenericServlet {
// 重写init方法
@Override
public void init() {
System.out.println("重写的init方法执行");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("正在处理用户请求,请稍后。。。");
ServletConfig servletConfig = this.getServletConfig();
System.out.println("service方法中获取到ServletConfig对象:" + servletConfig);
}
}
GenericServlet源码
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final long serialVersionUID = 1L; // 固定序列化版本号,代码后续修改不会被认为是一个新类,便于维护
private transient ServletConfig config; // 添加transient关键字,表示不参与序列化
// 无参构造
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();
}
// 这个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();
}
}
ServletConfig
ServletConfig被称为Servlet的配置信息对象。
/**
* javax.servlet.GenericServlet
* GenericServlet是一个接口,由Tomcat服务器(web服务器)实现
* public class org.apache.catalina.core.StandardWrapperFacade implements ServletConfig {}
* 一个Servlet对象中有一个ServletConfig对象。1对1
*
* ServletConfig被称为Servlet的配置信息对象。
*
* ServletConfig对象中包装的信息:
* <servlet>
* <servlet-name>ConfigTestServlet</servlet-name>
* <servlet-class>cn.lwx.javaweb.servletconfig.ConfigTestServlet</servlet-class>
* <!--配置一个Servlet对象的初始化信息-->
* <init-param>
* <param-name>driver</param-name>
* <param-value>com.mysql.cj.jdbc.Driver</param-value>
* </init-param>
* <init-param>
* <param-name>url</param-name>
* <param-value>jdbc:mysql://localhost:3306/javawebtest</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>123456</param-value>
* </init-param>
* </servlet>
* Tomcat解析web.xml文件,将web.xml文件中<servlet></servlet>标签中的配置信息自动包装到ServletConfig对象中
*
* ServletConfig接口中的4个方法:在继承servlet类中也可以使用this调用
* 1. public String getInitParameter(String name);
* 2. public Enumeration<String> getInitParameterNames();
* 3. public ServletContext getServletContext();
* 4. public String getServletName();
* 以上4个方法可以获取ServletConfig对象调用,在继承servlet类中也可以使用this调用
*/
public class ConfigTestServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.setContentType("text/html");
PrintWriter out = servletResponse.getWriter();
// 获取ServletConfig对象
ServletConfig servletConfig = this.getServletConfig();
// 输出
// org.apache.catalina.core.StandardWrapperFacade@c091ed2
out.print("ServletConfig对象:" + servletConfig.toString());
out.print("<br>");
// 获取<servlet-name></servlet-name>
String servletName = servletConfig.getServletName();
out.print("<servlet-name>"+servletName+"</servlet-name>"); // ConfigTestServlet
out.print("<br>");
// 通过ServletConfig对象的两个方法,获取web.xml文件中的初始化参数配置信息
// java.util.Enumeration<java.lang.String> getInitParameterNames() 获取所有初始化参数的name
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
// 遍历集合
while (initParameterNames.hasMoreElements()) {
String parameterName = initParameterNames.nextElement();//取元素
String initParameter = servletConfig.getInitParameter(parameterName);
out.print(parameterName + "=" + initParameter);
out.print("<br>");
}
// java.lang.String getInitParameter(java.lang.String name) 通过初始化参数的name获取value
/*String driver = servletConfig.getInitParameter("driver");
out.print(driver); // com.mysql.cj.jdbc.Driver*/
// 实际上获取一个Servlet对象的初始化参数,可以不用获取ServletConfig对象,可以直接通过this,因为当前类继承了GenericServlet
Enumeration<String> initParameterNames1 = this.getInitParameterNames();
// 遍历集合
while (initParameterNames1.hasMoreElements()) {
String parameterName1 = initParameterNames1.nextElement();//取元素
String initParameter1 = this.getInitParameter(parameterName1);
out.print(parameterName1 + "=" + initParameter1);
out.print("<br>");
}
}
}
ServletContext
ServletContext被称为Servlet上下文对象,也叫应用域。如果所有的用户共享一份数据,这个数据很少被修改,数据量很小,可以将这些数据放到ServletContext这个应用域中,并且放在ServletContext对象中的数据一般都是只读的。
/**
* ServletContext是一个接口,由Tomcat服务器(web服务器)实现
* public class org.apache.catalina.core.ApplicationContextFacade implements ServletConfig {}
* 对于一个webapp来说,无论有多少个Servlet对象,ServletContext对象只有一个。多对一
* 一个ServletContext对象通常对应的是一个web.xml文件,即一个webapp。1对1
*
* ServletContext被称为Servlet上下文对象。
*
* ServletContext对象的生命周期:在服务器启动阶段创建,在服务器关闭的时候销毁。
* ServletContext对象是应用级对象
*
* ServletContext接口中的方法:
* 1. public String getInitParameter(String name); 通过初始化参数的name获取value
* 2. public Enumeration<String> getInitParameterNames(); 获取所有的初始化参数的name
* 3. public String getContextPath(); 动态获取应用的根路径
* 4. public String getRealPath(String path); 获取文件的绝对路径(真实路径)
* 5. public void log(String message);
* public void log(String message, Throwable t); 记录日志
* 6. public void setAttribute(String name, Object value); 向ServletContext应用域中存数据
* 7. public Object getAttribute(String name); 从ServletContext应用域中取数据
* 8. public void removeAttribute(String name); 删除ServletContext应用域中的数据
*/
public class ContextTestServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.setContentType("text/html");
PrintWriter out = servletResponse.getWriter();
// 获取ServletContext()对象
ServletContext application = this.getServletContext();
// org.apache.catalina.core.ApplicationContextFacade@c091ed2
out.print("ServletContext对象是:" + application + "<br>");
/* web.xml
<!--上下文初始化参数,可以通过servletContext获取-->
<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>
<!--注意:以上的配置信息属于应用级的配置信息,一般一个项目中共享的配置信息会放到以上的标签当中。-->
<!--如果你的配置信息只是想给某一个servlet作为参考,那么你配置到servlet标签当中即可,使用ServletConfig对象来获取。-->
*/
// 获取上下文的初始化参数
Enumeration<String> initParameterNames = application.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String name = initParameterNames.nextElement();
String value = application.getInitParameter(name);
out.print(name + "=" + value + "<br>");
}
// getContextPath()这个方法可以动态获取应用的根路径(非常重要)
String contextPath = application.getContextPath();
out.print(contextPath + "<br>");
// 获取文件的绝对路径
String realPath = application.getRealPath("/index.jsp"); // "/" 代表的是web的根
out.print(realPath + "<br>");
// 记录日志
// 在控制台的"CATALINA_BASE"后的文件目录能找到日志文件
application.log("Hello JavaWeb"); // 在 localhost.2022-05-12.log 里打印
// "CATALINA_BASE"后的文件目录中的日志文件
//catalina.2022-05-12.log 服务器端的java程序运行的控制台信息
//localhost.2022-05-12.log ServletContext对象的log方法记录的日志信息存储到这个文件中
//localhost_access_log.2022-05-12.txt 访问日志
}
}
注意
以后我们编写Servlet类的时候,实际上是不会去直接继承GenericServlet类的,因为我们是B/S结构的系统,这种系统是基于HTTP超文本传输协议的,在Servlet规范当中,提供了一个类叫做HttpServlet,它是专门为HTTP协议准备的一个Servlet类,我们编写的Servlet类要继承HttpServlet。
它们之间的继承结构:
- javax/jakarta.servlet.Servlet(接口)
- javax/jakarta.servlet.GenericServlet implements Servlet(抽象类)
- javax/jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)