javaEEWeb(Tomcat)深度理解和Servlet的本质

博客 动态
0 171
羽尘
羽尘 2023-03-15 14:26:30
悬赏:0 积分 收藏

javaEE Web(Tomcat)深度理解 和 Servlet的本质

javaEE Web(Tomcat)深度理解 和 Servlet的本质

在这里插入图片描述

每博一文案

我所有的进步,只为更接近你。
上天没有给予人们公平的人生,有人拥有出奇的才能,便有人只能不辞辛苦的攀登阶梯,我默默地守望着一缕光芒,小心翼翼,如掬如束,可若长久凝望,一点会让自己,也受烫灼。
平凡的人生或是悲惨的际遇,可能还不是最糟糕的,我害怕的是,如果始终懦弱不堪,会让哪怕是一份小小的心意,也永远无法传达。
竭尽力量的小勇敢,小心愿,一点会被许多人笑话的吧,那么,会被一个人了解吗,逝水比喻时光荏苒,十年了,我一直在努力的改变自己,夕语,你呢,你变成什么样子了?
不经意抬头看到的躲闪目光,低头侧目时不断加速的心跳,还有慌张间来不及带走的心思,以及追寻一个背影时的迟疑步伐。
过去的千丝万缕才刚浮动显现,穿过遮掩长久的黑暗,未来我们再相见时,希望所有眼泪,都能消失无形吧,曾经那个丢掉记忆逃跑的男孩,再见了。
上一次离开,我是那样决绝,我以为自己不会再回来了,再次相见时,本以为时隔多年,命运会再次垂青于我,可是兜兜转转,像是上天给我开了一个玩笑,错的一直是我。
我渴望的爱情如同虚幻泡沫,我想要挽回的友情,也没有了机会,此时此刻,我已经失去了留下来的力量。
所有成熟的大人,都曾是受伤的小孩,那个小孩可能会长大,但永远不会离开,我一直都在你的世界,看着你一点点改变,只是你,常常遗忘过去的自己。
今后我所有的牵挂 所有的向往 都和你一样 
                                                —————— 《我是江小白》
                                                —————— 来源《https://www.bilibili.com/read/cv16491270》

@


