JavaWeb
本博客参照了韩顺平老师的 JavaWeb 课程讲义!
7 Tomcat
7.1 官方文档
7.1.1 地址: https://tomcat.apache.org/tomcat-8.0-doc/
7.2 WEB开发介绍
WEB,在英语中 web 表示网/网络资源(页面, 图片, css, js)意思,它用于表示 WEB 服务器(主机)供浏览器访问的资源
WEB 服务器(主机)上供外界访问的 web 资源分为:
- 静态web资源(如 html 页面):指web页面中供人们浏览的数据始终是不变。
- 动态web资源,比如 Servlet(java)、PHP 等
- 静态web 资源开发技术
- Html、CSS、js 等
- 常用动态web 资源开发技术:
- Servlet、SpringBoot、SpringvVC、 PHP、ASP.NET 等
7.3 JavaWeb开发技术栈图
-一图胜千言
7.4 BS 与 CS 开发介绍
7.4.1 BS开发
B: browser(浏览器,种类太多 ff, chrome, ie, edge)
S: Server(服务端,考虑很多)
示意图:
对BS的解读:
兼容性,因为浏览器的种类很多,发现你号的程序,在某个浏览器会出观问题,其它浏览器正常
安全性,通常情况下,Bs 安全性不如 CS 好控制
易用性,BS 好于CS,浏览器可直接下载
扩展性,BS相对统一,只需要写 Server
7.4.2 CS开发
C: Client(客户端)
S: Server(服务端)
示意图:
7.5 JavaWeb服务软件
7.5.1 JavaWeb服务器软件介绍
1.学习Javaweb 开发,需要先安装 JavaWeb 服务软件【我们把安装了 Javaweb 服务软件主机称为 web服务器/Javaweb 服务器】,然后在web 服务器中开发相应的 web 资源。[ Javaweb 服务器,Mysql服务器]
2.老韩提问:学习Javaweb 开发,为什么必须要先装 WEB 服务软件?
答:需要安装,理解 Tomcat 本质就是一个Java 程序,但是这个 Java 程序可以处理来自浏览器的 HTTP 请求,和我们前面讲的 java 网络服务(多人聊天,Server)
7.5.2 手写简单 Web 服务程序
1. 需求**:** 手写 MyWebServer.java , 让大家体验一下 JavaWeb 服务本质
提醒: 这里,我们需要使用到 Java基础(IO/网络),
http://localhost:9999 表示浏览器向localhost(127.0.0.1)表示本机的9999端口发出请求
2. 创建 hspedu_mytomcat 的 Java 应用程序.
3. 创建 D:\idea_java_projects\hspedu_mytomcat\src\hello.html
Hello, I AM WEB Server!
4. 创建 D:\idea_java_projects\hspedu_mytomcat\src\MyWebServer.java
1 | public class MyTomcat { |
5. 完成测试: 浏览器 http://localhost:9999/
7.5.3 常用 JavaWeb 服务软件
1. Tomcat:由 Apache 组织提供的一种 Web 服务器,提供对 jsp 和 Servlet 的支持。它是一种轻量级的 javaWeb 容器(服务器),也是当前应用最广的 JavaWeb 服务器(免费)。
2. Jboss:是一个遵从 JavaEE 规范的、它支持所有的 JavaEE 规范(免费)。
3. GlassFish: 由 Oracle 公司开发的一款 JavaWeb 服务器,是一款商业服务器,达到产品级质量(应用很少)。
4. Resin:是CAUCHO 公司的产品,是一个非常流行的服务器,对 servlet 和 JSP 提供了良好的支持, 性能也比较优良(收费)。
5. WebLogic【很猛】:是 Oracle 公司的产品,支持 JavaEE 规范, 而且不断的完善以适应新的开发要求,适合大型项目(收费,用的不多,适合大公司)。
7.6 Tomcat
7.6.1 Tomcat下载和安装
1. Tomcat 官方站点:**http://tomcat.apache.org/ **
2. 获取 Tomcat 安装程序包
tar.gz文件是Linux操作系统下的安装版本
zip文件是Windows系统下的压缩版本
3. 使用 zip 包安装 Tomcat
**4. which version https://tomcat.apache.org/whichversion.html ,**可以看到 Tomcat 仍然是支持 jsp 和 el
5. Tomcat 最好的小伙伴是 JSP+EL
7.6.2 Tomcat启动
windows系统:双击 bin 目录下的 startup.bat 文件
macos:
1 | 🌟进入tomcat安装目录的bin目录下 |
输入 http://localhost:8080/,显示如下界面代表安装成功, 默认在 8080 端口
在开发中,我们可以看一下哪些端口在监听: netstat -anb
7.6.3 Tomcat启动故障排除
1. 双击 startup.bat 文件,出现一个小黑窗口然后就没了,原因是因为没有配置好JAVA_HOME 环境变量Tomcat 本质是一个 Java 程序,所以要 jdk, 会去根据 JAVA_HOME 使用指定 jdk
2. JAVA_HOME 必须全大写
3. JAVA_HOME 中间必须是下划线
4. JAVA_HOME 配置的路径只需要配置到 jdk 的安装目录即可。不需要带上 bin 目录
5. 端口 8080 被占用 **[**查看端口netstat -anb,使用的非常多]
6. 如果其它服务程序占用了 8080 端口,可以关闭该服务,或者修改 Tomcat 服务的默认 端口 **8080 [**后面讲]
7.6.4 Tomcat 目录结构
解读
1. server.xml 用于配置 tomcat的基本设置(启动端口,关闭端口,主机名)
2. wex.xml 用于指定 tomcat 运行时配置(比如servlet等.)
3. webapps 目录是存放web应用,就是网站
7.6.5 catalina 启动 Tomcat(Windows)
1. 进入到 Tomcat 的 bin 目录下
2. 执行命令: catalina run
7.6.6 停止 Tomcat
进入 Tomcat 的 bin 目录下的 shutdown.bat 双击,就可以停止 Tomcat 服务器(windows)
7.6.7 修改 Tomcat 服务端口
1. Tomcat 目录下的 conf 目录,修改 server.xml 配置文件
2. 老韩说明: http://localhost , 默认是访问 80 端口,即 http://localhost**等价**http://localhost:80
7.6.8 Tomcat 服务中部署 WEB 应用
- 什么是Web应用
WEB应用是多个web资源的集合。简单的说,可以把web应用理解为硬盘上的一个目录,这个目录用于管理多个web资源。
web应用通常也称之为web应用程序,或web工程,通俗的说就是网站。
- Web应用组成
一个 WEB 应用由多个WEB 资源或其它文件组成,包括html 文件、css 文件、js文件、动态web页面、java 程序、支持jar 包、配置文件等。开发人员在开发 web 应用时,按照规定目录结构存放这些文件。否则,在把 web 应用交给 web 服务器管理时,不仅可能会使web 应用无法访问,还会导致 web 服务器启动报错。
- Javaweb程序/应用/工程目录结构
- 部署方式1:将web工程的目录拷贝到 Tomcat 的webapps 目录下
news web工程(目前都是静态资源 html, 图片)
将该news目录/文件夹 拷贝到 Tomcat 的webapps目录下
- 部署方式2:
在tomcat下的 conf/Catalina/localhost/ 目录中,添加配置文件,可以映射到其他位置的web应用(在其他地方寻找web应用,解决磁盘空间分配问题)
ROOT 的工程的访问:
在浏览器地址栏中输入访问地址如下:http://ip[域名]:port,没有web工程/ 应用名时,默认访问的是 ROOT 工程
在浏览器地址栏中输入的访问地址如下: http://ip[域名]:port/工程名/ ,没有资源名,则默认访问 index.jsp 页面
7.6.9 浏览器访问 Web 服务过程详解
7.6.9.1 回顾前面的 JavaWeb 开发技术栈图
7.6.9.2 浏览器访问 web 服务器文件 UML 时序图!!!
1. 说明
下面,我们对浏览器访问web服务器资源(html,css,图片,js)做详解,通过一个时序图加强对这个重要过程的理解,重要,核心
7.7 IDEA 开发 JavaWeb 工程
7.7.1 开发 javaweb 工程 & 配置 TomCat & 启动项目
1.需求/图解:使用 IDEA 开发 Javaweb 工程fishweb,并将网页部署到 fishweb 工程,看老师演示
7.7.2 注意事项和细节
1. 热加载选项说明
解读:
(1)on update action :表示当我们更新操作时,Tomcat 会自动更新类和资源(当jsp/html文件修改时,可以生效,但是如果你修改的java 文件,需要 Redepoly 才会生效)
(2) on frame deactivation :表示 IDEA 失去焦点((比如最小化),也会导致jsp/html 发生更新,但是java 修改了,还是需要 Redeploy
2. 端口修改
这里修改的端口, 只会影响到当前的项目,而不是去修改 server.xml
3.out 目录是什么
当tomcat 启动时,会生成 out 目录,该目录就是原项目资源的映射,我们浏览器访问的资源是 out 目录
4.当我们从外部拷贝资源到项目(图片,文件,js,css 等)
如果出现 404 不能访问错误,解决方式 rebulid project ->重启 Tomcat
7.7.3 JavaWeb 工程的目录介绍
8 动态 WEB 开发核心-Servlet
8.1 官方文档
8.1.1 地址: https://tomcat.apache.org/tomcat-8.0-doc/servletapi/index.html
8.1.3 Servlet和Tomcat的关系:一句话,Tomcat支持Servlet
8.2 为什么会出现 Servlet
提出需求**:** 请用你现有的html css javascript,开发网站,比如可以让用户留言**/购物/支付,** 你能搞定吗**?**
—不能,因为无法操作数据库
- 引入我们动态网页(能和用户交互)技术 ===> Servlet
- 对Java Web 技术体系的流程图改造说明(细化).[整体的概念]
8.3 什么是 Servlet
什么是Servlet
- Servlet 在开发动态 WEB 工程中,得到广泛的应用,掌握好 Servlet 非常重要,Servlet(基石)是 SpringMVC 的基础
Servlet(java 服务器小程序),它的特点:
- 他是由服务器端调用和执行的(一句话:是Tomcat解析和执行)
- 他是用java语言编号的,本质就是Java类
- 他是按照Servlet规范开发的(除 了tomcat->Servlet weblogic->Servlet)
- 功能强大,可以完成几乎所有的网站功能(在以前,我们老程员,使用Servlet开发网站)技术栈要求高
8.4 Servlet在JavaWeb项目位置
8.5 Servlet基本使用
8.5.1 Servlet开发方式说明
servlet3.0 前使用 web.xml , servlet3.0 版本以后**(**包括 **3.0)**支持注解, 同时支持 web.xml 配置
如何查看 servlet版本[如图]
讲解SpringBoot 时,我们用注解方式,从 ssm,springboot 后面全部使用注解
这专门讲 servlet, 为让大家更清晰知道 servlet 使用原理,老师用配置方式(说明: 原生的 Servlet 在项目中使用很少
不管使用哪种方式,本质都一样
8.5.2 快速入门- 手动开发 Servlet
需求说明
1、开发一个 Helloservlet
2、当浏览器 访问 http://localhost:8080/web应用名/helloServlet 时,后台输出 “hi HelloServelt”
- 具体步骤
- 编写类Helloservlet去实现 Servlet 接口
- 实现 service 方法,处理请求,并响应数据
- 在 web.xml 中去配置 servlet 程序的访问地址
1.创建 hspedu_servlet JavaWeb 工程,并配置好Tomcat
2.添加servlet-api.jar(在tomcat/lib下)到工程,因为servlet.jar不是jdk自带的,要引入
3.在src下包com.hspedu.servlet.HelloServlet.java,并实现Servlet接口
1 | package com.study.servlet; |
4.在web.xml配置HelloServlet,即:给HelloServlet提供对外访问地址
1 |
|
5.通过浏览器访问HelloServlet ,看是否正确(记住要redeploy[快]或者restart[慢])
http://localhost:8080/servlet/helloServlet
8.5.3 浏览器调用 Servlet 流程分析
一图胜千言
如果在web.xml中未查询到请求的资源,则会返回404错误!
Servlet常驻内存,属于单例模式
8.5.4 Servlet生命周期
● 主要有三个方法:
1. init():初始化阶段
2. service():处理浏览器请求阶段
3. destroy():终止阶段
- 示意图
初始化阶段
servlet 容器(比如:Tomcat)/加载 Servlet,加载完成后,Servlet 容器会创建一个 Servlet 实例
并调用 init()方法,init()方法只会调用一次,Servlet 容器在下面的情况装载 Servlet:
Servlet 容器 (Tomcat) 启动时自动装载某些 servlet,实现这个需要在 web.xml 文件中添加
1 1 表示装载的顺序在servlet 容器启动后,浏览器首次向 servlet 发送请求(这个前面说过)
Servlet 重新部署后(比如 tomcat 进行 redeploy 【*redeploy 会销毁所有的 servlet 实例!!!*】)。
浏览器再向 Servlet 发送第1次请求(或配置了tomcat启动自动装载)
处理浏览器请求阶段(service 方法)
每收到一个http 请求,服务器就会产生一个新的线程去处理[线程]
创建一个用于封装 HTTP 请求消息的 ServletRequest 对象和一个代表 HTTP 响应消息的ServletResponse 对象
然后调用 Servlet 的 service()方法并将请求和响应对象作为参数传递进去
终止阶段 destory 方法(体现 Servlet 完整的生命周期)
当web 应用被終止,或者 servlet 容器終止运行,或者Servlet 类重新装载时,会调用 destroy(方法
比如重启 tomcat,或者redeploy web 应用
8.5.5 GET 和 POST 请求的分发处理
开发 servlet,通常编写 doGet、doPost 方法。来对表单的get 和 post 请求进行分发处理
代码演示 HelloServlet.java register.html
- 创建 servlet\web\register.html
1 |
|
2. 修改 servlet\src\com\hspedu\servlet\HelloServlet.java
1 |
|
8.5.6 通过继承 HttpServlet 开发 Servlet
- HttpServlet 介绍
在实际项目中,都是使用继承 HttpServlet 类开发 Servlet 程序,更加方便
- HttpServlet 介绍
1、通过继承 HttpServlet 开发一个 HiServlet
2、当浏览器 访问 http://localhost:8080/web 应用名/hiServlet 时,后台输出 “hi HiServelt”
- 具体的开发步骤
- 编写一个类去继承 HttpServlet 类
- 根据业务需要重写 doGet 或 doPost 方法
- 到 web.xml 中的配置 Servlet 程序
- 应用实例
1.创建HiServlet.java
1 | package com.study.servlet; |
2.修改web.xml完成配置
1 | <servlet> |
3.完成测试
http://localhost:8080/servlet/hiServlet
8.5.7 IDEA 开发 Servlet 程序
- 说明
编手动开发 Servlet 需要程序员自己配置 Servlet ,比较麻烦,在工作中,直接使用 IDEA 开发 Servlet 会更加方便
- 应用实例
8.5.8 Servlet 注意事项和细节
- Servlet 是一个供其他 Java 程序(Servlet 引擎) 调用的 Java 类, 不能独立运行
- 针对浏览器的多次 Servlet 请求,通常情况下,服务器只会创建一个 Servlet 实例对象,也就是说 Servlet 实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web 容器退出/或者 redeploy 该 web 应用,servlet 实例对象才会销毁 【示意图】
在 Servlet 的整个生命周期内,init 方法只被调用一次。而对每次请求都导致 Servlet 引擎调用一次 servlet 的 service 方法。
对于每次访问请求,Servlet 引擎都会创建一个新的 HttpServletRequest 请求对象和一个新的 HttpServletResponse 响应对象,然后将这两个对象作为参数传递给它调用的 Servlet的 service()方法,service 方法再根据请求方式分别调用 doXXX 方法
如果在
元素中配置了一个 元素,那么 WEB 应用程序在启动时,就会装载并创建 Servlet 的实例对象、以及调用 Servlet 实例对象的 init()方法 应用场景:(定时发送邮件的服务/自动启动->完成任务)
8.6 Servlet - 注解方式
8.6.1 快速入门
- 具体步骤
编写类OkServlet去继承HttpServlet
注解方式配置OkServlet, 一个Servlet支持配置多个urlPattern
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package com.study.servlet.annotation;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 浦原
* 2023/7/7
* 14:25
* @version 1.0
* 1.注解方式配置
* @WebServlet是一个注解
* 2.源码:
* @Target({ElementType.TYPE})
* @Retention(RetentionPolicy.RUNTIME)
* @Documented
* public @interface WebServlet {
* String name() default "";
* String[] value() default {};
* String[] urlPatterns() default {};
* int loadOnStartup() default -1;
* WebInitParam[] initParams() default {};
* boolean asyncSupported() default false;
* String smallIcon() default "";
* String largeIcon() default "";
* String description() default "";
* String displayName() default "";
* }
* 3.urlPatterns 对应 <url-patterns><url-patterns/>
* 4.{"/ok1","/ok2"} 可以给OkServlet配置多个url-pattern
* 5.用户在浏览器可以这样访问:http://localhost:8080/servlet/ok2
*/
public class OkServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("注解方式 OkServlet doPost");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("注解方式 OkServlet doGet");
}
}
注解方式是如何实现的?
——Tomcat对包进行扫描,如果发现某个类被@WebServlet修饰,就说明该类是Servlet,就读取注解中的urlPatterns,然后进行下一步……(看请求的资源是否能从注解中找到……,找到则得到urlPatterns,去hashmap中看该servlet是否已经加载过……)
8.6.2 Servlet urlPattern 配置
8.6.2.1 精确匹配
——最简单、普遍的路径设置方式
配置路径 : @WebServlet(“/ok/zs”)
访问 servlet: localhost:8080/servlet/ok/zs
8.6.2.2 目录匹配
—— * 表示:零层、任意单层、任意多层
配置路径 : @WebServlet(“/ok/*”)
访问文件: localhost:8080/servlet/ok/aaa localhost:8080/servlet/ok/bbb
8.6.2.3 扩展名匹配
——必须保证后缀为 .action
配置路径 : @WebServlet(“**.action”)*
访问文件: localhost:8080/hsp/zs.action localhost:8080/hsp/ls.action
提示: @WebServlet(“/*.action”) , 不能带 / , 否则 tomcat 报错
8.6.2.4 任意匹配
配置路径 : @WebServlet(“/“) @WebServlet(“/**”)*
访问文件: localhost:8080/hsp/aaa localhost:8080/hsp/bbb localhost:8080/hsp/ccc
提醒: / 和 /*的配置, 会匹配所有的请求, 这个比较不实用
8.6.2.5 注意事项和使用细节
1、 当 Servlet 配置了 “/“, 会覆盖 tomcat 的 DefaultServlet, (当其他的 utl-pattern 都匹配不上时 ,都会走这个 Servlet, 这样可以拦截到其它静态资源,比如D:\hspedu_javaweb_temp\hspedu_servlet\web\hi.html [举例]查看:tomcat/conf/web.xml , 配置的 DefaultServlet
「The default servlet for all web applications, that serves static resources.这个默认的 servlet 是处理静态资源的,一旦拦截,静态资源不能处理」
2、当 Servelt 配置了 “/**”, 表示可以匹配任意访问路径*
3、提示: 建议不要使用 / 和 /*, 建议尽量使用精确匹配
4、优先级遵守: 精确路径 > 目录路径 > 扩展名路径 > /* > /
8.8 🌟关联篇: HTTP 协议
8.8.1请求头、响应头介绍
8.8.2HTTP状态码
当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码的英文为HTTP Status Code。
下面是常见的HTTP状态码:
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
HTTP状态码分类 | |
---|---|
分类 | 分类描述 |
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
HTTP状态码列表:
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
100 | Continue | 继续。客户端应继续其请求 |
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置”您所请求的资源无法找到”的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
GET请求行和请求头解析:
POST请求行和请求头解析:
何时使用 get / post ?
get和post方法功能类似的,使用建议:
1、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;
2、在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;
区别表现如下:
- get是从服务器上获取数据,post是向服务器传送数据。
- get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
- 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
- get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
- get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
若符合下列任一情况,则用POST方法:
- 请求的结果有持续性的副作用,例如,数据库内添加新的数据行。
- 若使用GET方法,则表单上收集的数据可能让URL过长。
- 要传送的数据不是采用7位的ASCII编码。
若符合下列任一情况,则用GET方法:
- 请求是为了查找资源,HTML表单数据仅用来帮助搜索。
- 请求结果无持续性的副作用。
- 收集的数据及HTML表单内的输入字段名称的总长不超过1024个字符。
原文链接:https://blog.csdn.net/qq_47443027/article/details/114696716
响应体:
常见状态码说明:
302
资源被转移了,返回给你302 还告诉你该去哪里找不见的资源,因此浏览器需要发送两次请求才能访问到原来的资源(只发生一次302的情况)
304
(在浏览器允许缓存的情况下)浏览器在请求某资源时,如果有该资源的缓存,就会把该资源的最后修改日期也发给服务器。
如果最后修改日期 = 服务器端该资源的最后修改日期,则服务器告诉浏览器请求的资源未修改过,返回304,不返回资源给浏览器,让浏览器去自己的缓存去找。
MIME类型
MIME 介绍:
MIME 是 HTTP 协议中数据类型。 MIME 的英文全称是”Multipurpose Internet Mail Extensions” 多功能 Internet 邮件扩充服务。 MIME 类型的格式是**”大类型/小类型”**,并与某一种文件的扩展名相对应
在响应包的Content-Type 就有指定
常见的 MIME 类型:
8.9 ServletConfig
8.9.1 ServletConfig 基本介绍
- ServletConfig 类是为 Servlet 程序的配置信息的类
- Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建
- Servlet 程序默认是第 1 次访问的时候创建, ServletConfig 在 Servlet 程序创建时, 就创建一个对应的 ServletConfig 对象(每个servlet都有一个对应的servletConfig)
8.9.2 ServletConfig 类能干什么
获取 Servlet 程序的 servlet-name 的值
获取初始化参数 init-param
获取 ServletContext 对象
8.9.3 ServletConfig
应用实例
● 需求: 编写 DBServlet.java 完成如下功能
在 web.xml 配置连接 mysql 的用户名和密码
在 DBServlet 执行 doGet()/doPost() 时,可以获取到 web.xml 配置的用户名和密码
示意图(思路分析)
1 | <servlet> |
8.10 ServletContext
——多个Servlet共享的数据空间
8.10.1 为什么需要 ServletContext
- 先看一个需求: 如果我们希望统计某个 web 应用的所有 Servlet 被访问的次数, 怎么办?
方案1-DB:
方案2-ServletContext:
8.10.2 ServletContext 基本介绍
ServletContext 是一个接口, 它表示 Servlet 上下文对象
一个 web 工程,只有一个 ServletContext 对象实例
ServletContext 对象 是在 web 工程启动的时候创建,在 web 工程停止的时销毁
ServletContext 对象可以通过 ServletConfig.getServletContext 方法获得对 ServletContext对象的引用,也可以通过 **this.getServletContext()**来获得其对象的引用。
由于一个 WEB 应用中的所有 Servlet 共享同一个 ServletContext 对象,因此 Servlet 对象之间可以通过 ServletContext 对象来实现多个 Servlet 间通讯。ServletContext 对象通常也被称之为域对象。【示意图】
8.10.3 ServletContext 可以做什么
获取 web.xml 中配置的上下文参数 context-param [信息和整个 web 应用相关, 而不是属于某个 Servlet]
获取当前的工程路径,格式: /工程路径 ==> 比如 /servlet. 其实就是/工程名
获取工程部署后在服务器硬盘上的绝对路径( 比 如 :D:\hspedu_javaweb\servlet\out\artifacts\servlet_war_exploded)
像 Map 一样存取数据, 多个 Servlet 共享数据
8.10.4 应用实例
1-获取工程相关信息
● 需求如下:
- 获取 web.xml 中配置的上下文参数 context-param
- 获取当前的工程路径, 格式: /工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
● 代码实现 - 具体看 项目中的代码.
1 |
|
8.10.5 应用实例 2-简单的网站访问次数计数器
……
8.11 HttpServletRequest
8.11.1 HttpServletRequest 介绍
——http请求中的信息都被封装在HttpServletRequest中
- HttpServletRequest 对象代表客户端的请求
- 当客户端/浏览器通过 HTTP 协议访问服务器时,HTTP 请求头中的所有信息都封装在这个对象中
- 通过这个对象的方法,可以获得客户端这些信息。
8.11.2 HttpServletRequest 类图
8.11.3 HttpServletRequest 常用方法
getRequestURI() 获取请求的资源路径
即 http://localhost:8080/servlet/loginServlet中的「servlet/loginServlet」
getRequestURL() 获取请求的统一资源定位符 ( 绝 对 路 径 )http://localhost:8080/servlet/loginServlet
getRemoteHost() 获取客户端的主机, getRemoteAddr()
getHeader() 获取请求头 request.getHeader(“Cookie(例)”) 可以获取http请求头中的任意信息
getParameter() 获取请求的参数
getParameterValues() 获取请求的参数(多个值的时候使用) , 比如 checkbox, 返回的数组
可以获取前端表单传来的数据,根据键(前端标签中的name属性)获取值
getMethod() 获取请求的方式 GET 或 POST
setAttribute(key, value); 设置域数据
getAttribute(key); 获取域数据
🌟getRequestDispatcher() 获取请求转发对象, 请求转发的核心对象
8.11.4 HttpServletRequest 应用实例
……
8.11.5 HttpServletRequest 注意事项和细节
- 获 取 doPost 参数中文乱码解决方案 , 注 意 setCharacterEncoding(“utf-8”) 要 写 在request.getParameter()前(在接受参数前设置字体 )。
- 注意:如果通过 PrintWriter writer, 有返回数据给浏览器,建议将获取参数代码写在writer.print() 之前,否则可能获取不到参数值(doPost)
- 处理 http 响应数据中文乱码问题 (改变编码为utf-8)
- 再次理解 Http 协议响应 Content-Type 的含义, 比如 text/plain(以文本方式解析) application/x-tar(表示返回的是文件,浏览器会以下载文件的方式处理)
8.11.7 请求转发
8.11.7.1 为什么需要请求转发
- 目前我们学习的都是一次请求, 对应一个 Servlet, 如图
- 但是在实际开发中,往往业务比较复杂,需要在一次请求中,使用到多个 Servlet 完成一个任务(Servlet 链, 流水作业) 如图:
8.11.7.2 请求转发说明
实现请求转发: 请求转发指一个 web 资源收到客户端请求后, 通知服务器去调用另外一个 web 资源进行处理
HttpServletRequest 对象(也叫 Request 对象)提供了一个 getRequestDispatcher 方法,该方法返回一个 RequestDispatcher 对象,调用这个对象的 forward 方法可以实现请求转发
request 对象同时也是一个域对象,开发人员通过 request 对象在实现转发时,把数据通过 request 对象带给其它 web 资源处理
setAttribute方法
getAttribute方法
removeAttribute方法
getAttributeNames方法
8.11.7.3 实现请求转发
请求转发原理示意图
8.11.7.4 请求转发应用实例
……
请求转发中,各个servlet可以共享request域对象的原因:
因为请求转发的方式为:
1 | // “/manageServlet”为发送的对象(转发给谁) |
8.11.7.5 请求转发注意事项和细节
🌟浏览器地址不会变化(地址会保留在第 1 个 servlet 的 url)
在同一次 HTTP 请求中,进行多次转发,仍然是一次 HTTP 请求
在同一次 HTTP 请求中,进行多次转发,多个 Servlet 可以共享 request 域/对象的数据(因为始终是同一个 request 对象)
可以转发到 WEB-INF 目录下(后面做项目使用)
不能访问当前 WEB 工程外的资源
因为浏览器地址栏会停止在第一个 servlet ,如果你刷新页面,会再次发出请求(并且会带数据), 所以在支付页面情况下,不要使用请求转发,否则会造成重复支付
8.11.8 课后作业
……
8.12 HttpServletResponse
8.12.1 HttpServletResponse 介绍
每次 HTTP 请求, Tomcat 会创建一个 HttpServletResponse 对象传递给 Servlet 程序去使用。
HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,如果需要设置返回给客户端的信息,通过 HttpServletResponse 对象来进行设置即可
8.12.2 HttpServletResponse 类图
8.12.3 向客户端返回数据方法
- 字节流 getOutputStream(); 常用于下载(处理二进制数据)
- 字符流 getWriter(); 常用于回传字符串
- (细节:)两个流同时只能使用一个。 使用了字节流,就不能再使用字符流,反之亦然,否则就会报错
8.12.4 向客户端返回数据应用实例
- 需求: 浏览器请求 , 返回 hello, world
……
8.12.5 向客户端返回数据注意事项和细节
- 处理中文乱码问题-方案 1
- 处理中文乱码问题-方案 2(常用,方便)
8.12.6 请求重定向
8.12.6.1 请求重定向介绍
请求重定向指: 一个 web 资源收到客户端请求后, 通知客户端去访问另外一个 web资源, 这称之为请求重定向
请求重定向原理示意图
8.12.6.2 请求重定向应用实例
- 需 求 : 演示请求重定向的使用当访问 DownServlet 下 载 文 件 , 重定向到DownServletNew 下载文件
1 | //1. sendRedirect 本质就会 返回 302 状态码 Location: /servlet/downservletNew |
8.12.6.3 请求重定向注意事项和细节
最佳应用场景:网站迁移, 比如原域名是 www.hsp.com 迁移到 www.hsp.cn , 但是百度抓取的还是原来网址.
浏览器地址会发生变化,本质是两次 http 请求.
不能共享 Request 域中的数据,本质是两次 http 请求,会生成两个 HttpServletRequest对象
不能重定向到 /WEB-INF 下的资源
可以重定向到 Web 工程以外的资源, 比如 到 www.baidu.com
重定向有两种方式, 推荐使用第 1 种.
动态获取到 application context(这个是指该项目在tomcat上运行时的项目名称,重定向时每次都需要填上,因此在修改时会比较麻烦,我们可以采取动态获取的方式简化它
使用方法:getServletContext().getContextPath()获取即可)
8.12.7 课后作业
编写一个 MyPayServlet , 能够接收到提交的数据
编写一个简单的支付页面 pay.html(如图)
如果支付金额大于 100, 则重定向到 payok.html, 否则重定向到原来的 pay.html
……
10 手动实现 Tomcat 底层机制+ 自己设计 Servlet
10.1 先看一个小案例, 引出对 Tomcat 底层实现思考
10.1.1 完成小案例
- 我们准备使用 Maven 来创建一个 WEB 项目, 老师先简单给小伙伴介绍一下 Maven 是什么, 更加详细的使用,我们还会细讲, 现在先使用一把
- 先创建一个 Maven 的 Web 项目 hsp-tomcat
- 配置阿里 maven 镜像
在maven的settings.xml文件中修改mirror标签中的内容即可
- 修改 D:\java_projects2\hsp\pom.xml
1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
- 创建 D:\java_projects2\hsp\src\main\webapp\cal.html
1 |
|
创建 java 目录,存放 java 源文件.
创建 CalServlet.java
修改 web.xml , 配置 Servlet
1 |
|
- 修改CalServlet.java, 完成计算任务
1 | package com.donn.servlet; /** |
- 创 建 工 具 类\utils\WebUtils.java
1 | package com.donn.utils; |
10.1.3 完成测试
10.1.3.1 配置 tomcat
10.1.3.2 启动 tomcat
10.1.3.3 浏览器访问: http://localhost:8080/cal.html
10.1.4 思考问题: Tomcat 底层实现 和 调用到 Servlet 流程?
10.1.5 我们的目标:
不用 Tomcat, 不用系统提供的 Servlet, 模拟 Tomcat 底层实现并能调用我们自己设计的 Servle, 也能完成相同的功能
10.2 🌟Tomcat 整体架构分析
10.2.1 一图胜千言
● 说明: Tomcat 有三种运行模式(BIO, NIO, APR) , 因为老师核心讲解的是 Tomcat 如何接收客户端请求, 解析请求, 调用 Servlet , 并返回结果的机制流程, 采用 BIO 线程模型来模拟.[绘图]
10.4 手动实现 Tomcat 底层机制+ 自己设计 Servlet
10.4.1 实现任务阶段 1- 编写自己 Tomcat, 能给浏览器返回 Hi, Hspedu
10.4.1.1 基于 socket 开发服务端-流程
10.4.1.2 需求分析
- 需求分析如图, 浏览器请求 http://localhost:8080/??, 服务端返回 hi , donn
10.4.1.3 分析+代码实现
● 分析示意图
● 代码实现
- 创 建DonnTomcatV1.java
1 | package com.donn.tomcat; |
10.4.1.4 测试 浏览器 : http://localhost:8081/
10.4.1.5 问题分析: 没有使用 BIO 线程模型, 没有实现多线程, 性能差
10.4.2 实现任务阶段 2__ 使用 BIO 线程模型, 支持多线程
10.4.2.1 BIO 线程模型介绍
10.4.2.2 需求分析/图解
- 需求分析如图, 浏览器请求 http://localhost:8081, 服务端返回 hi , donn, 后台donntomcat 使用 BIO 线程模型,支持多线程=> 对前面的开发模式进行改造
10.4.2.3 分析+代码实现
示意图:
创建线程类:
1 | package com.donn.tomcat.handler; |
调用线程类:
1 | package com.donn.tomcat; |
10.4.2.5 问题分析: HspTomcat 只是简单返回结果, 没有和 Servlet、 web.xml 关联
10.4.3 实现任务阶段 3- 处理 Servlet
10.4.3.1 Servlet 生命周期-回顾
10.4.3.2 需求分析/图解
● 需求分析如图, 浏览器请求 http://localhost:8080/hspCalServlet, 提交数据, 完成计算任务, 如果 servlet 不存在, 返回 404
10.4.3.3 分析+代码实现
● 分析示意图
实现:
1 | package com.donn.tomcat.http; |
回顾 Tomcat 工作架构图
11 WEB 工程路径专题
11.3 WEB 工程路径注意事项和细节
11.3.1 注意事项和细节说明
- Web 工程的相对路径和绝对路径:
相对路径:
● .表示当前目录
● ..表示上一级目录
● 资源名 表示当前目录的资源名
绝对路径: http://ip:port/工程路径/资源路径
在实际开发中, 路径都使用绝对路径, 而不是相对路径
在 web 中 / 斜杠 如果被浏览器解析, 得到的地址是: http://ip[域名]:port/
比如: <ahref=”/“>斜杠
在 web 中 / 斜杠如果被服务器解析,得到的地址是: **http://ip[域名]:port/工程路径/**,你也可以理解成 /工程路径/
下面的几种情况就是如此:
●
● servletContext.getRealPath(“/“); ==> 是得到执行路径/工作路径
● request.getRequestDispatcher(“/“);
在 javaWeb 中 路径最后带 / 和不带 / 含义不同, 一定要小心,比如
< a href=”/a/servlet03”>网址 中的servlet03 表示资源
< a href=”/a/servlet03/“>网址 中的servlet03 表示路径
🌟特别说明: 重定向 response.sendRediect(“/“); 这条语句虽然是在服务器执行的, 但是,服务器是把斜杠 / 发送给浏览器解析。 因此得到地址 http://ip[域名]:port/
小结: 在编写资源路径时 , 考虑这么几点
(1) 这个路径前面有没有 /
(2) 这个路径在哪里被解析 [服务器还是浏览器] , 如果前面有 / , 并且是在 浏览器被解析的 被解析成 http://ip:port/ , 如果在服务器端被解析 , 被解析成 /工程路径/
(3) 如果这个路径, 前面没有 / , 并且在浏览器被解析, 则以浏览器当前的地址栏 去掉资源部分, 作为一个相对路径,再拼接这条路径.
(4) 这个路径, 最后有没有 / , 如果最后有/ 表示路径, 如果没有 / 表示资源
12 Web 开发会话技术 Cookie&Session
12.1 会话
12.1.1 基本介绍
什么是会话?
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个 web 资源,然后关闭浏览器,整个过程称之为一个会话。
会话过程中要解决的一些问题?
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,服务器要想办法为每个用户保存这些数据
例如:多个用户点击超链接通过一个 servlet 各自购买了一个商品,服务器应该想办法把每一个用户购买的商品保存在各自的地方,以便于这些用户点结帐 servlet 时,结帐servlet 可以得到用户各自购买的商品为用户结帐
12.1.2 会话的两种技术
12.1.2.1 Session
12.1.2.2 Cookie
12.2 Cookie 有什么用
思考问题 1-抛砖引玉☞
大家在访问某个网站的时候,是否能看到提示你上次登录网站的时间,而且要注意的是不同用户上次登录的时间肯定是不一样的,这是怎么实现的?
思考问题 2-抛砖引玉☞
大家在访问某个购物网站的时候,是否能看到提示你曾经浏览过的商品,不同用户浏览过的商品肯定不一样,这是怎么实现的?
解决之道—cookie 技术
Cookie(小甜饼)是客户端技术,服务器把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 web 资源时,就会带着各自的数据去。这样,web 资源处理的就是用户各自的数据了。【简单示意图】
12.3 cookie 介绍
12.3.1 二说 cookie
- Cookie 是服务器在客户端保存用户的信息, 比如登录名, 浏览历史等, 就可以以 cookie方式保存.
- Cookie 信息就像是小甜饼(cookie 中文)一样,数据量并不大,服务器端在需要的时候可以从客户端/浏览器读取(http 协议),可以通过图来理解
- 再次说明: cookie 数据是保存在浏览器的
12.3.2 cookie 可以用来做啥
保存上次登录时间等信息
保存用户名,密码, 在一定时间不用重新登录
网站的个性化,比如定制网站的服务,内容
12.4 cookie 基本使用
12.4.1 文档: java_ee_api_中英文对照版.chm
12.4.2 cookie 常用方法
Cookie 有点象一张表(K-V), 分两列, 一个是名字, 一个是值, 数据类型都是 String
如何创建一个 Cookie(在服务端创建的)
Cookie c=new Cookie(String name,String val); c.setMaxAge();//保存时间
如何将一个 Cookie 添加到客户端
response.addCookie(c);
如何读取 cookie(在服务器端读取到 cookie 信息)
request.getCookies();
12.7 cookie 生命周期
12.7.1 介绍
- Cookie 的生命周期指的是如何管理 Cookie 什么时候被销毁(删除)
- setMaxAge()
● 正数,表示在指定的秒数后过期 过期后,浏览器不会删除该cookie,只是不再携带该cookie
● 负数,表示浏览器关闭, Cookie 就会被删除(默认值是-1)
● 0, 表示马上删除 Cookie 设置为0后,浏览器会把该cookie直接删除
12.8 cookie 有效路径
12.8.1 有效路径规则
- Cookie 有效路径 Path 的设置
- Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器,哪些不发。 path属性是通过请求的地址来进行有效的过滤
- 规则如下:
没设置默认为项目工程路径
12.10 Cookie 注意事项和细节
- 一个 Cookie 只能标识一种信息, 它至少含有一个标识该信息的名称(NAME) 和设置值(VALUE) 。
- 一个 WEB 站点可以给一个浏览器发送多个 Cookie,一个浏览器也可以存储多个 WEB 站点提供的 Cookie。
- cookie 的总数量没有限制,但是每个域名的 COOKIE 数量和每个 COOKIE 的大小是有限制的 (不同的浏览器限制不同, 知道即可) , Cookie 不适合存放数据量大的信息。
- 注意,删除 cookie 时,path 必须一致,否则不会删除
- Java servlet 中 cookie 中文乱码解决
如果存放中文的 cookie, 默认报错, 可以通过 URL 编码和解码来解决, 不建议存放中文的 cookie 信息
1 | //通过将中文转化成utf-8形式的String,便可以将转化的结果放入cookie中了 |
12.11 session 有什么用
思考两个问题—抛砖引玉
- 不同的用户登录网站后,不管该用户浏览该网站的哪个页面,都可显示登录人的名字,还可以随时去查看自己的购物车中的商品, 是如何实现的?
- 也就是说,一个用户在浏览网站不同页面时,服务器是如何知道是张三在浏览这个页面,还是李四在浏览这个页面?
- 方案1 : 可以把每个用户的信息都存到服务器的一个数据库中,再用一个‘🔑’来确定哪个用户对应db中的哪条记录
- 方案2 : 也可以将用户信息直接保存到cookie中,但是当切换用户后cookie内容不变,不安全;而且cookie作为传输的数据容易泄露,不便于传输敏感信息
解决之道—session 技术
Session 是服务器端技术,服务器在运行时为每一个用户的浏览器创建一个其独享的session 对象/集合( 其实相当于前面说的方案1 )
由于 session 为各个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的 session 中读取/添加数据, 从而完成相应任务
12.12 session 基本原理
12.12.1 Sesson 原理示意图
- 当用户打开浏览器,访问某个网站, 操作 session 时,服务器就会在内存(在服务端)为该浏览器分配一个 session 对象,该 session 对象被这个浏览器独占, 如图⬆️
- 这个 session 对象也可看做是一个容器/集合,session 对象默认存在时间为 30min(这是在tomcat/conf/web.xml),也可修改
12.12.2 Session 可以做什么
- 网上商城中的购物车
- 保存登录用户的信息
- 将数据放入到 Session 中, 供用户在访问不同页面时, 实现跨页面访问数据
- 防止用户非法登录到某个页面
- …..
12.12.3 如何理解 Session
- session 存储结构示意图
- 你可以把 session 看作是一容器类似 HashMap,有两列(K-V),每一行就是 session 的一个属性。
- 每个属性包含有两个部分,一个是该属性的名字(String),另外一个是它的值(Object)
12.13 session 常用方法
12.13.1 网上去找文档
12.13.2 Session 的基本使用
创建/获取 Session, API 一样
- HttpSession session = request.getSession();
- 第 1 次调用是创建 Session 会话, 之后调用是获取创建好的 Session 对象
向 session 添加属性session.setAttribute(String name,Object val);
从 session 得到某个属性Object obj=session.getAttribute(String name);
从 session 删除调某个属性:
- hs.removeAttribute(String name);
isNew(); 判断是不是刚创建出来的 Session
每个 Session 都有 1 个唯一标识 Id 值。 通过 getId() 得到 Session 的会话 id 值,
即cookie中的JSESSIONID
12.14 session 底层实现机制
12.14.1 原理分析图(一图胜千言)
● session 底层实现机制图解(重要)
如果在本次会话中,服务器为浏览器创建了session空间(说明产生了一组新的「sessionId + session体」的结构出现),那么服务器会让浏览器将set sessionid信息放入cookie中
12.14.3 Session 实现原理动画
● 服务器是如何实现一个 session 为一个用户浏览器服务的
12.15 session 生命周期
12.15.1 Session 生命周期-说明
public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位) ,超过指定的时长, Session 就会被销毁。
值为正数的时候,设定 Session 的超时时长。
负数表示永不超时
public int **getMaxInactiveInterval()**获取 Session 的超时时间
public void invalidate() 让当前 Session 会话立即无效
如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以 Session默认时长为准,Session 默认的超时为 30 分钟, 可以在 tomcat 的 web.xml 设置
Session 的生命周期指的是 :客户端/浏览器两次请求最大间隔时长,而不是累积时长。**即当客户端访问了自己的 session,session 的生命周期将从 0 开始重新计算。**(解读: 指的是同一个会话两次请求之间的间隔时间)
🌟底层: Tomcat 用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值,则将该会话销毁
14 JavaWeb 三大组件之监听器 Listener
14.1 官方文档
14.1.1 文档……
14.2 Listener 监听器介绍
Listener 监听器它是 JavaWeb 的三大组件之一。 JavaWeb 的三大组件分别是: Servlet 程序、 Listener 监听器、 Filter 过滤器
Listener 是 JavaEE 的规范,就是接口
监听器的作用是,监听某种变化(一般就是对象创建/销毁, 属性变化), 触发对应方法完成相应的任务
JavaWeb 中的监听器(共八个), 目前最常用的是 ServletContextListener
14.3 JavaWeb 的监听器
14.3.1 ServletContextListener 监听器
作用: 🌟监听 ServletContext 创建或销毁(当我们 Web 应用启动时, 就会创建 ServletContext),即生命周期监听, 应用场景
- 加载初始化的配置文件; 比如 spring 的配置文件
- 任务调度(配合定时器 Timer/TimerTask)
相关方法
1 | void contextInitialized(ServletContextEvent sce) //创建 Servletcontext 时触发 |
- 应 用 实 例 创 建 MyServletContextListener.java
1 | public class MyServletContextListener implements ServletContextListener { |
- 在 web.xml 配置 MyServletContextListener
14.3.2 ServletContextAttributeListener 监听器
- 作用: 🌟监听 ServletContext 属性变化
- 相关方法
1 | void attributeAdded(ServletContextAttributeEvent event) //添加属性时调用 |
- 使用少,再给大家举个例(后面的监听器类似)
创 建MyServletContextAttributeListener.java
1 | public class MyServletContextAttributeListener implements ServletContextAttributeListener { |
14.3.3 其它监听器-使用较少
14.3.3.1 HttpSessionListener 监听器
- 作用: 🌟监听 Session 创建或销毁, 即生命周期监听
- 相关方法
1 | void sessionCreated(HttpSessionEvent se) //创建 session 时调用 |
- 使用方法和前面一样, 可以用于监控用户上线,离线
14.3.3.2 HttpSessionAttributeListener 监听器
- 作用: 🌟监听 Session 属性的变化
- 相关方法
1 | void attributeAdded(ServletRequestAttributeEvent srae) //添加属性时 |
- 使用少 , 使用方法和前面一样。
14.3.3.3 ServletRequestListener 监听器
ServletRequestListener 监听器
作用:监听 Request 创建或销毁,即 Request 生命周期监听
🌟可以用来监控, 某个 IP 访问我们网站的频率, 日志记录 ,访问资源的情况
14.3.3.4 ServletRequestAttributeListener 监听器
- 作用: 监听 Request 属性变化
……
14.3.3.5 HttpSessionBindingListener 感知监听器
……
14.3.3.6 HttpSessionActivationListener 感知监听器
……
15 JavaWeb 三大组件之 过滤器 Filter
15.1 官方文档
15.1.1 文档: ……
15.2 Filter 过滤器说明
15.2.1 为啥要过滤器-需求示意图
● 一图胜千言
15.2.2 过滤器介绍
- Filter 过滤器它是 JavaWeb 的三大组件之一(Servlet 程序、 Listener 监听器、 Filter 过滤器)
- Filter 过滤器是 JavaEE 的规范,是接口
- Filter 过滤器它的作用是:拦截请求,过滤响应。
- 应用场景
- 权限检查
- 日志操作
- 事务管理
15.3 Filter 过滤器基本原理
● 一图胜千言
15.4 Filter 过滤器快速入门
● 需求: 在 web 工程下, 有后台管理目录 manage, 要求该目录下所有资源(html、 图片、jsp 、 Servlet 等) 用户登录后才能访问
听老师说明, 完成模块的套路/流程[多年的体会]
- 先完成一个正确的流程-看到一个效果-> 写后面代码就可以验证
- 加入其它的功能[加入 session,验证合法性]
- 完善功能
1 | package com.hspedu.filter; |
●在 web.xml 配置过滤器
1 | <!--老师解读:filter一般写在其它servlet的前面 |
15.5 Filter 过滤器 url-pattern
1、 url-pattern : Filter 的拦截路径, 即浏览器在请求什么位置的资源时, 过滤器会进行拦截过滤
2、精确匹配
3、 目录匹配
4、 后缀名匹配
5、 Filter 过滤器它只关心请求的地址是否匹配, 不关心请求的资源是否存在
15.6 Filter 过滤器生命周期
● Filter 生命周期图解
1 | package com.hspedu.filter; |
🌟 如果后面的请求目标资源(jsp,servlet..) 会使用到request 和 response,那么会继续传递——即使访问的url不同了,但是只要还是被这个filter拦截,那么就是传递相同的request 和 response
15.7 FilterConfig
● FilterConfig 接口图
● FilterConfig 说明
- FilterConfig 是 Filter 过滤器的配置类
- Tomcat 每次创建 Filter 的时候,也会创建一个 FilterConfig 对象,这里包含了 Filter 配置文件的配置信息。
- FilterConfig 对象作用是获取 filter 过滤器的配置内容
● 应用实例 FilterConfig_.java
1 | /** |
- 配置 web.xml
1 | <filter> |
15.8 FilterChain 过滤器链
15.8.1 一句话: FilterChain: 在处理某些复杂业务时, 一个过滤器不够, 可以设计多个过滤器共同完成过滤任务, 形成过滤器链。
15.8.2 基本原理示意图
15.8.3 应用实例 AFilter.java BFilter.java hi.jsp web.xml
- 需求: 演示过滤器链的使用
15.8.4 FilterChain 注意事项和细节
多个 filter 和目标资源在一次 http 请求, 在同一个线程中
当一个请求 url 和 filter 的 url-pattern 匹配时, 才会被执行, 如果有多个匹配上, 就会顺序执行, 形成一个 filter 调用链(底层可以使用一个数据结构搞定)
多个 filter 共同执行时,因为是一次 http 请求, 使用同一个 request 对象
多个 filter 执行顺序, 和 web.xml 配置顺序保持一致.
chain.doFilter(req, resp)方法 将执行下一个过滤器的 doFilter 方法, 如果后面没有过滤器,则执行目标资源。
小结: 注意执行过滤器链时, 顺序是(用前面的案例分析) Http请求 -> A 过滤器 dofilter()-> A 过滤器前置代码 -> A 过滤器 chain.doFilter() -> B 过滤器 dofilter() -> B 过滤器前置代码 -> B过滤器 chain.doFilter() -> 目标文件 -> B过滤器后置代码 -> A过滤器后置代码 ->返回给浏览器页面/数据
🌟后置代码指:过滤器中 doFilter()方法中,chain.doFilter()之后的代码
18 线程数据共享和安全 -ThreadLocal
18.1 什么是 ThreadLocal
- ThreadLocal 的作用, 可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.
- ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!]
- ThreadLocal 可以像 Map 一样存取数据,key 为当前线程, get 方法
- 每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个 ThreadLocal 对象实例
- 每个 ThreadLocal 对象实例定义的时候,一般为 static 类型
- ThreadLocal 中保存数据,在线程销毁后,会自动释放
18.2 快速入门 ThreadLocal
● 需求: 演示 ThreadLocal (作用: 在一个线程中, 共享数据(线程安全))的使用-画图
1 | public class T1 { |
18.3 ThreadLocal 源码解读+画图
- 老韩说明: 这里涉及到的弱引用,涉及到知识点很多,暂不深入
一个Thread有一个 threadLocals(TheadLocalMap类型) ,threadLocals中有一个table,table中有许多桶,每个桶都是Entry类型,(Entry的key是ThreadLocal类型,value是你存进去的数据)
⚠️疑问:
!!!threadLocals中只有一个table,table中存着该线程存放的许多Entry,问:为什么不把Entry直接放在threadLocals下面,而是要多加一层table?
分层、用于未来扩展吧?