[Java]JavaWeb学习笔记(动力节点老杜2022)

news2025/1/16 0:43:37

文章目录

  • 🥽 Tomcat服务器
    • 🌊 下载与安装
    • 🌊 关于Tomcat服务器的目录
    • 🌊 启动Tomcat
    • 🌊 实现一个最基本的web应用(这个web应用中没有java小程序)
  • 🥽 静态资源与动态资源
  • 🥽 模拟Servlet本质
  • 🥽 Servlet规范
  • 🥽 开发一个带有Servlet(Java小程序)的webapp(重点)
  • 🥽 关于JavaEE的版本
  • 🥽 解决Tomcat服务器在DOS命令窗口中的乱码问题(控制台乱码)
  • 🥽 向客户端相应内容
  • 🥽 在Servlet中连接数据库
  • 🥽 在集成开发环境当中开发Servlet程序
  • 🥽 Servlet对象的生命周期
  • 🥽 适配器设计模式Adapter实现Servlet接口


🥽 Tomcat服务器

🌊 下载与安装

【Tomcat服务器版本与支持Java版本的对应关系:https://tomcat.apache.org/whichversion.html】

在这里插入图片描述

【Tomcat官网下载地址:https://tomcat.apache.org/download-10.cgi】

在这里插入图片描述

下载完成后,直接选择合适的位置将下载的压缩包解压即可,解压就是安装。

🌊 关于Tomcat服务器的目录

  • bin : 这个目录是Tomcat服务器的命令文件存放的目录,比如:启动Tomcat,关闭Tomcat等。
  • conf: 这个目录是Tomcat服务器的配置文件存放目录。(server.xml文件中可以配置端口号,默认Tomcat端口是8080)
  • lib :这个目录是Tomcat服务器的核心程序目录,因为Tomcat服务器是Java语言编写的,这里的jar包里面都是class文件。
  • logs: Tomcat服务器的日志目录,Tomcat服务器启动等信息都会在这个目录下生成日志文件。
  • temp:Tomcat服务器的临时目录。存储临时文件。
  • webapps:这个目录当中就是用来存放大量的webapp(web application:web应用)
  • work:这个目录是用来存放JSP文件翻译之后的java文件以及编译之后的class文件。

🌊 启动Tomcat

  • bin目录下有一个文件:startup.bat,通过它可以启动Tomcat服务器。
    • xxx.bat文件是个什么文件?bat文件是windows操作系统专用的,bat文件是批处理文件,这种文件中可以编写大量的windows的dos命令,然后执行bat文件就相当于批量的执行dos命令。
    • startup.sh,这个文件在windows当中无法执行,在Linux环境当中可以使用。在Linux环境下能够执行的是shell命令,大量的shell命令编写在shell文件当中,然后执行这个shell文件可以批量的执行shell命令。
    • tomcat服务器提供了bat和sh文件,说明了这个tomcat服务器的通用性。
    • 分析startup.bat文件得出,执行这个文件,实际上最后是执行:catalina.bat文件。
      在这里插入图片描述
    • catalina.bat文件中有这样一行配置:MAINCLASS=org.apache.catalina.startup.Bootstrap (这个类就是main方法所在的类。)
      在这里插入图片描述
    • tomcat服务器就是Java语言写的,既然是java语言写的,那么启动Tomcat服务器就是执行main方法。
  • 我们尝试打开dos命令窗口,在dos命令窗口中输入startup.bat来启动tomcat服务器。
  • 启动Tomcat服务器只配置path对应的bin目录是不行的。有两个环境变量需要配置:
    • JAVA_HOME=JDK的根,在任何位置都可以找到Java运行Java程序
    • CATALINA_HOME=Tomcat服务器的根,在任何位置都可以找到Tomcat运行Tomcat服务器
      在这里插入图片描述
  • 配置Tomcat服务器需要哪些环境变量?
    • JAVA_HOME=JDK的根
    • CATALINA_HOME=Tomcat服务器的根
    • PATH=%JAVA_HOME%\bin%CATALINA_HOME%\bin,在任何位置可以找到相应的可执行文件
      在这里插入图片描述
  • 启动Tomcat: startup
    在这里插入图片描述
  • 关闭Tomcat:stop (shutdown.bat文件重命名为stop.bat,为什么?原因是shutdown命令和windows中的关机命令冲突。所以修改一下。)
    在这里插入图片描述
  • 怎么测试Tomcat服务器有没有启动成功呢?
    • 打开浏览器,在浏览器的地址栏上输入URL即可:
      • http://ip地址:端口号
      • ip地址是什么?端口号知道,是8080
      • 本机的IP地址是:127.0.0.1,或者是localhost,都行。

在这里插入图片描述

🌊 实现一个最基本的web应用(这个web应用中没有java小程序)

  • 第一步:找到CATALINA_HOME\webapps目录
    • 因为所有的webapp要放到webapps目录下。(没有为什么,这是Tomcat服务器的要求。如果不放到这里,Tomcat服务器找不到你的应用。)
  • 第二步:在CATALINA_HOME\webapps目录下新建一个子目录,起名:oa
    • 这个目录名oa就是你这个webapp的名字。
      在这里插入图片描述
  • 第三步:在oa目录下新建资源文件,例如:index.html
    • 编写index.html文件的内容。
      在这里插入图片描述
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
      </html>
      
  • 第四步:启动Tomcat服务器
    在这里插入图片描述
  • 第五步:打开浏览器,在浏览器地址栏上输入这样的URL:http://ip地址:端口号/webapp名/资源文件名 http://127.0.0.1:8080/oa/index.html
    在这里插入图片描述
  • 思考一个问题:
    • 我们在浏览器上直接输入一个URL,然后回车。这个动作和超链接一样吗?既然是一样的,我们完全可以使用超链接。

      <!--注意以下的路径,以/开始,带项目名,是一个绝对路径。不需要添加:http://127.0.0.1:8080,即 / 表示http://127.0.0.1:8080-->
      <a href="/oa/login.html">user login2</a>
      
      <!--多个层级也没有关系,正常访问即可。-->
      <!--注意:我们目前前端上的路径都以“/”开始的,都是加项目名的-->
      <a href="/oa/test/debug/d.html">d page</a>
      

