文章目录
- 1、JavaWEB相关的知识点学习
- 2、对于动态的 Web 应用来讲:一个请求响应中有多少个角色的参与?角色之间是怎么进行通信的呢?
- 3、webapp角色之间遵守什么规范?
- 4、模拟 Servlet 本质
- 5、JavaWeb 只做两件事情
- 6、Servlet 规范中规定了:
- 7、理解Servlet 是一个什么样子的规范?
- 8、实际操作:开发一个带有 Servlet 的 webapp(重点)
- 9、向浏览器相应一段 servlet 代码
- 10、在Servlet 中进行数据库的连接
- 在集成开发环境中(IDEA)开发Servlet 程序
- 11 集成开发环境的文件组织以及注意事项
- 12 Servlet 对象的生命周期
- 13、创建一个服务的相关代码 AServlet
- 14、适配器的相关介绍
- 在程序中写一个 GenericServlet 类
1、JavaWEB相关的知识点学习
前端时间和后端之间的信息交互:
前端确定了访问了文件位置,调用后端的相关执行程序文件
2、对于动态的 Web 应用来讲:一个请求响应中有多少个角色的参与?角色之间是怎么进行通信的呢?
整个 B/S 结构中,什么人参与进去?
1、浏览器的开发者;
2、Web Server 开发团队 Tomcat,Jetty;
3、DB Server MySQL Oracle;
4、Java 程序的开发 Web APP 开发
Web 应用的开发的目录需要遵从一定的规范,在不同的 Web Server 都可以使用
达到通用的实现规范,可以不同的服务器上面使用
Serlet 就是制定的一套规范,可以规范的开发网络应用
3、webapp角色之间遵守什么规范?
HTTP 协议(超文本传输协议)
Browser 和 WebServer 之间存在的协议
Servlet 规范,WebServer 和 Webapp之间存在的协议
Servlet 规范的作用:Web server , Web App之间解耦合,减少依赖程度
JDBC 的规范
Webapp 和 DBServer 之间存在的规范
4、模拟 Servlet 本质
不同的公司,制定了相关行业内部的规则,其他的开发者遵从相关的规则即可;遵循了相关的规则之后,就可以进行互相协同操作;
关于前端访问静态的 html 文件,使用到大服务器的路径就可以
关于前端访问Java 程序,可以通过程序员执行的映射关系,进行程序的访问
5、JavaWeb 只做两件事情
1、编写一个类实现Servlet 接口
2、编写配置文件,编写的类配置到配置文件,在配置文件中指定请求路径和类名之间的关系
注意:
- 配置文件的文件名字是固定好的,web.properties,配置文件的放的位置都是固定好的,不能乱来
- 因为项目是需要放在服务器上面运行的,服务器的是其他公式已经写好的东西,所以需要遵从相关的规范,
不能随便乱来;
6、Servlet 规范中规定了:
合格的 webapp 应该是什么样子的目录结构;
合格的 webapp 拥有什么样子的配置文件
合格的webapp配置文件放在什么地方
合格的webapp的Java程序放在什么地方
这些都是规定好的
Tomcat 服务器需要遵守规范,JavaWEB程序员也是同样需要遵守相关的规范,这样子Tomcat和
webapp 之间才能解耦合;
7、理解Servlet 是一个什么样子的规范?
遵循了Servlet 规范的webapp 可以在不同的额服务器的下面运行
Servlet 规范中包括了什么呢?
1、规定了什么样子的接口
2、规范了一些类
3、规范了web 应用中应该有什么样子的配置文件
4、规范了配置文件的名字
5、规范了配置文件存储的路径
6、规范了webapp 配置文件中的内容…
8、实际操作:开发一个带有 Servlet 的 webapp(重点)
开发步骤(11步):
8.1
- 1、在webapp 目录下面新建一个目录,起名叫做 crm(crm就是webapp的名字),起名字是根据自己的开发需要设定的
8.2
- 2、在crm目录下面,新建一个目录:WEB-INF
这个文件的创建是Servlet 中所规定的,必须是全部大写的才可以
8.3
- 3、在 WEB-INF 下面新建一个目录叫做 classes 必须是这个名字,Servlet 规范中规定的
注意:这里存放的是,Java 程序编译之后的class 文件,这李存放的是字节码文件
8.4
- 4、在WEB-INF 下面创建一个新的目录:lib(不是必须的)
Java在开发的过程中使用到了第三方的 jar 包,需要使用这个名字,必须使用这个名字
8.5
- 5、在WEB-INF 新建一个文件叫做:web.xml
这个文件名字是必须的,文件的名字是必须叫做这个名字的,文件必须放在这里;
web.xml 是一个配置文件,配置文件中描述了请求路径以及 Servlet 类之间的对照关系
(这个文件直接从其他的webapp中赋值粘贴即可)
<?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"
metadata-complete="true">
<display-name>Tomcat Documentation</display-name>
<description>
Tomcat Documentation.
</description>
</web-app>
8.6
6、编写Java程序,小程序,不能随意开发,必须实现 Servlet 接口
-
Servlet 接口在什么位置?(javaEE 使用的是另外的类库,SE加强版本)
-
Servlet.class 文件
-
Servlet 是JavaEE 中的一员
-
Tomcat 服务器实现了 Servlet 接口,Tomcat 也是需要使用 Servlet 接口的
所以这个类在 Servlet 下面的文件中是可以找到的;lib 目录下面存在
Servlet-api.jar 文件 -
开发的Java源代码可以放置在任何的位置,但是 编译生成的 .class 文件必须放在 classes 文件夹下面
8.7
编写Java程序
8.8
将写好的Java文件编译好形成的 .class 文件放置在:WEB-INF\classes 文件夹下面
8.9
web.xml 文件中编写配置信息,使得 “请求路径” 和 ”Servlet类名“ 关联在一起
注册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"
metadata-complete="true">
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.luobin.javaweb.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>
webapp 的文件组成结构
关于目前的 webapp 的文件结构
|-----webapp
|-----WEB-INF
|-----classes(存放字节码文件)
|-----lib(第三方 jar 包)
|-----web.xml(注册servlet)
|-----html
|-----css
|-----javascript
关于浏览器发送请求到最终的服务器调用Servlet 方法,是一个什么样子的过程?
(下面的实现方法比较的粗糙,有一些细节是没有提到的)
1、用户输入URL在浏览器里面,或者点击超链接
2、Tomcat 服务器收到了请求,截取路径:/crm/test
3、Tomcat服务器在web.xml文件中查找/crm/test 对应的serclet 为:com.luobin.javaweb.HelloServlet
4、Tomcat 服务器通过反射机制,创建com.luobin.javaweb.HelloServlet的对象的service 方法
8.10
启动 tomcat 服务器(mac 使用这个命令可以像 win 在控制台进行输出信息)
catalina.sh run
8.11
在浏览器打开url
http://localhost:8080/crm/test
这个请求路径必须和 web.xml 中的url-pattern 保持一直才可以,否则,运行时可能不成功的;
注意:浏览器上面请求的路径和 web.xml 中的url-pattern 中的唯一区别就是:浏览器上面的请求路径是带着项目名字的;
浏览器上面编写的路径太长的时候,可以使用超链接进行处理;(html 文件只能放置在WEB-INF 目录的外面)
以后不需要编写 main 方法tomcat 在执行的时候,就是相当于 main 方法的功能,javaWeb 程序员,只需要写Servlet 接口的实现类,然后注册到 web.xml即可
8.12关于JavaEE 版本的相关问题
- JavaEE 当前的最高版本是JavaEE8
- JavaEE被 Oracle 捐献给了 Apache
- 以后叫做jakataEE
- 以后没有JavaEE8 升级之后叫做: jakataEE9
javaEE8 叫做:javax.servlet.Servlet
jakataEE9 叫做:jakata.servlet.Servlet
更改了之后,只能在 Tomcat9 以及以前的版本部署webapp 在之后的版本中是没有办法部署的;
9、向浏览器相应一段 servlet 代码
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
// 向着控制台记性字符串的打印
System.out.println("My first servlet , Hello Servlet");
// 设置相应的文本是普通的文本内容还是 html 等格式的内容
// 设置这个相应的格式在流的前面进行设置,不要再流的后面设置,因为这样子设置之后,没有修改显示的格式
// 想要设置就在流的前面设置即可
response.setContentType("text/html");
// 如何把一个信息直接输入到浏览器上面?
// 需要使用ServletResponse 接口: response
// response表示相应的意思:从服务器向着浏览器发送数据叫做相应
// 这是一个输出流,负责将字符串输出到浏览器上面
// 上面的是向着浏览器进行打印,这里的是向着浏览器进行打印
PrintWriter out = response.getWriter();
out.println("Hello Servlet ,You are my first Servlet");
// 向着浏览器相应一段 html 的代码,提供使用
out.println("<h1>Hello Servlet</h1>");
// 创建的这个流是不需要刷新的,也是不需要关闭的;Tomcat 是会自动维护的
}
10、在Servlet 中进行数据库的连接
- Servlet 是Java程序,所以在servlet 中可以直接编写JDBC进行数据库的连接
- 在一个 webapp 中,需要将驱动放在 WEB-INF/lib 下面(com.mysql.cj.jdbc.Driver)
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 编写 jdbc 代码,进行数据库的连接,记性数据的查询操作
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
// 进行配置文件的获取,获取到进入数据库的权限,进行数据库的操作权限
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String username = bundle.getString("username");
String password = bundle.getString("password");
try {
// 获取驱动,进行驱动的连接
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
conn = DriverManager.getConnection(url, username, password);
// 获取预编译的数据库操作对象
String sql = "select * from dept";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
// 处理查询结果集
while (rs.next()) {
String dname = rs.getString("dname");
System.out.println(dname);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
在集成开发环境中(IDEA)开发Servlet 程序
1、先创建一个空的项目,在空的项目下面创建不同的模块进行开发工作的开展
2、新建模块
新建一个普通的JavaSE模块(先不使用JavaEE模块)
3、让Module 变成JavaEE模块
- 右键项目的名字即可(add Framework Support)
- (让Module 变成webapp 模块,符合webapp 的规范,或者叫做符合Servlet 规范 Module)
- 弹出来的窗口中选择 Web Application 选项,选择了这个webapp 的支持之后,IDEA会自动的生成符合Servlet 规范的webapp 文件目录
4、(非必须):根据webApplication 里面的 .jsp 文件删除掉
5、编写servlet(StudentServlet)
6、编写的时候,发现 Servlet 相关jar 包没有导入进去,在这里projects structure 里面进行相关的包的导入即可
11 集成开发环境的文件组织以及注意事项
注意:
- 1、lib 文件夹需要放置在WEB-INF 下面,否则类没有加载进去,会产生异常;
- 2、在html 中设置的超链接需要和 web.xml 里面注册的地址是相同的,否则超链接找不到注册路径无法执行相关的代码,因为根本连类都找不到;
- 3、当lib 文件夹的位置变了之后,需要重新将 jar 包 add as library这样子才能识别,不然找不到驱动的,也就是找不到 jar 包;
12 Servlet 对象的生命周期
什么时候是被创建出来的,创建了一个还是多个?
Servlet 对象的创建是Tomcat 自动创建的,web 服务器负责创建的;
Servlet 对象是由谁进行维护的呢?
所有的对象的创建到最终的结束,javaweb 开发人员是没有办法进行干预的,Servlet 的对象是由Tomcat 服务器(web 服务器)全权负责的;
Tomcat 服务器通常可以叫做为:web容器(web container)(web server)
12.1 什么是Servlet 生命周期?
生命周期就是对象的刚开始的创建一直到最后的对象的销毁
12.2 Servlet 对象什么时候创建?
在调用的额时候被创建
12.3 Servlet 什么时候被销毁?
12.4 Servlet 对象创建了几个?
调用了几个服务就会创建相关的几个对象
12.5 Servlet 生命周期:表示这一个对象的创建到最终的销毁,整个过程是一个什么样子的;
12.6 我们自己 new 出来的对象受到 web 容器的影响吗?
-
自己new 出来的Servlet 对象是不受到web 容器管理的;
-
web 容器创建出来的Servlet 对象,使得Servlet 对象都会放置在一个集合当中:HashMap,只有放在 HashMap,只有放在 HashMap 容器里面的对象才会被Tomcat 服务器进行管理,自己创建出来的对象是不会放进去的,所以就不会被管理;
-
web 容器底层是应该具有一个 HashMap 这样子的集合,用来存储Servlet 对象以及请求路径之间的关系;
12.7 服务器在启动的时候,Servlet 对象有没有被创建出来?(默认情况下面)
经过了实验,在服务器启动了之后,Servlet 对象开始并没有被创建出来,当在访问其注册的地址的时候,对象会被创建出来;
在请求的时候,才会被创建出来是比较合理的,在用户发请求之前是先不会被创建出来的,只有在用户请求了之后,才会被创建出来,对于资源的节约是有一定的帮助作用的;
为什么在调用的时候,访问的时候,才创建相关的对象呢?
因为提前创建好的对象没有什么用户,不用的话,反而一直在占用内存空间,造成了空间的浪费;
想让Servlet 对象在服务器启动的时候就把对象创建出来的办法有:
<servlet>
<servlet-name>aservlet</servlet-name>
<servlet-class> com.luobin.servlet.AServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>aservlet</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
添加了 标签在后面加上整数,整数的数字越小,其优先级别是越高的;
这个整数是不能使用负数的;
通过上面的小实验得到的结论:
1、用户在第一次请求的时候,对象被创建,也就是被实例化了
2、Aservlet 对象被创建出来之后,Tomcat 先调用了 init 方法(因为先创建出来的对象,所以在后面才可以进行 init 方法的调用)
3、服务器启动了之后,在网页进行刷新的时候,会一直调用 service 方法,init 以及构造方法都只是会执行一次,初始化的时候执行一次;
(Servlet 是一种假单例模式)
init 无参数构造方法,只是会在第一次用户发送请求的时候执行;
只要用户发送请求,service 方法必定会被执行的;请求 100 此 会被调用100 次;
4、Servlet 方法的 destroy 方法知识会被 Tomcat 服务器调用一次
destrory 在服务器被关闭的时候被调用的;服务器在进行对象的销毁之前,会调用 destroy 方法;
调用 destroy 方法的时候,对象销毁了还是没有销毁?
没有被销毁的,在销毁之前就会调用这个方法;destroy 是一个实例方法,实例方法被调用了,说明实例是存在的,也就是对象是存在的;
13、创建一个服务的相关代码 AServlet
package com.luobin.servlet;
import javax.servlet.*;
import java.io.IOException;
import java.security.Provider;
/**
* @author Doraemon
* @version 1.0
* @date 2021/11/10 2:36 下午
*/
// 在创建对象的时候 Tomcat 会自动的进行对象的创建,只会创建出来一个对象,但是不是一个真的单例,是一个假的单例
// 是多线程共享的一个对象
// 真的单例模式是构造参数私有化的,这个显然不是的
public class AServlet implements Servlet {
// 无参数构造函数
public AServlet() {
System.out.println("AServlet 无参数构造方法执行了!");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("AServlet's init method execute");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("AServlet's service method execute");
}
/**
* 只是会执行一次
* Tomcat 服务器在销毁对象之前进行这个方法的执行
* 在这个方法中可以编写在销毁前面的准备
* 比如说在AServlet 对象中开启了一些资源,这些资源是流,可能是数据库连接,关闭服务器的时候,需要关闭相关的流,这些关闭的代码可以书写在这个地方
*/
@Override
public void destroy() {
System.out.println("AServlet's destroy method execute");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
13.1、Servlet 对象的生命周期可以类比于人的生命:
- Servlet 构造方法的执行,相当于人出生了
- Servlet init 方法的执行,标志着拟正在接受教育,被初始化
- Servlet service() 方法的执行,表示你已经开始工作了,为人类开始提供服务
- Servlet destroy() 方法的执行表示,在生命的最后的所得事情
13.2、关于servlet 类中方法的调用次数?
- 构造方法只会执行一次
- init 方法执行一次
- destroy 只会执行一次
- service 用户发送一次请求执行一次,发送多次请求,执行多次的方法
当创建了一个有参数的构造方法之后,这个时候没有创建无参数的构造方法的话是出现一系列的问题的;
此时会报 500 错误,在http 协议中这是一个服务器端的错误,所以在具体的开发过程中,是不建议自己来定义构造方法的,因为定义不好的时候,一不小心会导致无法实例化Servlet 对象的;
13.3、思考:init 构造方法几乎可以在同一时间同时执行,但是为什么需要写两个方法呢?合并到一起不行吗?
因为单独写了一个 init 方法之后,此时的init 方法中可以书写一些报错的信息,方便控制程序的执行;
在实际的开发中不建议写构造方法,因为有可能写一个有参数的构造方法,会导致一些莫名其妙的错误,此时的 init 方法的作用就体现出来了
13.4、init service destroy 方法中使用最多的是什么方法?
使用最多的是service 方法,
init 只是会执行一次;(初始化线程池等)
dextroy 使用的也是比较少的;
14、适配器的相关介绍
问题:早编写Servlet 类直接实现 Servlet 接口存在问题:
我们只是需要一个service 方法,但是直接世界 Servlet 类会产生很多没有什么用处的代码,或者使用的次数比较少的代码,代码比较丑陋,这个时候可以使用适配器设计模式;
适配器设计模式:手机不能直接插到220 V的电源上面,充电器头通过了适配,可以进行充电的操作;
在程序中写一个 GenericServlet 类
这是一个抽象类,什么方法使用的频繁,将其写为抽象方法,让其子类,即Servlet 类进行抽象方法的实现,可以使得代码的书写变得简洁些;
这样子就会达到了适配器的效果,使得代码的数量得到一定的减少,维护起来更加的方便
14.1、GenericServlet 类的改造,可以更加的方便子类程序的编写
思考:
- 提供了GenericServlet 之后, init 还是会执行吗?
肯定会执行的,子类没有,默认执行父类的 init 方法; - init 方法是谁调用的呢?
Tomcat 服务器会进行调用 - init 方法中的 ServletConfig 对象谁创建的,谁传过来的?
Tomcat 服务器创建的,然后传递了进去
Tomcat 服务器先创建了Servlet 对象建立,然后进行传递进去;