文章目录
1. 前置知识
- 服务器启动时,servlet对象是否被创建出来?
package com.sdnu.javaweb;
import jakarta.servlet.*;
import java.io.IOException;
/**
* 实现servlet接口
*
* @author Beyong
* @date 2023/03/03 20:44
**/
public class AServlet implements Servlet {
public AServlet() {
System.out.println("A的无参构造方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
package com.sdnu.javaweb;
import jakarta.servlet.*;
import java.io.IOException;
/**
* 实现Servlet
*
* @author Beyong
* @date 2023/03/03 20:49
**/
public class BServlet implements Servlet {
public BServlet() {
System.out.println("B的无参构造方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
<?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.sdnu.javaweb.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.sdnu.javaweb.BServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bServlet</servlet-name>
<url-pattern>/b</url-pattern>
</servlet-mapping>
</web-app>
在控制台发现没有执行构造方法,说明服务器启动的时候,构造方法没有执行。
- 如何使得服务器启动的时候,创建servlet对象
在代码中添加
<load-on-startup>数字</load-on-startup>
数字越小,则优先级越高。
2.servlet生命周期
package com.sdnu.javaweb;
import jakarta.servlet.*;
import java.io.IOException;
/**
* 实现servlet接口
*
* @author Beyong
* @date 2023/03/03 20:44
**/
public class AServlet implements Servlet {
public AServlet() {
System.out.println("A的无参构造方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("AServlet'init method execute");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("AServlet'service method execute");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("AServlet'destroy method execute ");
}
}
2.1 默认情况下,服务器启动时,servlet对象并没有被创建
2.2 用户执行一次请求
结论:
- 用户在第一次请求的时候,Servlet对象被实例化,AServlet的构造方法被执行,并且执行的是无参构造。
- AServlet对象被创建出来后,AServlet马上执行init方法
- 第一次请求时,init方法执行后,马上执行service方法
2.3用户执行第二次请求
控制台输出:
AServlet’service method execute
2.4 3,4,5,6…次请求
后面的请求,Servlet对象并没有创建,而是使用之前的创建好的Servlet对象,调用该对象的方法。
-
servlet对象是单例的,但是servlet类不符合单例模式(假单例)。
-
无参构造方法只执行一次,init方法也只执行一次,即第一次。
-
只要用户发送请求,service必然执行。
2.5 关闭服务器
服务器在关闭前,执行servlet对象的destroy方法,destroy方法执行结束后,AServlet对象的才会被销毁,AServlet对象内存才会释放。
3.servlet方法解析
- 构造方法
javaweb不建议手动编写构造方法,因为手动编写构造方法容易导致错误,所以init方法很有必要。 - init
很少有,使用在初始化的时候,使用初始化数据连接池,线程池。 - service
一定要有,处理用户的请求。 - destroy
进行资源关闭。
4.适配器模式改造servlet
4.1不使用servlet模式
接口
package com.sdnu.javaweb.adapter;
/**
* 接口
* @author Beyong
* @date 2023/03/04 11:08
**/
public interface MyInterface {
void m1();
void m2();
void m3();
void m4();
void m5();
void m6();
void m7();
void core();
}
UserService:
package com.sdnu.javaweb.adapter;
/**
* 用户
*
* @author Beyong
* @date 2023/03/04 11:10
**/
public class UserService implements MyInterface{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
@Override
public void m5() {
}
@Override
public void m6() {
}
@Override
public void m7() {
}
@Override
public void core() {
System.out.println("UserService'core method execute!!!");
}
}
CustomerService:
package com.sdnu.javaweb.adapter;
/**
* CustomerService
*
* @author Beyong
* @date 2023/03/04 11:13
**/
public class CustomerService implements MyInterface{
@Override
public void m1() {
}
@Override
public void m2() {
System.out.println("Customer'm2 method execute");
}
@Override
public void m3() {
}
@Override
public void m4() {
}
@Override
public void m5() {
}
@Override
public void m6() {
}
@Override
public void m7() {
}
@Override
public void core() {
}
}
不使用适配器模式下,则代码每一个service都要取实现接口。
4.2使用适配器模式
接口:
package com.sdnu.javaweb.adapter2;
/**
* 接口
* @author Beyong
* @date 2023/03/04 11:24
**/
public interface MyInterface {
void m1();
void m2();
void m3();
void m4();
void m5();
void m6();
void m7();
void core();
}
用户适配器:
package com.sdnu.javaweb.adapter2;
/**
* UserService适配器
*
* @author Beyong
* @date 2023/03/04 11:26
**/
public abstract class UserAdapter implements MyInterface{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
@Override
public void m5() {
}
@Override
public void m6() {
}
@Override
public void m7() {
}
public abstract void core();
}
顾客适配器:
package com.sdnu.javaweb.adapter2;
/**
* 客户适配器
*
* @author Beyong
* @date 2023/03/04 11:28
**/
public abstract class CustomerAdapter implements MyInterface{
public abstract void m1();
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
@Override
public void m5() {
}
@Override
public void m6() {
}
@Override
public void m7() {
}
@Override
public void core() {
}
}
用户:
package com.sdnu.javaweb.adapter2;
/**
* 普通用户
*
* @author Beyong
* @date 2023/03/04 11:34
**/
public class UserService extends UserAdapter{
@Override
public void core() {
}
}
顾客:
package com.sdnu.javaweb.adapter2;
/**
* 顾客
*
* @author Beyong
* @date 2023/03/04 11:35
**/
public class CustomerService extends CustomerAdapter{
@Override
public void m1() {
}
}
5.GenericServlet
我们写一个通用的GenericServlet
package com.sdnu.javaweb.servlet;
import jakarta.servlet.*;
import java.io.IOException;
/**
* servlet适配器
*
* @author Beyong
* @date 2023/03/04 11:48
**/
public abstract class GenericServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse);
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
LoginServlet
package com.sdnu.javaweb.servlet;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
/**
* c的servlet
*
* @author Beyong
* @date 2023/03/04 11:49
**/
public class LoginServlet extends GenericServlet{
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) {
System.out.println("c'service method execute");
}
}
web.xml
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.sdnu.javaweb.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
地址:http://127.0.0.1:8080/lifecycle/login
进一步改造:
package com.sdnu.javaweb.servlet;
import jakarta.servlet.*;
import java.io.IOException;
/**
* servlet适配器
*
* @author Beyong
* @date 2023/03/04 11:48
**/
public abstract class GenericServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
/**
* 这个init方法供子类重写
*/
public void init(){
}
@Override
public ServletConfig getServletConfig() {
return null;
}
public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
6.ServletConfig详解
- 什么是ServletConfig
ServletConfig是Servlet规范中的一员。 - Tomcat实现了ServletConfig接口
- 一个Servlet对应一个ServletConfig
- Servlet对象是Tomcat创建的,同时创建了ServletConfig.
- 创建一个Servelt对象,就有一个ServletConfig(Servlet对象信息)。
- Tomcat解析web.xml文件,将web.xml文件中
<servlet></servlet>
标签中的配置信息自动包装到ServletConfig对象中去。
- ServletConfjg有哪些方法?
getInitParameterNames
getInitParameter
package com.sdnu.javaweb.servlet;
import jakarta.servlet.*;
import sun.plugin2.util.ParameterNames;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
/**
* servletConfig测试2
*
* @author Beyong
* @date 2023/03/06 13:05
**/
public class ConfigServletTest2 extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.setContentType("text/html");
PrintWriter out = servletResponse.getWriter();
ServletConfig config = this.getServletConfig();
out.print("servletConfig对象是:" + config.toString());
out.print("</br>");
String servletName = config.getServletName();
out.print("<servlet>" + servletName + "</servlet>");
out.print("</br>");
Enumeration<String> initParameterNames = config.getInitParameterNames();
while(initParameterNames.hasMoreElements()){
String parameterName = initParameterNames.nextElement();
String parameterVal = config.getInitParameter(parameterName);
out.print(parameterName + "=" + parameterVal);
out.print("<br>");
}
String driver = config.getInitParameter("driver");
out.print(driver);
// Enumeration<String> names = this.getInitParameterNames();
// while(names.hasMoreElements()){
// String name = names.nextElement();
// String value = this.getInitParameter(name);
// out.print(name + " = " + value);
// out.print("<br>");
// }
}
}
<?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.sdnu.javaweb.servlet.ConfigServletTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>configTest</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>configTest2</servlet-name>
<servlet-class>com.sdnu.javaweb.servlet.ConfigServletTest2</servlet-class>
<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/sdnu</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>root123</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>configTest2</servlet-name>
<url-pattern>/test2</url-pattern>
</servlet-mapping>
</web-app>
7.ServletConfig接口有四个方法
- public String getInitParameter(String name);
- public Enumeration getInitParameterNames();
- public ServletContext getServletContext();
- public String getServletName();
以上四个方法可以在自己编写的Servlet类中使用this调用,这个Servlet继承了GenericServlet
8.ServletContext
- ServletContext是接口,是Servlet规范的一员。
- Tomcat实现了ServletContext接口。
- ServletContext是服务器创建的,在服务器启动的时候创建,在服务器关闭的时候销毁,对于一个WebApp来说,ServletContext只有一个。
- ServletContext对象对应整个web.xml。
- ServletContext接口的方法:
(1)
Enumeration<String> initParameterNames = application.getInitParameterNames();
String value = application.getInitParameter(name);
以上两个方法获取context-param标签中的name和value
<context-param>
<param-name>startIndex</param-name>
<param-value>2</param-value>
</context-param>
(2获取应用的根路径
String contextPath = application.getContextPath();
(3)获取文件的绝对路径
public String getRealPath(String path)
(4)访问日志
public void log(String message);
public void log(String message, Throwable t);
Tomcat服务器的Log目录下都有哪些日志信息?
catalina.2023-02-28.log 服务器的java程序运行的控制信息
localhost.2023-03-07.log ServletContext对象的log方法记录的日志存储到这个文件中
localhost_access_log.2023-02-28.txt 访问日志
- ServletContext又叫应用域,放到ServletContext中的数据一般是数据量小,所以用户共享的,不经常修改的。
存:public void setAttribute(String name, Object value);
取:public void getAttribute(String name);
删:public void removeAttribute(String name);
User user = new User("jack", "123456");
application.setAttribute("UserObj", user);
Object userObj = application.getAttribute("UserObj");
out.print(userObj);
out.print("</br>");
9.HttpServlet
jakarta.servlet.Servlet 【接口】
jakarta.servlet.GenericServlet implements Servlet 【抽象类】
jakarta.servlet.http.HttpServlet extends GenericServlet 【类】
以后编写程序继承HttpServlet
作者:Beyong
出处:Beyong博客
github地址:https://github.com/beyong2019
本博客中未标明转载的文章归作者Beyong有,欢迎转载,但未经作者同意必须保留此段声明,且在文章明显位置给出原文连接,否则保留追究法律责任的权利。