🥽 静态资源与动态资源

  • http://127.0.0.1:8080/oa/userList.html
    在这里插入图片描述
    • 访问这个地址,可以展示一个用户列表页面。但是这个用户列表页面是写死在HTML文件当中的。这种资源我们称为静态资源。怎么能变成动态资源。显然需要连接数据库。
    • 连接数据库需要JDBC程序,也就是说需要编写Java程序连接数据库,数据库中有多少条记录,页面上就显示多少条记录,这种技术被称为动态网页技术。(动态网页技术并不是说页面中有flash动画。动态网页技术是说页面中的数据是动态的,根据数据库中数据的变化而变化。)
      在这里插入图片描述
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
      </head>
      <body>
        <table>
          <thead>
            <th>no</th>
            <th>username</th>
          </thead>
          <tbody>
            <tr>
              <td>1</td>
              <td>Tom</td>
            </tr>
            <tr>
              <td>2</td>
              <td>Michile</td>
            </tr>
            <tr>
              <td>3</td>
              <td>Jane</td>
            </tr>
            <tr>
              <td>4</td>
              <td>Marry</td>
            </tr>
            <tr>
              <td>5</td>
              <td>Jack</td>
            </tr>
          </tbody>
        </table>
      </body>
      </html>
      
  • 对于一个动态的web应用来说,一个请求和响应的过程有多少个角色参与,角色和角色之间有多少个协议
    在这里插入图片描述
    • 有哪些角色(在整个BS结构的系统当中,有哪些人参与进去了)
      • 浏览器软件的开发团队(浏览器软件太多了:谷歌浏览器、火狐浏览器、IE浏览器…)
      • WEB Server的开发团队(WEB Server这个软件也是太多了:Tomcat、Jetty、WebLogic、JBOSS、WebSphere…)
      • DB Server的开发团队(DB Server这个软件也是太多了:Oracle、MySQL…)
      • webapp的开发团队(WEB应用是我们做为JavaWEB程序员开发的)
    • 角色和角色之间需要遵守哪些规范,哪些协议
      • webapp的开发团队 和 WEB Server的开发团队 之间有一套规范: JavaEE规范之一Servlet规范。
        • Servlet规范的作用是什么?
          • WEB Server 和 webapp解耦合。
      • Browser 和 WebServer之间有一套传输协议:HTTP协议。(超文本传输协议。)
      • webapp开发团队 和 DB Server的开发团队之间有一套规范:JDBC规范。
        在这里插入图片描述

🥽 模拟Servlet本质

  • 充当SUN公司的角色,制定Servlet规范,javax.servlet.Servlet接口,Webapp的开发者编写的Servlet类都要实现该接口

    package javax.servlet;
    
    /*
    	我们现在充当的角色时SUN公司
    	SUN公司把Servlet接口/规范制定出来
    */
    public interface Servlet{
    
    	// 一个专门提供服务的方法
    	void service();
    }
    
  • 充当Tomcat服务器的开发者

    package org.apache;
    
    import java.util.Scanner;
    import java.util.Properties;
    import java.io.FileReader;
    import javax.servlet.Servlet;
    
    // 充当Tomcat服务器的开发者
    public class Tomcat{
    	public static void main(String[] args) throws Exception{
    		System.out.println("Tomcat服务器启动成功,开始接收用户的访问。");
    
    		// 简单的使用Scanner来模拟一下用户的请求
    		// 用户访问服务器是通过浏览器上的“请求路径”
    		// 也就是说用户请求路径不同,后台执行的Servlet不同。
    		/*
    			/userList    UserListServlet
    			/login		 UserLoginServlet
    			/bank		 BankServlet
    			......
    		*/
    		System.out.print("请输入您的访问路径:");
    		Scanner s = new Scanner(System.in);
    
    		// 用户的请求路径  /bbbb
    		String key = s.nextLine(); // Tomcat服务器已经获取到了用户的请求路径了。
    
    		// Tomcat服务器应该通过用户的请求路径找对应的XXXServlet
    		// 请求路径和XXXServlet之间的关系应该由谁指定呢?
    		// 对于Tomcat服务器来说需要解析配置文件
    		FileReader reader = new FileReader("web.properties");
    		Properties pro = new Properties();
    		pro.load(reader);
    		reader.close();
    
    		// 通过key获取value
    		String className = pro.getProperty(key);
    		// 通过反射机制创建对象
    		Class clazz = Class.forName(className);
    		Object obj = clazz.newInstance(); // obj的类型对于Tomcat服务器开发人员来说不知道。
    		
    		// 但是Tomcat服务器的开发者知道,你写的XXXXServlet一定实现了Servlet接口
    		Servlet servlet = (Servlet)obj;
    		servlet.service();
    
    	}
    }
    
  • 充当Webapp的开发者

    • BankServlet implements Servlet

      package com.bjpowernode.servlet;
      
      import javax.servlet.Servlet;
      
      // 充当的角色发生了改变:webapp开发者
      // 只要是我们webapp开发者写的XXXServlet都要实现Servlet接口
      public class BankServlet implements Servlet{
      	public void service(){
      		System.out.println("BankServlet's service...");
      	}
      }
      
    • UserListServlet implements Servlet

      package com.bjpowernode.servlet;
      
      import javax.servlet.Servlet;
      
      // 充当的角色发生了改变:webapp开发者
      
      public class UserListServlet implements Servlet{
      	public void service(){
      		System.out.println("UserListServlet's service...");
      	}
      }
      
    • UserLoginServlet implements Servlet

      package com.bjpowernode.servlet;
      
      import javax.servlet.Servlet;
      
      // 充当的角色发生了改变:webapp开发者
      
      public class UserLoginServlet implements Servlet{
      	public void service(){
      		System.out.println("UserLoginServlet's service...");
      	}
      }
      
    • 编写配置文件,请求资源路径和相应Servlet类的对应关系有配置文件给出

      /aaaa=com.bjpowernode.servlet.UserListServlet
      /bbbb=com.bjpowernode.servlet.UserLoginServlet
      /cccc=com.bjpowernode.servlet.BankServlet
      
  • 通过分析,对于我们javaweb程序员来说,我们只需要做两件事,(1)编写一个类实现Servlet接口;(2)将编写的类配置到配置文件中,在配置文件中:指定 请求路径 和 类名 的关系。

  • 注意:

    • 这个配置文件的文件名不能乱来。固定的。

    • 这个配置文件的存放路径不能乱来。固定的。

    • 文件名、文件路径都是SUN公司制定的Servlet规范中的明细。

      // 从该段代码可以看出
      FileReader reader = new FileReader("web.properties");
      Properties pro = new Properties();
      pro.load(reader);
      reader.close();
      
  • 严格意义上来说Servlet其实并不是简单的一个接口:

    • Servlet规范中规定了:
      • 一个合格的webapp应该是一个怎样的目录结构。
      • 一个合格的webapp应该有一个怎样的配置文件。
      • 一个合格的webapp配置文件路径放在哪里。
      • 一个合格的webapp中java程序放在哪里。
      • 这些都是Servlet规范中规定的。
  • Tomcat服务器要遵循Servlet规范。JavaWEB程序员也要遵循这个Servlet规范。这样Tomcat服务器和webapp才能解耦合。

🥽 Servlet规范

  • 遵循Servlet规范的webapp,这个webapp就可以放在不同的WEB服务器中运行。(因为这个webapp是遵循Servlet规范的。)
  • Servlet规范包括什么呢?
    • 规范了哪些接口
    • 规范了哪些类
    • 规范了一个web应用中应该有哪些配置文件
    • 规范了一个web应用中配置文件的名字
    • 规范了一个web应用中配置文件存放的路径
    • 规范了一个web应用中配置文件的内容
    • 规范了一个合法有效的web应用它的目录结构应该是怎样的。