说明: 该博客是在基于安装了 Tomcat 的前提下操作的。 详细安装 Tomcat 的步骤大家可以移步至:(Tomcat 的安装以及其中配置环境原理的详细说明_tomcat要在什么环境下运行_ChinaRainbowSea的博客-CSDN博客

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

我们首先编写一个关于静态的网页的页面:一个简单的 百度链接:如下

<!--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>实现一个最基本的web应用(这个web应用中没有java小程序) </title>
</head>
<body style="text-align:center">
    <h3>百度链接</h3>
    <a href="https://www.baidu.com/">进入百度</a>
</body>
</html>

具体步骤如下:

第一步: 找到我们安装 Tomcat 中的路径找到一个名为 webapps 的目录。

注意: 我们所有的 web的 app 都要放到该 webapps 目录下,(没有为什么,这是 Tomcat 服务器的要求,如果不放到这里,Tomcat 服务器是无法到你的应用的app,并运行的)。

如下图所示:

在这里插入图片描述


第二步: 在我们找到的这个 webapps 目录下创建一个子目录,名为 Mytest 的目录。

注意: 这个目录名 test 就是你这个运行 webapp的名字。

在这里插入图片描述

第三步: 将我们上面编写的 html 静态文件,添加到该 Mytest目录下。

在这里插入图片描述

第四步: 启动我们的 Tomcat 服务器,打开我们的浏览器在地址栏上输入:http://127.0.0.1:8080/项目名/index.html :具体如下:http://127.0.0.1:8080/Mytest/index.html,最后回车,就可以访问到我们编写的 index.html 这个静态网页了。

在这里插入图片描述

在这里插入图片描述


重点:

我们在浏览器上直接输入一个 URL,然后回车,这个操作和点击一个 超链接是本质是一样的都是静态访问,既然都是一样的了。那我们完全可以使用超链接,访问我们在 Tomcat 服务器上编写的 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>访问我们部署到Tomcat中的index.html资源文件</title>
</head>
<body>
    <!--注意:我们目前前端上的路径都以“/”开始的,都是加项目名的。-->
    <a href="http://127.0.0.1:8080/Mytest/index.html">index.html</a>
</body>
</html>

在这里插入图片描述

在同一个部署到同一个项目下的,资源文件是可以相互访问的。例如:我们编写一个名为 index2.html 文件,通过 index.html 访问 index2.html 资源文件。

<!--index2.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>部署到Tomcat服务器中的index2.html资源文件</title>
</head>
<body style="text-align:center">
    <h1 >你好世界</h1>
    <!--部署到Tomcat同一个项目下的之间的访问,不需要添加:http://127.0.0.1:8080-->
    <!--注意:我们目前前端上的路径都以“/”开始的,都是加项目名的。-->
    <a href="/Mytest/index.html">访问我们部署到Tomcat中同一个项目中的的index.html资源文件</a>
</body>
</html>

同样放到我们安装 Tomcat 服务器的 webapps 中我们建立的项目 Mytest目录下

在这里插入图片描述

在这里插入图片描述

上述这种资源的访问:我们可以称之为是 静态资源 。所谓的静态资源就是,固定的,数据是不会更新的,从一开始就写死了的。

怎么能变成动态资源 ,显然是需要连接数据库的

连接数据库需要用 JDBC 程序,也就是需要编写 Java程序连接数据库,数据库中右多少条记录的信息,页面会根据数据库的记录的信息,进行一个动态的显示。这种技术被称为动态网页技术 。(动态网页技术并不是说页面中有 flash 动画。动态网页技术是说页面中的数据是动态的,是根据数据库中存储的数据进行一个时时动态更新变化的 )。这个操作在本博客的后半部分有详细说明。

2. 一个动态 Web 页面中所包含的 “角色” 和 “协议”

如下是一个简易的 Web 通信图

在这里插入图片描述

2.1 角色

根据上图分析:在整个BS结构的系统当中 有哪些人参与进去了

  • 浏览器软件的开发团队 :(浏览器软件太多了:谷歌浏览器,火狐浏览器,IE 浏览器...)
  • Web Serve的开发团队 : Web Server 这个软件也是太多了:Tomcat,Jetty,WebLogic ,JBOSS,WebSphere...
  • DB Server的开发团队: DB Server 也是不少的:Oracle,MySQL...
  • Web app的开发团队: Web 应该程序是我们作为 Java web 程序员 开发的。

2.2 协议

协议: 所谓的协议就是一种规范,大家都要遵守的规范。不过不遵守规范的话。相互之间是无法通信交流的。就不如说:两个人之间交流:一个人说英语,一个人说中文,这两个人之间使用的语言不同,也就是遵守的规范不同,两个人就无法交流了。各自都听不明白。如果两个人都遵守同一个规范,都是说中文,或者英文,相互之间就可以明白各自在说什么了,相互交流了。

同理: 浏览器前端 与 服务器后端之间想要相互交流数据信息,也是要遵守规范。服务器后端 与 数据库也是一样的。

在这里插入图片描述

  • Brower(浏览器) 与 WebServer 之间有一套传输协议:HTTP (超文本传输协议)

  • Web Server 与 webapp 之间有一套规范:JavaEE规范比如 Servlet规范

  • Webapp 和 DB Server 之间有一套规范:JDBC 规范,关于 JDBC 的详细内容,大家可以移步至:?????? 初始 JDBC_ChinaRainbowSea的博客-CSDN博客

  • Servlet 规范的作用是 : Web Server 和 Webapp 解耦合(让 Webapp 可以在不同的服务器上运行,提高代码的移植性)。

    • Servle 规范包括什么呢? 规范了哪些接口,规范了哪些类
      1. 规范了一个 web 应用中应该有哪些配置文件。
      2. 规范了一个web应用之哦个你配置文件的名字:web.xml
      3. 规范了一个web应用中配置文件存放的路径:\webapps\crm\WEB-INF\ 这个目录下
      4. 规范了一个web应用中配置文件的内容:XML标签中的类名...
      5. 规范了一个合法有效的web应用它的目录结构应该是怎样的
    webapproot
         |------WEB-INF
         		  |------classes(存放字节码)
         		  |------lib(第三方jar包)
         		  |------web.xml(注册Servlet)
         |------html
         |------css
         |------javascript
         |------image
         ....
    

模拟 Servlet 通信

SUN公司把Server 接口/规范制定出来了

package MyJavaWeb;

/**
 * 我们现在充当的角色是SUN公司。
 * SUN公司把Server 接口/规范制定出来了。
 */
public interface Servlet {
    // 一个专门提供服务的方法
    public abstract void service();
}

充当的角色为:webapp开发者 三个

package MyJavaWeb;

/**
 * 充当的角色为:webapp开发者
 * 只要我们webapp开发者的 XXXServlet 都要实现 Servlet 接口
 */
public class BankServlet implements Servlet{
    @Override
    public void service() {
        System.out.println("BankServlet is service...");
    }
}


package MyJavaWeb;

public class UserLoginServlet implements Servlet{
    @Override
    public void service() {
        System.out.println("UserLoginServlet is Servlet...");
    }
}

package MyJavaWeb;

public class UserListServlet implements Servlet{
    @Override
    public void service() {
        System.out.println("UserListServlet is Servlet...");
    }
}

充当Tomcat服务器的开发者

package MyJavaWeb;


import java.io.FileReader;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Scanner;

/**
 * 充当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 scanner = new Scanner(System.in);

        // 用户的请求路径:
        String key = scanner.nextLine();  // Tomcat 服务器已经获取到了用户的请求路径了

        // Tomcat 服务器应该通过用户的请求路径找到对应的 XXXServlet
        // 请求路径和XXXServlet 之间的关系应该由谁指定呢? wedapps 的开发者
        // 对应Tomcat 服务器来说需要解析配置文件
        //ResourceBundle bundle = ResourceBundle.getBundle("web.properties");

        FileReader reader = new FileReader("servlet01/src/MyJavaWeb/web.properties");
        Properties properties = new Properties();
        properties.load(reader);
        reader.close();

        // 通过 key 获取value
        String className = properties.getProperty(key);

        // 通过反射机制创建对象,注意:需要无参构造器
        Class clazz = Class.forName(className);
        Object o = clazz.newInstance();

        //因为这里使用的是多态:所有的 XXXServlet 都实现了其Servlet 接口
        // 但是Tomcat 服务器的开发者知道: 你写的XXXServlet 一定实现了 Servlet 接口
        Servlet servlet = (Servlet) o;

        servlet.service();

    }
}

模拟的 Web.xml配置文件

在这里插入图片描述

/aaa=MyJavaWeb.BankServlet
/bbb=MyJavaWeb.UserLoginServlet
/ccc=MyJavaWeb.UserListServlet
# 注意不要有空格

运行

在这里插入图片描述

在这里插入图片描述

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

具体步骤如下:

第一步: 在我们的 安装Tomcat的中的 webapp 目录下新建一个目录,起名为 crm (注意:这个crm就是我们的web项目的名称),当然我们也可以建立其他的项目,比如银行项目,可以创建一个目录 bank,办公系统可以创建一个 oa。等等 注意: crm就是我们这个项目的根了。

在这里插入图片描述

第二步: 在我们新建的 crm 目录下面新建一个名为 WEB-INF 的子目录。

注意: 这个目录的名字是被 Servlet 强制规范的,必须全部大写,必须是 WEB-INF 名,不可以是其他的。

在这里插入图片描述

第三步: 在我们刚刚创建的 WEB-INF 目录下新建一个子目录:classes

注意: 这个目录的名字必须是全部小写的 classes ,名字必须是这个,这也是被 Servlet 强制规范的。另外这个目录下,存放的是 java程序编译之后的 class文件(这里存放的是字节码文件)

在这里插入图片描述

第四步: 在我们上述创建的 WEB-INF 目录下创建一个名为 lib 的子目录。

注意: 这个目录不是必须要创建的,但如果你的一个 webapp项目需要第三方的 jar包的话,这个 jar 包要放到这个 lib 目录下,例如:java语言连接数据库需要数据库的驱动 jar 包,那么这个jar 包就一定要放到 lib 目录下。这个目录的名字也不能随便写,必须是全部小写,而且目录名必须是 lib ,这也是 Servlet 强制规范了的。

在这里插入图片描述

第五步: 编写一个 Java程序 ,这个小Java程序也不能随便开发的,我们开发的这个Java程序必须实现 Servelt 接口。

注意: 这个 Servlet 接口的信息是不在 JDK 当中的,(因为 Servelt 不是 JavaSE中的内容,Servlet 是属于 JavaEE的,是另外的一套类库)。

Servlet 接口(Servlet.class文件)是由 Oracle 提供的。(最初是 SUN公司提供的)。Servlet 接口是 JavaEE的规范的一员。

Tomcat 服务器实现了 Servlet 规范,所以 Tomcat 服务器也需要使用 Servlet 接口。Tomcat 服务器汇总应该有这个接口。在 Tomcat 服务器的这样一个目录下 apache-tomcat-8.5.82\lib\有这么一个 servlet-api.jar 文件,将其解压这个 servlet-api.jar之后,你会看到有一个 Servlet.class 的字节码文件

在这里插入图片描述

在这里插入图片描述

注意:JakartaEE9 开始,Servlet 接口的全名变成了 : jakarta.servlet.Servlet 不是上述 Tomcat 8 这样的目录路径了。

如下是我们编写的一个 java 小程序。

package com.RainbowSea.servlet;  // 包名

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

public class HelloServlet 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 {

        // 设置一下响应的内容类型是普通文本或Html代码
        // 需要在获取流对象之前设置,才有效果
        response.setContentType("text/html");

        System.out.println("My First Servlet, Hello Servlet");  // 在命令行中输出显示
        // 怎么将一个信息直接输出到浏览器上?
        // 需要使用ServletResponse接口 : response
        // response 表示响应:从服务器向浏览器发送数据叫响应
        PrintWriter out =  response.getWriter();
        out.print("Hello Servlet, You are My first servlet!"); // 在浏览器上输出显示

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

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

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

    @Override
    public void destroy() {

    }
}

我们需要将这个Java程序,编译一下,生成一个 class 的字节码文件,将我们这个Java程序编译生成的字节码文件,放到我们在 WEB-INF 子目录下的 classes 目录下。注意: Java源代码你原意在哪里就放在哪里,这个无所谓,但是你必须把其编译后生成的class字节码文件存放到 classes 目录下。这是被 Servlet 规范强制规定的。你只有将该Java小程序的字节码文件放到 classes 目录下,Servlet 才能识别到,并运行执行它。

第六步: 怎么能让你的 HelloServlet Java小程序编译通过呢 ?

从上述我们知道了。Servlet 接口的jar包是不在,我们的 JDK 当中的,所以如果我们直接使用命令 javac 编译的话,会存在一个问题:那就是我们识别出我们这个 HelloServlet Java代码中的 Servlet 接口,从而导致编译无法通过。如下所示

在这里插入图片描述

重点: 你怎么能让你的 HelloServleet 编译通过呢?配置环境变量 ClassPath。

这个 ClassPath 表示的就是类路径,作用就是当我们通过 cmd 命令执行 javac 编译的时候,其中存在的类名如果在 JDK中没有的话,会通过找 我们在 ClassPath环境变量中配置的类路径去找到对应的 类名中的 class文件并执行。具体操作如下:

将我们在 Tomcat 中自带的 servlet-api.jar 包的路径,配置到我们的 ClassPath 环境变量中就可以了。因为 Tomcat 实现了 Servlet 规范。

在这里插入图片描述

在这里插入图片描述

最后点击三个确定就配置好了。

配置好以后我们重新 javac 编译一下这个 HelloServlet Java程序就没有问题了。(注意:配置好以后,我们需要重新打开一个新的cmd命令窗口,才是使用了我们配置了信息编译的)

注意: 使用的 javac 命令

javac -encoding UTF-8 -d . *.java # 编译该包下所有的java 文件
# -endoing UTF-8 如果你的代码中存在中文注释的话,要附加上这样一条以 utf-8 编码,编译,不然它无法识别你的中文注释的而导致编译无法通过。

在这里插入图片描述

编译通过:

在这里插入图片描述

第七步: 将我们上述 HelloServlet 编译生成的 class 字节码文件,复制粘贴到我们 crm/WEB-INF/classes 目录下(注意:要连同对应是生成class字节码文件的包名路径,一起拷贝到 classes 目录下)

在这里插入图片描述

思考问题:以上配置的CLASSPATH和Tomcat服务器运行有没有关系?

没有任何关系,以上配置这个环境变量只是为了让你的HelloServlet能够正常编译生成class文件。

第八步: 在我们上述创建的 WEB-INF 目录下新建一个文件:web.xml

在这里插入图片描述

注意: 这个文件是必须的,这个文件名必须叫做 web.xml 。这个文件必须放在 WEB-INF 这个目录下。一个合法的 webapp, web.xml文件是必须的,这个 web.xml 文件就是一个配置文件,这个配置文件中描述了请求路径和 Servlet 类之间的对照关系。

这个文件最好从其他的 webapp 中拷贝,最好不要手写,没有必要,因为容易写错,而且写错了,还挺难发现的。所以我们复制粘贴就好了。

如下是从其他 webapp 复制过来的通用的 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">
</web-app>

在web.xml文件中编写配置信息,让“请求路径”和“Servlet类名”关联在一起。这一步用专业术语描述:在web.xml文件中注册Servlet类。

如下是含有 web.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-name>RainbowSea</servlet-name>
        <!--这个位置不能随便写,必须是该类的全限定类名:带包名的类名-->
		<servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class>
	</servlet>

    <!--servlet 映射信息-->
    <!--任何一个servlet都对应这一个servlet-mapping 配置信息 -->
	<servlet-mapping>
        <!--这个也是随便写的,但是这里的名字要和上面的 <servlet-name></servlet-name>两者之间要保持一致-->
        <!--一般是和类名一致-->
		<servlet-name>RainbowSea</servlet-name>
        <!--这里需要一个路径:这个路径唯一的要求就是要 / 开始
        因为我们通过在浏览器上输入项目名 + 资源路径中 url 是要 / 分隔的-->
        <!--这个映射路径随便写都可以,但是一定要 “/” 开头 -->
		<url-pattern>/RainbowSea/Rainbow/Sea</url-pattern>
	</servlet-mapping>
   
</web-app>

在这里插入图片描述

如下是没有注释信息的 web.xml 信息,因为如果我们不使用IDEA 集成开发环境编写的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-name>RainbowSea</servlet-name>
		<servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>RainbowSea</servlet-name>
		<url-pattern>/RainbowSea/Rainbow/Sea</url-pattern>
	</servlet-mapping>

</web-app>

浏览器发送请求,到最终服务器调用 Server 方法中读取 web.xml 的粗略过程:

  1. 用户输入 URL ,或者直接点击超链接:http://127.0.0.1:8080/crm/RainbowSea/Rainbow/Sea
  2. 然后 Tomcat 服务器接收到请求,截取路径:/crm/RainbowSea/Rainbow/Sea 信息。
  3. Tomcat 服务器先找到 webapps 项目下的crm
  4. Tomcat 服务器在找到我们编写的配置 web.xml 配置文件,在该配置文件中信息读取到 <servlet-mapping><url-pattern>/RainbowSea/Rainbow/Sea</url-pattern> </servlet-mapping> 在通过这个信息找到 <servlet-mapping><servlet-name>RainbowSea</servlet-name> </servlet-mapping>中的 Rainbows 中的信息。
  5. 找到 <servlet> : <servlet-name>RainbowSea</servlet-name> </servlet> 中的 RainbowSea信息找到 <servlet> : <servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class> </servlet> 信息。
  6. 最后我们拿到了 该执行的Java程序的全限定类名:com.RainbowSea.servlet.HelloServlet 。有了该类的全限定类名,我们Tomcat服务器就可以通过 反射机制 创建 com.RainbowSea.servlet.HelloServlet 的对象了。需要注意的是:如果要使用反射机制的话:该类中必须定义了 无参构造器才行 。因为反射机制的底层是调用了 。该类的无参构造器的。
  7. 最后:Tomcat 服务器调用 com.RainbowSea.servlet.HelloServlet 对象中的 service 方法。执行程序。

第九步: 启动 Tomcat 服务器

在这里插入图片描述

第十步: 打开浏览器,在浏览器地址栏上输入一个 url ,这个 URL 必须是:http://127.0.0.1:8080/项目名/我们在web.xml中编写的映射路径,这里是:http://127.0.0.1:8080/crm/RainbowSea/Rainbow/Sea

  • http://127.0.0.1:8080/ : 表示的是本地计算机上的 Tomcat 服务器资源
  • crm : 我们上述步骤编写的 webapps 项目名
  • /RainbowSea/Rainbow/Sea : 我们在 web.xml 中编写的资源路径映射的路径。web.xml文件中的url-pattern

执行结果:

在这里插入图片描述

在这里插入图片描述

非常重要的一件事:浏览器上的请求路径不能随便写,这个请求路径必须和我们编写的 web.xml文件中的url-pattern 一致。

注意: 浏览器上的请求路径和 web.xml 文件中的 url-pattern 的唯一区别就是:浏览器上的请求路径带项目名:/crm

浏览器上编写的路径太复杂,可以使用超链接。注意: 这个我们编写的 html 页面只能放到 WEB-INF 目录的外面。

在这里插入图片描述

如下是我们编写的 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>index page</title>
</head>
<body>
    <a href="/crm/RainbowSea/Rainbow/Sea">hello servlet</a>
</body>
</html>

执行效果:我们在浏览器上输入:http://127.0.0.1:8080/crm/index.html。注意 Tomcat 要保持开启状态。

在这里插入图片描述

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

3.1 Servlet 连接 MySQL8.0 数据库

上述的 Sevlet 编写的小程序是静态的,没有连接数据库中的信息。这里我们来,编写一个动态的小程序。连接了我们的 MySQL 数据库

第一步: 我们先在数据库中创建一个名为 dbtest9 的数据库,在该数据库下创建一个名为t_student 的表,表中添加一些数据。

SELECT *
FROM emps;

CREATE TABLE t_student (
  `no` INT,
  `name` VARCHAR(255)
);

在这里插入图片描述

第二步: 编写 一个名为 MySQLServlet的ava程序,并编译生成对应的 class 文件

package com.RainbowSea.servlet; // 包名

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MySQLServlet 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 {
        // 编写JDBC代码,连接数据库,查询所有学生信息
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        // 设置一下响应的内容类型是普通文本或Html代码
        // 需要在获取流对象之前设置,才有效果
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        try {
            // 1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 获取连接
            String url = "jdbc:mysql://localhost:3306/dbtest9";
            String user = "root";
            String password = "MySQL123";

            connection = DriverManager.getConnection(url, user, password);

            // 3. 获取到预编译的数据库连接操作对象
            String sql = "select no ,name from t_student";
            preparedStatement = connection.prepareStatement(sql);
            // 4. 执行sql
            resultSet = preparedStatement.executeQuery();
            // 5. 处理查询结果集
            while (resultSet.next()) {
                String no = resultSet.getString("no");
                String name = resultSet.getString("name");
                out.print(no +"->"+name + "<br>");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 6. 关闭资源

            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }


            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }

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

    @Override
    public void destroy() {

    }
}

同样使用我们的 cmd 命令编译生成对应的字节码文件:

javac -encoding UTF-8 -d . *.java # 编译该包下所有的java 文件
# -endoing UTF-8 如果你的代码中存在中文注释的话,要附加上这样一条以 utf-8 编码,编译,不然它无法识别你的中文注释的而导致编译无法通过。

在这里插入图片描述

同样的,根据我们在该Java程序中定义的 : package com.RainbowSea.servlet 生成对应的包(目录)存放对应的 MySQLServlet.class文件。如下图所示:

在这里插入图片描述

第三步 :我们将我们的 MySQLServlet.class 文件拷贝到,我们webapp项目中的 `

在这里插入图片描述

同样的:我们需要将我们生成的 class 字节码文件的包括:包名(目录)完成的拷贝过去。如下

在这里插入图片描述

第四步: 编写我们在 webapps/crm/WEB-INF 目录下的 web.xml 文件。在 web.xml 文件中编写配置信息,让 “请求路径” 和 “MySQLServlet类名 ” 关联在一起。这一步专业术语被称为是: 在web.xmll 文件中注册Servlet类

在这里插入图片描述

编写的web.xml 信息内容如下: 注意: 如果我们是通过手动的方式编写的,而没有借助 IDEA 这样之类的集成开发环境环境的话。是我们识别我们在 web.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-name>RainbowSea</servlet-name>
		<servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>RainbowSea</servlet-name>
		<url-pattern>/RainbowSea/Rainbow/Sea</url-pattern>
	</servlet-mapping>
    
    
      <servlet>
		<servlet-name>MySQLServlet</servlet-name>
		<servlet-class>com.RainbowSea.servlet.MySQLServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>MySQLServlet</servlet-name>
		<url-pattern>/RainbowSea/student/list</url-pattern>
	</servlet-mapping>

</web-app>

第五步 : 启动 Tomcat 服务器。

在这里插入图片描述

第六步: 在浏览器的地址栏上输入: http://127.0.0.1:8080/crm//RainbowSea/student/list进行访问。

在这里插入图片描述

第七步: 验证我们的数据信息是否是:动态更新的:我们更新我们的数据库表中的信息。添加一条数据: 7 , Tomcat

在这里插入图片描述

INSERT INTO t_student VALUES(7,"Tomcat");

在这里插入图片描述

我们在访问,我们页面中的数据是否也是同步更新上的。刷新一下页面,即可。

在这里插入图片描述

从上述刷新运行的结果上看,我们的页面是被同步更新的。

4. 补充:

4.1 JavaEE 的版本说明

JavaEE 目前最高版本是 JavaEE8。

2017 年 8 月,Oracle(甲骨文)决定将 Java EE(Java Enterprise Edition)移交给开源组织,最后 Eclipse 基金会接手。这应该是甲骨文实现对 Java 品牌控制的最新举措,尽管之前 Sun 的资产已经被甲骨文围剿得只剩一个 VirtualBox 还能喘口气。不过,甲骨文可不允许开源组织用 Java 的名号,于是 Eclipse 选出了 "Jakarta EE" 和"Enterprise Profile"两个后续按名字,最终前者以 64.4% 的票数获胜。所以就把 JavaEE 改名了,以后就不叫 JavaEE了,以及就叫做 了 Jakarta EE 。从 JavaEE8 版本升级之后的 JavaEE9 ,就不再是这个 “JavaEE9” 这个名字了,而是叫做了 Jakarta EE9 了。

因为本名都被修改了,所以其中对应的类存在的包名也是被修改了的。具体如下。

注意点:

  • JavaEE8 版本对应的 Servlet 全限定类名是:javax.servlet.Servlet。如下是 Tomcat 8 中 Servlet .java的存放路径

在这里插入图片描述

  • JakartaEE9 版本的时候对应的 Servlet 全限定类名是:jakarta.servlet.Servlet (包名都被换了)如下是 Tomcat 10 中 Servlet.java的存放路径。

在这里插入图片描述

  • 如果你之前的项目还是使用 Tomcat 8 中的javax.servlet.Servlet ,那么你的项目无法直接部署到 Tomcat 10+版本上。你只能部署到 Tomcat 9- 版本之后上,在 Tomcat 9 以及 Tomcat 9 之前的版本中还是能够识别 javax.servlet 这个包的。
  • 当然也是有解决方法的。在 Tomcat 的官网上有所说明:https://tomcat.apache.org/

    在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


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

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

java.util.logging.ConsoleHandler.encoding = GBK

具体的可以移步至:?????? Tomcat 的安装以及其中配置环境原理的详细说明_tomcat要在什么环境下运行_ChinaRainbowSea的博客-CSDN博客

5. 总结:

  1. 理解一个 web 页面中所包含的 角色 和 协议:

    • 角色 : 浏览器开发团体,Web Serve服务器开发团队,webapps 开发团队,DB数据库开发团队。
    • 协议:
      • 浏览器页面 与 web Serve 服务器之间的协议是 :HTTP 超文本传输协议
      • web Server 服务器与 webapps 之间的协议是:Java EE 的 中 规范,比如 Servlet 等等等
      • webapps 与 DB 数据库之间的协议是:JDBC
  2. Servle 规范包括什么呢? 规范了哪些接口,规范了哪些类 : 规范了 web 应用中的配置文件,以及配置文件名 web.xml,配置文件的存放路径:\webapps\crm\WEB-INF\ ,配置文件的内容:XML 标签中的类名(在web.xmll 文件中注册Servlet类),规范了一个合法有效的 web 应用它的目录结构应该是怎样的。

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

webapproot
     |------WEB-INF
     		  |------classes(存放字节码)
     		  |------lib(第三方jar包)
     		  |------web.xml(注册Servlet)
     |------html
     |------css
     |------javascript
     |------image
     ....
  1. 关于 JavaEE 的版本说明:Servlet 包名的改变所带来的影响后果:jakartaEE9 版本的时候对应的 Servlet 全限定类名是:jakarta.servlet.Servlet如果你之前的项目还是使用 Tomcat 8 中的javax.servlet.Servlet ,那么你的项目无法直接部署到 Tomcat 10+版本上。你只能部署到 Tomcat 9- 版本之后上,在 Tomcat 9 以及 Tomcat 9 之前的版本中还是能够识别 javax.servlet 这个包的。 这个问题在 Tomcat 的官网上有已有解决方法。https://tomcat.apache.org/

  2. 理解web.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-name>RainbowSea</servlet-name>
        <!--这个位置不能随便写,必须是该类的全限定类名:带包名的类名-->
		<servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class>
	</servlet>

    <!--servlet 映射信息-->
    <!--任何一个servlet都对应这一个servlet-mapping 配置信息 -->
	<servlet-mapping>
        <!--这个也是随便写的,但是这里的名字要和上面的 <servlet-name></servlet-name>两者之间要保持一致-->
        <!--一般是和类名一致-->
		<servlet-name>RainbowSea</servlet-name>
        <!--这里需要一个路径:这个路径唯一的要求就是要 / 开始
        因为我们通过在浏览器上输入项目名 + 资源路径中 url 是要 / 分隔的-->
        <!--这个映射路径随便写都可以,但是一定要 “/” 开头 -->
		<url-pattern>/RainbowSea/Rainbow/Sea</url-pattern>
	</servlet-mapping>
   
</web-app>

在这里插入图片描述

  1. 浏览器发送请求,到服务器调用 Servlet 中的方法的粗略过程:

    1. 用户输入 URL ,或者直接点击超链接:http://127.0.0.1:8080/crm/RainbowSea/Rainbow/Sea
    2. 然后 Tomcat 服务器接收到请求,截取路径:/crm/RainbowSea/Rainbow/Sea 信息。
    3. Tomcat 服务器先找到 webapps 项目下的crm
    4. Tomcat 服务器在找到我们编写的配置 web.xml 配置文件,在该配置文件中信息读取到 <servlet-mapping><url-pattern>/RainbowSea/Rainbow/Sea</url-pattern> </servlet-mapping> 在通过这个信息找到 <servlet-mapping><servlet-name>RainbowSea</servlet-name> </servlet-mapping> 中的 Rainbows 中的信息。
    5. 找到 <servlet> : <servlet-name>RainbowSea</servlet-name> </servlet> 中的 RainbowSea信息找到 <servlet> : <servlet-class>com.RainbowSea.servlet.HelloServlet</servlet-class> </servlet> 信息。
    6. 最后我们拿到了 该执行的Java程序的全限定类名:com.RainbowSea.servlet.HelloServlet 。有了该类的全限定类名,我们Tomcat服务器就可以通过 反射机制 创建 com.RainbowSea.servlet.HelloServlet 的对象了。需要注意的是:如果要使用反射机制的话:该类中必须定义了 无参构造器才行 。因为反射机制的底层是调用了 。该类的无参构造器的。
    7. 最后:Tomcat 服务器调用 com.RainbowSea.servlet.HelloServlet 对象中的 service 方法。执行程序。

6. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,江湖再见,后会有期!!!

在这里插入图片描述

posted @ 2023-03-15 14:05  Rainbow-Sea  阅读(0)  评论(0编辑  收藏  举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员