🥽 开发一个带有Servlet(Java小程序)的webapp(重点)

  • 开发步骤是怎样的?
    • 第一步:在webapps目录下新建一个目录,起名crm(这个crm就是webapp的名字)。当然,也可以是其它项目,比如银行项目,可以创建一个目录bank,办公系统可以创建一个oa。

      • 注意:crm就是这个webapp的根
        在这里插入图片描述
    • 第二步:在webapp的根下新建一个目录:WEB-INF

      • 注意:这个目录的名字是Servlet规范中规定的,必须全部大写,必须一模一样。必须的必须。
        在这里插入图片描述
    • 第三步:在WEB-INF目录下新建一个目录:classes

      • 注意:这个目录的名字必须是全部小写的classes。这也是Servlet规范中规定的。另外这个目录下一定存放的是Java程序编译之后的class文件(这里存放的是字节码文件)。
        在这里插入图片描述
    • 第四步:在WEB-INF目录下新建一个目录:lib

      • 注意:这个目录不是必须的。但如果一个webapp需要第三方的jar包的话,这个jar包要放到这个lib目录下,这个目录的名字也不能随意编写,必须是全部小写的lib。例如java语言连接数据库需要数据库的驱动jar包。那么这个jar包就一定要放到lib目录下。这Servlet规范中规定的。
        在这里插入图片描述
    • 第五步:在WEB-INF目录下新建一个文件:web.xml

      • 注意:这个文件是必须的,这个文件名必须叫做web.xml。这个文件必须放在这里。一个合法的webapp,web.xml文件是必须的,这个web.xml文件就是一个配置文件,在这个配置文件中描述了请求路径和Servlet类之间的对照关系。
        在这里插入图片描述
      • 这个文件最好从其他的webapp中拷贝,最好别手写。没必要。复制粘贴
      • <?xml version="1.0" encoding="UTF-8"?>
        
        <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                              https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
          version="5.0"
          metadata-complete="true">
        
        
        </web-app>
        
        

      在这里插入图片描述

    • 第六步:编写一个Java程序,这个小Java程序也不能随意开发,这个小java程序必须实现Servlet接口。

      • 这个Servlet接口不在JDK当中。(因为Servlet不是JavaSE了。Servlet属于JavaEE,是另外的一套类库。)
      • Servlet接口(Servlet.class文件)是Oracle提供的。(最原始的是sun公司提供的。)
      • Servlet接口是JavaEE的规范中的一员。
      • Tomcat服务器实现了Servlet规范,所以Tomcat服务器也需要使用Servlet接口。Tomcat服务器中应该有这个接口,Tomcat服务器的CATALINA_HOME\lib目录下有一个servlet-api.jar,解压这个servlet-api.jar之后,你会看到里面有一个Servlet.class文件。
        在这里插入图片描述
        在这里插入图片描述
      • 重点:从JakartaEE9开始,Servlet接口的全名变了:jakarta.servlet.Servlet
      • 注意:编写这个Java小程序的时候,java源代码你愿意在哪里就在哪里,位置无所谓,你只需要将java源代码编译之后的class文件放到classes目录下即可
    • 第七步:编译我们编写的HelloServlet

      package com.bjpowernode.servlet;
      
      // 在Tomcat9以及Tomcat9之前的版本中使用javax.servlet这个包
      import jakarta.servlet.Servlet;
      import jakarta.servlet.ServletException;
      import jakarta.servlet.ServletRequest;
      import jakarta.servlet.ServletResponse;
      import jakarta.servlet.ServletConfig;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      
      public class HelloServlet implements Servlet{
      
      	// 5个方法
      	public void init(ServletConfig config) throws ServletException{
      	
      	}
      
      	public void service(ServletRequest request,ServletResponse response)
      		throws ServletException , IOException{
      
      		// 向控制台打印输出
      		System.out.println("My First Servlet, Hello Servlet");
      		
      	}
      
      	public void destroy(){
      	
      	}
      
      	public String getServletInfo(){
      		return "";
      	}
      
      	public ServletConfig getServletConfig(){
      		return null;
      	}
      }
      
      • 重点:你怎么能让你的HelloServlet编译通过呢?配置环境变量CLASSPATH CLASSPATH=.;C:\dev\apache-tomcat-10.0.12\lib\servlet-api.jar
        在这里插入图片描述
      • 思考问题:以上配置的CLASSPATH和Tomcat服务器运行有没有关系?
        • 没有任何关系,以上配置这个环境变量只是为了让你的HelloServlet能够正常编译生成class文件。
    • 第八步:将以上编译之后的HelloServlet.class文件拷贝到WEB-INF\classes目录下。
      javac -d . HelloServlet.java
      在这里插入图片描述
      在这里插入图片描述

    • 第九步:在web.xml文件中编写配置信息,让“请求路径”和“Servlet类名”关联在一起。

      • 这一步用专业术语描述:在web.xml文件中注册Servlet类。
      • 可能会由于xml配置文件中的注释信息导致Tomcat启动报错,可以将xml配置文件中的注释信息删除
      • <?xml version="1.0" encoding="UTF-8"?>
        
        <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                              https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
          version="5.0"
          metadata-complete="true">
        
        	<!--servlet描述信息-->
        	<!--任何一个servlet都对应一个servlet-mapping -->
        	<servlet>
        		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
        		<!--这个位置必须是带有包名的全限定类名-->
        		<servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
        	</servlet>
        
        	<!--servlet映射信息-->
        	<servlet-mapping>
        		<!--这个也是随便的,不过这里写的内容要和上面的一样。-->
        		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
        		<!--这里需要一个路径-->
        		<!--这个路径唯一的要求是必须以 / 开始-->
        		<!--当前这个路径可以随便写-->
        		<url-pattern>/fdsa/fd/saf/d/sa/fd/sa/fd</url-pattern>
        	</servlet-mapping>
        	
        </web-app>
        
        
    • 第十步:启动Tomcat服务器
      在这里插入图片描述

    • 第十一步:打开浏览器,在浏览器地址栏上输入一个url,这个URL必须是:

      • http://127.0.0.1:8080/crm/fdsa/fd/saf/d/sa/fd/sa/fd
        在这里插入图片描述
      • 启动Tomcat服务器之后,Tomcat会监听ip地址表示的主机的8080端口,crm表示访问部署在Tomcat服务器上的crm项目,fdsa/fd/saf/d/sa/fd/sa/fd表示访问的项目资源路径
      • 非常重要的一件事:浏览器上的请求路径不能随便写,这个请求路径必须和web.xml文件中的url-pattern一致
      • 注意:浏览器上的请求路径和web.xml文件中的url-pattern的唯一区别就是:浏览器上的请求路径带项目名:/crm
    • 浏览器上编写的路径太复杂,可以使用超链接。(非常重要:html页面只能放到WEB-INF目录外面。

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta http-equiv="X-UA-Compatible" content="IE=edge" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>Document</title>
        </head>
        <body>
          <a href="/crm/fdsa/fd/saf/d/sa/fd/sa/fd">HelloServelet</a>
        </body>
      </html>
      

      在这里插入图片描述
      在这里插入图片描述

    • 以后不需要我们编写main方法了。tomcat服务器负责调用main方法,Tomcat服务器启动的时候执行的就是main方法。我们javaweb程序员只需要编写Servlet接口的实现类,然后将其注册到web.xml文件中,即可。

    • 总结一下:一个合法的webapp目录结构应该是怎样的?

      webapproot
           |------WEB-INF
           		  |------classes(存放字节码)
           		  |------lib(第三方jar包)
           		  |------web.xml(注册Servlet)
           |------html
           |------css
           |------javascript
           |------image
           ....
      
    • 浏览器发送请求,到最终服务器调用Servlet中的方法,是怎样的一个过程?(以下这个过程描述的很粗糙。其中还有很多步骤我省略了。)

      • 用户输入URL,或者直接点击超链接:http://127.0.0.1:8080/crm/fdsa/fd/saf/d/sa/fd/sa/fd
      • 然后Tomcat服务器接收到请求,截取路径:/crm/fdsa/fd/saf/d/sa/fd/sa/fd
      • Tomcat服务器找到crm项目
      • Tomcat服务器在web.xml文件中查找/fdsa/fd/saf/d/sa/fd/sa/fd 对应的Servlet是:com.bjpowernode.servlet.HelloServlet
      • Tomcat服务器通过反射机制,创建com.bjpowernode.servlet.HelloServlet的对象。
      • Tomcat服务器调用com.bjpowernode.servlet.HelloServlet对象的service方法。

🥽 关于JavaEE的版本

  • JavaEE目前最高版本是 JavaEE8
  • JavaEE被Oracle捐献了,Oracle将JavaEE规范捐献给Apache了。
  • Apache把JavaEE换名了,以后不叫JavaEE了,以后叫做 jakarta EE。
  • 以后没有JavaEE了。以后都叫做Jakarta EE。
  • JavaEE8版本升级之后的"JavaEE 9",不再是"JavaEE9"这个名字了,叫做JakartaEE9
  • JavaEE8的时候对应的Servlet类名是:javax.servlet.Servlet
  • JakartaEE9的时候对应的Servlet类名是:jakarta.servlet.Servlet (包名都换了)
  • 如果你之前的项目还是在使用javax.servlet.Servlet,那么你的项目无法直接部署到Tomcat10+版本上。你只能部署到Tomcat9-版本上。在Tomcat9以及Tomcat9之前的版本中还是能够识别javax.servlet这个包。
  • 官方为版本的切换提供了迁移工具,【This will almost certainly require code changes to enable applications to migrate from Tomcat 9 and earlier to Tomcat 10 and later. A migration tool has been developed to aid this process.】
  • Tomcat 10版本对应的Servlet文档
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

🥽 解决Tomcat服务器在DOS命令窗口中的乱码问题(控制台乱码)

将CATALINA_HOME/conf/logging.properties文件中的内容修改如下:

// Windows DOS命令窗口的编码为GBK
java.util.logging.ConsoleHandler.encoding = GBK

🥽 向客户端相应内容

package com.bjpowernode.servlet;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletConfig;
import java.io.IOException;
import java.io.PrintWriter;


public class HelloServlet implements Servlet{

	// 5个方法
	public void init(ServletConfig config) throws ServletException{
	
	}

	public void service(ServletRequest request,ServletResponse response)
		throws ServletException , IOException{

		// 向控制台打印输出
		System.out.println("My First Servlet, Hello Servlet");

		// 设置响应的内容类型是普通文本或html代码
		// 需要在获取流对象之前设置,有效。
		// 响应到浏览器出现中文乱码,可以指定字符集text/html;charset=UTF-8
		response.setContentType("text/html");

		// 怎么将一个信息直接输出到浏览器上?
		// 需要使用ServletResponse接口:response
		// response表示响应:从服务器向浏览器发送数据叫做响应。
		PrintWriter out = response.getWriter();
		
		// 设置响应的内容类型时不要在获取流之后设置。
		//response.setContentType("text/html");

		out.print("Hello Servlet, You are my first servlet!");

		// 浏览器是能够识别html代码的,那我们是不是应该输出一段HTML代码呢?
		out.print("<h1>hello servlet,你好Servlet</h1>");

		// 这是一个输出流,负责输出字符串到浏览器
		// 这个输出流不需要我们刷新,也不需要我们关闭,这些都由Tomcat来维护。
		/*
		out.flush();
		out.close();
		*/
	}

	public void destroy(){
	
	}

	public String getServletInfo(){
		return "";
	}

	public ServletConfig getServletConfig(){
		return null;
	}
}

在这里插入图片描述

🥽 在Servlet中连接数据库

Servlet是Java程序,所以在Servlet中完全可以编写JDBC代码连接数据库。

在一个webapp中去连接数据库,需要将驱动jar包放到WEB-INF/lib目录下。(com.mysql.cj.jdbc.Driver 这个类就在驱动jar包当中。)

注册驱动,新版本中建议使用com.mysql.cj.jdbc.Driver,com.mysql.jdbc.Driver已过时。(对应Mysql的版本为8.0+)

package com.bjpowernode.servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.ServletConfig;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;


public class StudentServlet implements Servlet{

	public void init(ServletConfig config) throws ServletException{
	
	}

	public void service(ServletRequest request,ServletResponse response)
		throws ServletException , IOException{
		
		// 响应到浏览器出现中文乱码,可以指定字符集text/html;charset=UTF-8
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();

		// 编写JDBC代码,连接数据库,查询所有学生信息。
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try{
			// 注册驱动 (com.mysql.jdbc.Driver,这个已过时。)
			// 新版本中建议使用:com.mysql.cj.jdbc.Driver驱动。
			Class.forName("com.mysql.cj.jdbc.Driver");
			// 获取连接
			String url = "jdbc:mysql://localhost:3306/mydatabase";
			String user = "root";
			String password = "123456";
			conn = DriverManager.getConnection(url,user,password);
			// 获取预编译的数据库操作对象
			String sql = "select id,name from account";
			ps = conn.prepareStatement(sql);
			// 执行SQL
			rs = ps.executeQuery();
			// 处理查询结果集
			while(rs.next()){
				String no = rs.getString("id");
				String name = rs.getString("name");
				//System.out.println(no + "," + name);
				out.print(no + "," + name + "<br>");
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// 释放资源
			if(rs != null){
				try{
					rs.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			if(ps != null){
				try{
					ps.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			if(conn != null){
				try{
					conn.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
	}

	public void destroy(){
	
	}

	public String getServletInfo(){
		return "";
	}

	public ServletConfig getServletConfig(){
		return null;
	}
}

将相应的jar包放到WEB-INF/lib目录下

在这里插入图片描述

编译生成字节码文件

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  version="5.0"
  metadata-complete="true">

	<servlet>
		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
		<servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
		<url-pattern>/fdsa/fd/saf/d/sa/fd/sa/fd</url-pattern>
	</servlet-mapping>
	
	<servlet>
		<servlet-name>jdbc_test</servlet-name>
		<servlet-class>com.bjpowernode.servlet.StudentServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>jdbc_test</servlet-name>
		<url-pattern>/jdbc_test</url-pattern>
	</servlet-mapping>
	
</web-app>

在这里插入图片描述

🥽 在集成开发环境当中开发Servlet程序

  • 集成开发工具很多,其中目前使用比较多的是:
    • IntelliJ IDEA(这个居多,IDEA在提示功能方面要强于Eclipse,也就是说IDEA使用起来比Eclipse更加智能,更好用。JetBrain公司开发的。收费的。)
    • Eclipse(这个少一些),Eclipse目前还是有团队使用,只不过处于减少的趋势,自己从事工作之后,可能会遇到。Eclipse是IBM团队开发的。Eclipse寓意是“日食”。“日食”表示将太阳吃掉。太阳是SUN。IBM团队开发Eclipse的寓意是吞并SUN公司,但是2009年的时候SUN公司被Oracle公司并购了。IBM并没有成功并购SUN公司。
  • 使用IDEA集成开发工具开发Servlet
    • 第一步:New Project(我比较习惯先创建一个Empty Project【空工程】,然后在空工程下新建Module【模块】,这不是必须的,只是一种习惯,你可以直接新建非空的Project),这个Empty Project起名为:javaweb(不是必须的,只是一个名字而已。一般情况下新建的Project的名字最好和目录的名字一致。)
    • 第二步:新建模块(File --> new --> Module…)
      • 这里新建的是一个普通的JavaSE模块(这里先不要新建Java Enterprise模块,Java Enterprise基于Maven)
      • 这个Module自动会被放在javaweb的project下面。
      • 这个Module起名:servlet01
        在这里插入图片描述
        在这里插入图片描述
    • 第三步:让Module变成JavaEE的模块。(让Module变成webapp的模块。符合webapp规范。符合Servlet规范的Module)
      • 在Module上点击右键:Add Framework Support…(添加框架支持)
      • 在弹出的窗口中,选择Web Application(选择的是webapp的支持)
      • 选择了这个webapp的支持之后,IDEA会自动给你生成一个符合Servlet规范的webpp目录结构。在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述
      • 重点,需要注意的:在IDEA工具中根据Web Application模板生成的目录中有一个web目录,这个目录就代表webapp的根
    • 第四步(非必须):根据Web Application生成的资源中有index.jsp文件,这里我选择删除这个index.jsp文件。
    • 第五步:编写Servlet(StudentServlet)
      • class StudentServlet implements Servlet
      • 这个时候发现Servlet.class文件没有。怎么办?将CATALINA_HOME/lib/servlet-api.jar和jsp-api.jar添加到classpath当中(这里的classpath说的是IDEA的classpath)
        • File --> Project Structrue --> Modules --> + 加号 --> Add JARS…
        • 在这里插入图片描述
          在这里插入图片描述
          在这里插入图片描述
          在这里插入图片描述
      • 实现jakarta.servlet.Servlet接口中的5个方法。
        package com.javaweb.servlet;
        
        import javax.servlet.*;
        import java.io.IOException;
        
        public class StudentServlet implements Servlet {
        
            @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() {
        
            }
        }
        
        
    • 第六步:在Servlet当中的service方法中编写业务代码(我们这里连接数据库了。)
      package com.javaweb.servlet;
      
      import javax.servlet.*;
      import java.io.IOException;
      import java.io.PrintWriter;
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      
      public class StudentServlet implements Servlet {
      
          @Override
          public void init(ServletConfig servletConfig) throws ServletException {
      
          }
      
          @Override
          public ServletConfig getServletConfig() {
              return null;
          }
      
          @Override
          public void service(ServletRequest request, ServletResponse response)
                  throws ServletException, IOException {
              // 响应到浏览器出现中文乱码,可以指定字符集text/html;charset=UTF-8
              response.setContentType("text/html;charset=UTF-8");
              PrintWriter out = response.getWriter();
              // 编写JDBC代码,连接数据库,查询所有学生信息。
              Connection conn = null;
              PreparedStatement ps = null;
              ResultSet rs = null;
              try{
                  // 注册驱动 (com.mysql.jdbc.Driver,这个已过时。)
                  // 新版本中建议使用:com.mysql.cj.jdbc.Driver驱动。
                  Class.forName("com.mysql.cj.jdbc.Driver");
                  // 获取连接
                  String url = "jdbc:mysql://localhost:3306/mydatabase";
                  String user = "root";
                  String password = "285013 ";
                  conn = DriverManager.getConnection(url,user,password);
                  // 获取预编译的数据库操作对象
                  String sql = "select id,name from account";
                  ps = conn.prepareStatement(sql);
                  // 执行SQL
                  rs = ps.executeQuery();
                  // 处理查询结果集
                  while(rs.next()){
                      String no = rs.getString("id");
                      String name = rs.getString("name");
                      //System.out.println(no + "," + name);
                      out.print(no + "," + name + "<br>");
                  }
              }catch(Exception e){
                  e.printStackTrace();
              }finally{
                  // 释放资源
                  if(rs != null){
                      try{
                          rs.close();
                      }catch(Exception e){
                          e.printStackTrace();
                      }
                  }
                  if(ps != null){
                      try{
                          ps.close();
                      }catch(Exception e){
                          e.printStackTrace();
                      }
                  }
                  if(conn != null){
                      try{
                          conn.close();
                      }catch(Exception e){
                          e.printStackTrace();
                      }
                  }
              }
          }
      
          @Override
          public String getServletInfo() {
              return null;
          }
      
          @Override
          public void destroy() {
      
          }
      }
      
      
    • 第七步:在WEB-INF目录下新建了一个子目录:lib(这个目录名可不能随意,必须是全部小写的lib),并且将连接数据库的驱动jar包放到lib目录下。
      在这里插入图片描述
    • 第八步:在web.xml文件中完成StudentServlet类的注册。(请求路径和Servlet之间对应起来)
      <?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>studentServlet</servlet-name>
              <servlet-class>com.javaweb.servlet.StudentServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>studentServlet</servlet-name>
              <url-pattern>/servlet/student</url-pattern>
          </servlet-mapping>
          
      </web-app>
      
    • 第九步:给一个html页面,在HTML页面中编写一个超链接,用户点击这个超链接,发送请求,Tomcat执行后台的StudentServlet。
      • student.html
      • 这个文件不能放到WEB-INF目录里面,只能放到WEB-INF目录外面。
      • student.html文件的内容
      • <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>student page</title>
        </head>
        <body>
            <!--这里的项目名是 /xmm ,无法动态获取,先写死-->
            <a href="/xmm/servlet/student">student list</a>
        </body>
        </html>
        
    • 第十步:让IDEA工具去关联Tomcat服务器。关联的过程当中将webapp部署到Tomcat服务器当中。
      • IDEA工具右上角,绿色小锤子右边有一个:Add Configuration
        在这里插入图片描述
      • 左上角加号,点击Tomcat Server --> local
        在这里插入图片描述
      • 在弹出的界面中设置服务器Server的参数(基本上不用动)
        在这里插入图片描述
      • 在当前窗口中有一个Deployment(点击这个用来部署webapp),继续点击加号,部署即可。
        在这里插入图片描述
      • 修改 Application context为:/xmm
        在这里插入图片描述
    • 第十一步:启动Tomcat服务器
      • 在右上角有绿色的箭头,或者绿色的小虫子,点击这个绿色的小虫子,可以采用debug的模式启动Tomcat服务器。
      • 我们开发中建议适用debug模式启动Tomcat
    • 第十二步:打开浏览器,在浏览器地址栏上输入:http://localhost:8080/xmm/servlet/student
      在这里插入图片描述

🥽 Servlet对象的生命周期

  • 什么是Servlet对象生命周期?
    • Servlet对象什么时候被创建。
    • Servlet对象什么时候被销毁。
    • Servlet对象创建了几个?
    • Servlet对象的生命周期表示:一个Servlet对象从出生在最后的死亡,整个过程是怎样的。
  • Servlet对象是由谁来维护的?
    • Servlet对象的创建,对象上方法的调用,对象最终的销毁,Javaweb程序员是无权干预的。
    • Servlet对象的生命周期是由Tomcat服务器(WEB Server)全权负责的。
    • Tomcat服务器通常我们又称为:WEB容器。(这个叫法你要知道【WEB Container】)
    • WEB容器来管理Servlet对象的死活。
  • 思考:我们自己new的Servlet对象受WEB容器的管理吗?
    • 我们自己new的Servlet对象是不受WEB容器管理的。
    • WEB容器创建的Servlet对象,这些Servlet对象都会被放到一个集合当中(HashMap),只有放到这个HashMap集合中的Servlet才能够被WEB容器管理,自己new的Servlet对象不会被WEB容器管理。(自己new的Servlet对象不在容器当中)
    • web容器底层应该有一个HashMap这样的集合,在这个集合当中存储了Servlet对象和请求路径之间的关系
      在这里插入图片描述
  • 研究:服务器在启动的Servlet对象有没有被创建出来(默认情况下)?
    • 在Servlet中提供一个无参数的构造方法,启动服务器的时候看看构造方法是否执行。
    • 经过测试得出结论:默认情况下,服务器在启动的时候Servlet对象并不会被实例化。
    • 这个设计是合理的。用户没有发送请求之前,如果提前创建出来所有的Servlet对象,必然是耗费内存的,并且创建出来的Servlet如果一直没有用户访问,显然这个Servlet对象是一个废物,没必要先创建。
  • 怎么让服务器启动的时候创建Servlet对象呢?
    • 在servlet标签中添加<load-on-startup>子标签,在该子标签中填写整数,越小的整数优先级越高。
          <servlet>
              <servlet-name>aservlet</servlet-name>
              <servlet-class>com.bjpowernode.javaweb.servlet.AServlet</servlet-class>
              <!-- 
              	在服务器启动时创建Servlet对象,在该标签中填写整数
              	数字表示创建对象的先后顺序 
              	数字越小优先级越高
              -->
              <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
              <servlet-name>aservlet</servlet-name>
              <url-pattern>/a</url-pattern>
          </servlet-mapping>
      
  • Servlet对象生命周期
    • 默认情况下服务器启动的时候AServlet对象并没有被实例化
    • 用户发送第一次请求的时候,控制台输出了以下内容:
      AServlet无参数构造方法执行了
      AServlet's init method execute!
      AServlet's service method execute!
      
    • 根据以上输出内容得出结论:
      • 用户在发送第一次请求的时候Servlet对象被实例化(AServlet的构造方法被执行了。并且执行的是无参数构造方法。)
      • AServlet对象被创建出来之后,Tomcat服务器马上调用了AServlet对象的init方法。(init方法在执行的时候,AServlet对象已经存在了。已经被创建出来了。)
      • 用户发送第一次请求的时候,init方法执行之后,Tomcat服务器马上调用AServlet对象的service方法。
    • 用户继续发送第二次请求,控制台输出了以下内容:
      AServlet's service method execute!
      
    • 根据以上输出结果得知,用户在发送第二次,或者第三次,或者第四次请求的时候,Servlet对象并没有新建,还是使用之前创建好的Servlet对象,直接调用该Servlet对象的service方法,这说明:
      • 第一:Servlet对象是单例的(单实例的。但是要注意:Servlet对象是单实例的,但是Servlet类并不符合单例模式。我们称之为假单例。之所以单例是因为Servlet对象的创建我们javaweb程序员管不着,这个对象的创建只能是Tomcat来说了算,Tomcat只创建了一个,所以导致了单例,但是属于假单例。真单例模式,构造方法是私有化的。)
      • 第二:无参数构造方法、init方法只在第一次用户发送请求的时候执行。也就是说无参数构造方法只执行一次。init方法也只被Tomcat服务器调用一次。
      • 第三:只要用户发送一次请求:service方法必然会被Tomcat服务器调用一次。发送100次请求,service方法会被调用100次。
    • 关闭服务器的时候,控制台输出了以下内容:
      AServlet's destroy method execute!
      
    • 通过以上输出内容,可以得出以下结论:
      • Servlet的destroy方法只被Tomcat服务器调用一次。
      • destroy方法是在什么时候被调用的?
        • 在服务器关闭的时候。
        • 因为服务器关闭的时候要销毁AServlet对象的内存。
        • 服务器在销毁AServlet对象内存之前,Tomcat服务器会自动调用AServlet对象的destroy方法。
    • 请问:destroy方法调用的时候,对象销毁了还是没有销毁呢?
      • destroy方法执行的时候AServlet对象还在,没有被销毁。destroy方法执行结束之后,AServlet对象的内存才会被Tomcat释放。
      package com.bjpowernode.javaweb.servlet;
      
      import jakarta.servlet.*;
      
      import java.io.IOException;
      
      public class AServlet implements Servlet {
      
          // 无参数构造方法
          public AServlet() {
              System.out.println("AServlet无参数构造方法执行了");
          }
      
          // 程序员手动提供Servlet类的有参数的构造方法,会怎么样?
          /*public AServlet(String s){
      
          }*/
      
          // init被翻译为初始化
          // init方法只执行一次
          // 在AServlet对象第一次被创建之后执行。
          // init方法通常是完成初始化操作的。
          // init方法在执行的时候AServlet对象已经被创建出来了。
          @Override
          public void init(ServletConfig servletConfig) throws ServletException {
              System.out.println("AServlet's init method execute!");
          }
      
          // service方法:是处理用户请求的核心方法。
          // 只要用户发送一次请求,service方法必然会执行一次。
          // 发送100次请求,service方法则执行100次。
          @Override
          public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
              System.out.println("AServlet's service method execute!");
          }
      
          // destroy方法也是只执行一次。
          // Tomcat服务器在销毁AServlet对象之前会调用一次destroy方法
          // destroy方法在执行的时候,AServlet对象的内存还没有被销毁。即将被销毁。
          // destroy方法中可以编写销毁前的准备。
          // 比如说,服务器关闭的时候,AServlet对象开启了一些资源,这些资源可能是流,可能是数据库连接
          // 那么,关闭服务器的时候,要关闭这些流,关闭这些数据库连接,那么这些关闭资源的代码就可以写到destroy方法当中。
          @Override
          public void destroy() {
              System.out.println("AServlet's destroy method execute!");
          }
      
          @Override
          public ServletConfig getServletConfig() {
              return null;
          }
      
          @Override
          public String getServletInfo() {
              return null;
          }
      }
      
      
    • Servlet对象更像一个人的一生:
      • Servlet的无参数构造方法执行:标志着你出生了。
      • Servlet对象的init方法的执行:标志着你正在接受教育。
      • Servlet对象的service方法的执行:标志着你已经开始工作了,已经开始为人类提供服务了。
      • Servlet对象的destroy方法的执行:标志着临终。有什么遗言,抓紧的。要不然,来不及了。
    • 关于Servlet类中方法的调用次数?
      • 构造方法只执行一次。
      • init方法只执行一次。
      • service方法:用户发送一次请求则执行一次,发送N次请求则执行N次。
      • destroy方法只执行一次。
    • 当我们Servlet类中编写一个有参数的构造方法,如果没有手动编写无参数构造方法会出现什么问题?
      • 报错了:500错误。
      • 注意:500是一个HTTP协议的错误状态码。
      • 500一般情况下是因为服务器端的Java程序出现了异常。(服务器端的错误都是500错误:服务器内部错误。)
      • 如果没有无参数的构造方法,会导致出现500错误,无法实例化Servlet对象。
      • 所以,一定要注意:在Servlet开发当中,不建议程序员来定义构造方法,因为定义不当,一不小心就会导致无法实例化Servlet对象。
    • 思考:Servlet的无参数构造方法是在对象第一次创建的时候执行,并且只执行一次。init方法也是在对象第一次创建的时候执行,并且只执行一次。那么这个无参数构造方法可以代替掉init方法吗?
      • 不能。
      • Servlet规范中有要求,作为javaweb程序员,编写Servlet类的时候,不建议手动编写构造方法,因为编写构造方法,很容易让无参数构造方法消失,这个操作可能会导致Servlet对象无法实例化。所以init方法是有存在的必要的。
    • init、service、destroy方法中使用最多的是哪个方法?
      • 使用最多就是service方法,service方法是一定要实现的,因为service方法是处理用户请求的核心方法。
      • 什么时候使用init方法呢?
        • init方法很少用。
        • 通常在init方法当中做初始化操作,并且这个初始化操作只需要执行一次。例如:初始化数据库连接池,初始化线程池…
      • 什么时候使用destroy方法呢?
        • destroy方法也很少用。
        • 通常在destroy方法当中,进行资源的关闭。马上对象要被销毁了,还有什么没有关闭的,抓紧时间关闭资源。还有什么资源没保存的,抓紧时间保存一下。
  • 我们编写一个Servlet类直接实现Servlet接口有什么缺点?
    • 我们只需要service方法,其他方法大部分情况下是不需要使用的。代码很丑陋。

🥽 适配器设计模式Adapter实现Servlet接口

  • 手机直接插到220V的电压上,手机直接就报废了。怎么办?可以找一个充电器。这个充电器就是一个适配器。手机连接适配器。适配器连接220V的电压。这样问题就解决了。
  • 编写一个GenericServlet类,这个类是一个抽象类,其中有一个抽象方法service。
    • GenericServlet实现Servlet接口。
    • GenericServlet是一个适配器。
    • 以后编写的所有Servlet类继承GenericServlet,重写service方法即可。不需要每次都要实现所有的抽象方法
      package com.bjpowernode.javaweb.servlet;
      
      import jakarta.servlet.*;
      
      import java.io.IOException;
      
      /**
       * 编写一个标准通用的Servlet,起名:GenericServlet
       * 以后所有的Servlet类都不要直接实现Servlet接口了。
       * 以后所有的Servlet类都要继承GenericServlet类。
       * GenericServlet 就是一个适配器。
       */
      public abstract class GenericServlet implements Servlet {
      	
      	@Override
          public void init(ServletConfig config) throws ServletException{
      
          }
      
          @Override
          public ServletConfig getServletConfig() {
              return null;
          }
      
          /**
           * 抽象方法,这个方法最常用。所以要求子类必须实现service方法。
           * @param servletRequest
           * @param servletResponse
           * @throws ServletException
           * @throws IOException
           */
          public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
                  throws ServletException, IOException;
      
          @Override
          public String getServletInfo() {
              return null;
          }
      
          @Override
          public void destroy() {
      
          }
      }
      
      
  • 思考:GenericServlet类是否需要改造一下?怎么改造?更利于子类程序的编写?
    • 思考第一个问题:我提供了一个GenericServlet之后,init方法还会执行吗?
      • 还会执行。会执行GenericServlet类中的init方法。子类没有重写父类的方法会默认执行父类的方法
    • 思考第二个问题:init方法是谁调用的?
      • Tomcat服务器调用的。
    • 思考第三个问题:init方法中的ServletConfig对象是谁创建的?是谁传过来的?
      • 都是Tomcat干的。
      • Tomcat服务器先创建了ServletConfig对象,然后调用init方法,将ServletConfig对象传给了init方法。
    • 思考一下Tomcat服务器伪代码:
      • public class Tomcat {
            public static void main(String[] args){
                // .....
                // Tomcat服务器伪代码
                // 创建LoginServlet对象(通过反射机制,调用无参数构造方法来实例化LoginServlet对象)
                Class clazz = Class.forName("com.bjpowernode.javaweb.servlet.LoginServlet");
                Object obj = clazz.newInstance();
                
                // 向下转型
                Servlet servlet = (Servlet)obj;
                
                // 创建ServletConfig对象
                // Tomcat服务器负责将ServletConfig对象实例化出来。
                // 多态(Tomcat服务器完全实现了Servlet规范)
                ServletConfig servletConfig = new org.apache.catalina.core.StandardWrapperFacade();
                
                // 调用Servlet的init方法
                servlet.init(servletConfig);
                
                // 调用Servlet的service方法
                // ....
                
            }
        }
        
package com.bjpowernode.javaweb.servlet;

import jakarta.servlet.*;

import java.io.IOException;

/**
 * 编写一个标准通用的Servlet,起名:GenericServlet
 * 以后所有的Servlet类都不要直接实现Servlet接口了。
 * 以后所有的Servlet类都要继承GenericServlet类。
 * GenericServlet 就是一个适配器。
 */
public abstract class GenericServlet implements Servlet {

    // 成员变量
    // 将ServletConfig对象保存以便其他方法可以使用
    private ServletConfig config;

    /**
     * init方法中的ServletConfig对象是小猫咪创建好的。
     * 这个ServletConfig对象目前在init方法的参数上,属于局部变量。
     * 那么ServletConfig对象肯定以后要在service方法中使用,怎么才能保证ServletConfig对象在service方法中能够使用呢?
     */
     // 防止子类重写该方法,将该方法声明为final,提供一个单独的init方法是供子类重写的,在该方法中调用允许子类重写的init方法
    @Override
    public final void init(ServletConfig config) throws ServletException {
        //System.out.println("servletConfig对象,小猫咪创建好的:" + config);
        this.config = config;
        // 调用init()方法
        this.init();
    }

    /**
     * 这个init方法是供子类重写的。
     */
    public void init(){

    }

    @Override
    public ServletConfig getServletConfig() {
        return config;
    }

    /**
     * 抽象方法,这个方法最常用。所以要求子类必须实现service方法。
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException;

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

transient 表示修饰的属性不可序列化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178565.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GPU虚拟化(留坑)

文章内容大程度参考B站王利明老师对《GPU虚拟化技术分享》的演讲&#xff1a;https://b23.tv/uQKBpcK GPU 有什么用&#xff1f; GPU可以用于图形渲染&#xff0c;也能够用于高性能计算和编解码等场景。 图&#xff1a;GPU 的典型软件架构&#xff08;不含虚拟化&#xff09; …

注解存储对象到Spring,详解 五大类注解 和方法注解

上一篇博客我们介绍了如何使用xml来引入bean对象&#xff0c;当项目多的时候&#xff0c;显然那样是比较麻烦的。现在我们只需要 个注解就可以替代了。注意&#xff1a;注解和xml可以同时使用准备工作:配置扫描路径我们需要配置 下存储对象的扫描包路径&#xff0c;只有被配置的…

【笔记】openwrt - full cone NAT(全锥NAT)、解决“arp_cache: neighbor table overflow!”

最近安装了比特彗星&#xff08;bitcomet&#xff09;后&#xff0c;老是收到警告说日志的接收超过每秒上限了。一看日志&#xff0c;好家伙&#xff0c;一堆的kern.info kernel: [194004.157620] neighbour: arp_cache: neighbor table overflow!日志&#xff0c;还是kernel的…

损失函数总结

回归损失与分类损失 回归用于逼近某个数值,预测的结果是连续的,例如预测小明的身高,160,161,162,163cm。平方损失即MSE: 分类用于预测物体属于某一个标签,预测的结果是离散的,例如预测明天是否下雪:是or否。 由于预测分类,最终的输出需要介于(0,1)之间,通常在网络…

Redis消息队列 | 黑马点评

目录 一、认识消息队列 二、List模拟消息队列 三、PubSub的消息队列 四、Stream的消息队列&#xff08;重点&#xff09; 1、单消费模式 2、消费者组 五、redis三种消息队列对比 六、优化秒杀实战 1、创建消息队列 2、修改下单脚本 3、接收消息处理 一、认识消息队列 …

设计模式 - 创建型模式_工厂方法模式

文章目录创建型模式概述CaseBad ImplBetter Impl &#xff08;⼯⼚模式优化代码&#xff09;创建型模式 创建型模式提供创建对象的机制&#xff0c; 能够提升已有代码的灵活性和可复⽤性。 类型实现要点工厂方法定义⼀个创建对象的接⼝&#xff0c;让其⼦类⾃⼰决定实例化哪⼀…

【蓝桥杯-筑基篇】基础数学思维与技巧(1)

&#x1f353;系列专栏:蓝桥杯 &#x1f349;个人主页:个人主页 目录 1.一百以内的AB 2.小学生算术求进位次数 3.最大公约数 4.最小公倍数 5.十进制转换其他进制 6.其他进制转十进制 7.天空数 8.求集合的所有子集 9.判断一个数是否为2的次方数 10.二进制中1的个数 1.一…

ISIS简介、NSAP与NET地址、Router-Id转换成NET地址

2.0.0 ISIS简介、NSAP与NET地址、Router-Id转换成NET地址 ISIS简介 IS-IS&#xff08;Intermediate System-to-Intermediate System&#xff09;中间系统到中间系统。 1、该协议最初是ISO国际标准化组织为CLNP&#xff08;Connection Less Network Protocol&#xff0c;无连接…

HashMap 正解

HashMap 实现原理 以及扩容机制 HashMap 的 put 以及扩容基本实现 数据结构 上述截图是 HashMap 的内部存储的数据结构。大体上是通过 hash 值来获取到对应的下标。如果当前下标为 null 的话&#xff0c;直接创建并设置一个新的节点&#xff0c;反之就是添加到该链表的最后 pu…

好客租房-09_学习MongoDB并完善通讯系统

9. 学习MongoDB 并完善租房的通讯系统后端本章目的为MongoDB快速入门, 并完善上一节编写的通讯系统后台, 将DAO层从HashMap迁移到MongoDB中.思考如下问题:MongoDB属于关系型还是非关系型数据库为什么在我们的通讯系统中选择MongoDB作为数据库?9.1 mongoDB概念简介MongoDB是一个…

python+django医院固定资产设备管理系统

管理员功能模块 管理员登录&#xff0c;通过填写用户名、密码、角色等信息&#xff0c;输入完成后选择登录即可进入医院设备管理系统&#xff0c; 管理员登录进入医院设备管理系统可以查看首页、个人中心、科室员管理、维修员管理、设备领用管理、设备信息管理、设备入库管理、…

人工智能入门杂记

本篇文章属于所有发表的文章的导读吧&#xff0c;以后会常更新。 目录 1.数据挖掘、机器学习、深度学习、云计算、人工智能 2.深度学习、强化学习、对抗学习、迁移学习 3.基础知识--线性代数 4.基础知识--概率与数理统计 5.常用工具库 6.机器学习 6.1 什么是训练什么是推…

Java数组

文章目录Java 数组一、数组介绍二、数组1. 数组静态初始化1.1 数组定义格式1.2 数组静态初始化2. 数组元素访问3. 数组遍历操作3.1 数组遍历介绍3.2 数组遍历场景3.3 数组遍历案例1&#xff09;数组遍历-求偶数和2&#xff09;数组遍历-求最大值3&#xff09;数组遍历综合案例4…

【C语言航路】第十四站:文件

目录 一、为什么使用文件 二、什么是文件 1.程序文件 2.数据文件 3.文件名 三、文件的打开和关闭 1.文件指针 2.文件的打开和关闭 四、文件的顺序读写 1.对于输入输出的理解 2.fgetc与fputc &#xff08;1&#xff09;fgetc与fputc的介绍 &#xff08;2&#xff0…

2023年springcloud面试题(第一部分)

1. 什么是微服务架构微服务架构就是将单体的应用程序分成多个应用程序&#xff0c;这多个应用程序就成为微服务&#xff0c;每个微服务运行在自己的进程中&#xff0c;并使用轻量级的机制通信。这些服务围绕业务能力来划分&#xff0c;并通过自动化部署机制来独立部署。这些服务…

MP-4可燃气体传感器介绍

MP-4可燃气体传感器简介MP-4可燃气体传感器采用多层厚膜制造工艺&#xff0c;在微型Al2O3陶瓷基片的两面分别制作加热器和金属氧化物半导体气敏层&#xff0c;封装在金属壳体内。当环境空气中有被检测气体存在时传感器电导率发生变化。该气体的浓度越高&#xff0c;传感器的电导…

JavaWeb | JDBC相关API详解 2 (内附以集合形式输出表)

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;JDBC Java入门篇&#xff1a; &#x1f525;Java基础学习篇 Java进阶学习篇&#x…

C语言编程题

1、求斐波那契数列1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8……前20项之和 #include<stdio.h> int main() {int i,j,k,t2;ij1;printf("%d %d\n",i,j);for(k0;k<9;k){iij;jij;ttij;printf("%d %d\n",i,j);}printf(&q…

java七大查找 十大排序 贪心

七大查找 1.1二分查找(前提是 数据有序)说明&#xff1a;元素必须是有序的&#xff0c;从小到大&#xff0c;或者从大到小都是可以的。public static int binarySearc(int[] arr,int number){int min0;int maxarr.length-1;while(true){if(min>max){return -1;}int mid(maxm…

c++二插搜索树

1二插搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: ​ 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 ​ 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 …