[toc]
javaWeb
基础概念
-
Javaweb
: 使用Java开发的基于互联网的项目 -
软件架构
:- C/S:Client/Server 客户端/服务器端
- 在用户本地有一个客户端程序,在远程有一个服务器端程序
- 如:QQ,迅雷
- 优点
- 用户体验好
- :
- 开发、安装,部署,维拒麻烦
- B/S: Browser/ Server 浏览器/服务器
- 只需要通过浏览器就可以通过不同的网址,客户访问不同的服务器程序
- 优点
- 开发、安装,部署,维拒简单
- 缺点:
- 如果应用过大,则用户的体验可能会受到影响
- 对硬件要求过高
- C/S:Client/Server 客户端/服务器端
-
B/S架构详解
-
资源分类
-
静态资源
- 来使用静态网页开发技术发布的资源.
- 特点:
- 所有用户访问,得到的结果是一样的。
- 如:文本,图片,音频、视频,HTML, CSS, Javascript
- 如果用户请求的是静态资源,那么服务器会直接将静态资源发送给浏览器。浏览器中内置了静态资源的解析引率,可以展示静态资源
-
动态资源
-
使用动态网页及时发布的资源。
-
特点
- 所有用户访问,得到的结果可能不一样。
- 如: jsp/servlet, php, asp ...
- 如果用户请求的是动态资源,那么服务器会执行动态资源,转换为静态资源,再发送给浏览器
-
-
-
-
网络通信三要素
- IP:电子设备(计算机)在网络中的唯一标识。
- 端口:应用程序在计算机中的唯一标识。0~65536
- 一般不建议使用0~1024之间的端口,这些端口很可能会被系统所占用
- 传输协议:规定了数据传输的规则
- 基础协议
- tcp:安全协议,三次握手。速度稍慢
- udp:不安全协议。速度快
- 基础协议
-
web服务器软件
- 服务器:安装了服务器软件的计算机
- 服务器软件:接收用户的请求,处理请求,做出响应
- web服务器软件:接收用户的请求,处理请求,做出响应。
- 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
- web容器
- 常见的java相关的web服务器软件:
- webLogic: oracle公司,大型的JavaEE服务器,支持所有的javaEE规范,收费的。
- websphere:IBM公司,大型的JavaEE服务器,支持所有的Javale规范,收费的。
- JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的Javaee规范,使用免费,文档收费。
- Tomcat: Apache基金组织,中小型JavaEE服务器,仅支持少量的JavaEE规范,开源免费。
Tomcat 笔记
初始安装配置
配置阶段
首先安装Tomcat需要配置环境变量
JAVA_HOME : E:\JDK_eclipse\jik_8(注释: 自己的JDK安装位置)
在path中添加 %JAVA_HOME%\bin;
然后分别添加变量TOMCAT_HOME 和 CATALINA_HOME 他们的值均为 Tomcat 的解压路径 例如我的就是 E:\Rescource\tomcat\apache-tomcat-9.0.48
然后在path中添加 %CATALINA_HOME%\lib;%CATALINA_HOME%\bin
然后打开黑窗口 win + R 输入 cmd 使用cd 命令切换到自己的Tomcat安装位置下面的bin文件夹下面。
注意: 当我们配置过环境变量之后,所有的 %CATALINA_HOME% 就等价 E:\Rescource\tomcat\apache-tomcat-9.0.48
可以直接使用下面的命令,只不过是需要将路径换成自己的Tomcat安装路径
cd /d %CATALINA_HOME%\bin
切换到相关目录后 输入 service install
只不过是我已经安装过了所以最后会出现一个Failed 的提示。 首次安装不会出现Failed的提示 会出现跟下面类似的输出内容。
当你再次尝试输入 service install
的时候还有一下结果,最后会出现一个Failed 的提示,影响不大。
基本配置阶段到这里就结束了。
端口配置(初次看可以忽略)
配置端口的文件为%CATALINA_HOME%\config\serve.xml
在文件的大概69行附近,会发现如下上面这个样子的代码(推荐用vscode打开该文件,因为vscode会对文件进行渲染,方便我们阅读),port
里面的参数,就是我们要设置的端口号
,我们可以改成我们想要的端口,范围是(0~65536),不过建议不要用0-1024之间的端口(80除外),因为1024之间的端口很可能是系统要用的端口,所以一般设置在1024~
65536之间。
==注意==:在设置的之前,我们可以去搜索 引擎当中查一下我们即将设置的端口号是不是某个软件的默认端口号,尽量两个端口之间不要重复,否则会起冲突。
==推荐==:使用80端口,因为80端口就是http协议的端口,如果使用80端口之后,我们在访问的时候默认不用加端口号,就可以直接访问。如图所示:直接在地址栏中输入localhost
然后回车就行
启动阶段
在资源管理器(我的电脑)当中打开 我们安装的Tomcat的文件夹下面的 bin文件夹
E:\Rescource\tomcat\apache-tomcat-9.0.48\bin
双击下面的 Tomcat9w.exe
点击START进行启动我们的Tomcat ,如果START上面的service status显示为 Stated
则说明我们的Tomcat已经正常启动了。
打开浏览器 搜索 localhost:8080
即可进入Tomcat默认界面(注:我的地址改成了906,默认的端口为8080)
启动
Tomcat三种启动方式
文件夹位置: %CATALINA_HOME%\bin
Tomcat的启动文件都在 %CATALINA_HOME%\bin
文件夹下面,下面说明的启动文件均在这个文件夹下面
启动方式:
第一种: 双击
startup.bat
进行启动第二种:双击
tomcat.exe
进行启动第三种: 双击
Tomcat9w.exe
进行启动 (推荐) 在打开的窗口中点击start关闭方式:
对应第一二种:
- 双击
shutdown.bat
- 直接关闭黑窗口
对应第三种:
- 双击
Tomcat9w.exe
进行启动 (推荐) 在打开的窗口中点击stop
第一二种方式启动的缺点是双击之后打开的黑窗口不能关闭,关闭之后Tomcat服务自动就关闭了,第三种无影响。
第一二种启动方式启动之后黑窗口可能会出现中文乱码,解决方式:
报错
查看Tomcat日志
文件夹位置:%CATALINA_HOME%\logs
Tomcat的所有日志是放在%CATALINA_HOME%\logs
文件夹下面的,下面说的文件都在这个文件夹下;
Tomcat正常启动的日志是放在 catalina.启动日期.log
文件里面的以追加的形式存放;
Tomcat报错日志是放在 commons-daemon.2021-06-25.log
文件下面 其中中间部分为日期;
例如:
正常的启动日志:
文件为:
%CATALINA_HOME%\logs\catalina.2021-06-25.log
红色标注的区域为一次正常的Tomcat启动日志,而上面的则是上一次的启动日志,日志是以追加的形式添加到文件里面的。
报错的输出日志:
文件为:
%CATALINA_HOME%\logs\commons-daemon.2021-06-25.log
一个红色区域为一次报错,同样也是以追加形式存放的
启动失败
一直启动失败其中报错原因如下:
报错文件位置:
%CATALINA_HOME%\logs\commons-daemon.2021-06-25.log
说是找不到指定程序,然后还有JVM DLL加载失败,就是所找不到Java启动的虚拟机了,这时候就需要使用自己本机上面的虚拟机了。
使用自己的虚拟机方法如下:
在Tomcat9w中设置Java虚拟机为自己的jre下面的虚拟机,具体地址为 JRE下面的server下面的jvm.dll
还可以将自己的Tomcat内存调大:还是上面的图二中下面两个输入框中的数值
startup.bat启动中文乱码问题
文件位置: %CATALINA_HOME%\conf\logging.properties
修改上述文件中输出内容的编码为GBK就行了,其默认配置为utf-8
修改的具体代码如下,首先找到 java.util.logging.ConsoleHandler.encoding
然后将其值改为GBK:
java.util.logging.ConsoleHandler.encoding = GBK
用户
Tomcat中manage设置
文件位置: %CATALINA_HOME%\conf\tomcat-users.xml
文件中可自行添加自己需要的用户,添加方式如下:
==注意: <!-- --> 中间的内容为注释==
<!--
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
-->
<user username="ziop" password="123456" roles="manager-gui"/>
具体用户权限解释如下:
一个user节点表示单个用户,属性username和password分别表示登录的用户名和密码,属性roles表示该用户所具备的权限。
user节点的roles属性值与role节点的rolename属性值相对应,表示当前用户具备该role节点所表示的角色权限。当然,一个用户可以具备多种权限,因此属性roles的值可以是多个rolename,多个rolename之间以英文逗号隔开即可。rolename的属性值并不是随意的内容,否则Tomcat怎么能够知道我们随便定义的rolename表示什么样的权限呢。
实际上,Tomcat已经为我们定义了4种不同的角色——也就是4个rolename,我们只需要使用Tomcat为我们定义的这几种角色就足够满足我们的工作需要了。以下是Tomcat Manager 4种角色的大致介绍(下面URL中的*为通配符):
manager-gui 允许访问html接口(即URL路径为/manager/html/*) manager-script 允许访问纯文本接口(即URL路径为/manager/text/*) manager-jmx 允许访问JMX代理接口(即URL路径为/manager/jmxproxy/*) manager-status 允许访问Tomcat只读状态页面(即URL路径为/manager/status/*)
从Tomcat Manager内部配置文件中可以得知,manager-gui、manager-script、manager-jmx均具备manager-status的权限,也就是说,manager-gui、manager-script、manager-jmx三种角色权限无需再额外添加manager-status权限,即可直接访问路径/manager/status/*。
部署项目
部署项目的方式:
直接将项目放到webapps目录下即可。
-
位置 :
%CATALINA_HOME%\webapps
-
/he11o:项目的访问路径->虚拟目录
-
简化部署:
- 将项目打成一个war包,再将war包放置到 webapps目录下。
- 运行tomcat的时候war包会自动解压缩
- 将项目打成一个war包,再将war包放置到 webapps目录下。
在server.xml文件里面设置虚拟目录 (==不推荐使用==)
-
配置文件位置:
%CATALINA_HOME%\conf\server.xml
-
在配置文件的
<host>标签中设置虚拟目录的位置
-
配置内容如下:
-
<Context docBase = "E:\test" path="/test"/>
-
docBase
: 存放项目的文件夹路径 -
path
: 虚拟目录,我们在浏览器中访问的目录
-
-
缺点:
- 因为
serve.xml
是针对真个tomcat的配置文件,我们经常在这里面修改很容易弄坏真个tomcat,所以一般不在这里面配置
- 因为
热部署
- 在
conf\Catalina\localhost
下面创建一个任意名称的xml文件。
-
例如:
test.xml
-
在
test.xml
当中写上-
<Context docBase = "E:\test" />
-
同时我们需要在
E:\test\
下面创建一个HTML文件 -
在浏览器中访问效果如图:
-
当我们想要取消该站点的访问的时候只需要把该站点的XML 文件名后边加上
_bak
就行,例如我的为test.xml_bak
,tomcat就会为我们取消该xml下面的所有部署
-
==对比==: 修改前两种方式之后需要重新tomcat 配置才会生效,而第三种则不需要重启tomcat就可以更改配置文件的内容。
热部署扩展
我们既然在server.xml
中有一个叫做engine的标签,有一个属性叫做name ,它的值等于我们对应在config文件夹下面的Catalina,而Catalina标签下面的host标签中的name = localhost刚好对应Catalina文件夹下面的localhost。
我们不妨猜测,正在engine标签下面每多写一个host标签在Catalina文件夹下面就会多出一个与之对应的文件夹,所以我将默认的host标签复制了一份,同样放在engine下面,将复制后的host标签的name属性改为了我的IP地址。然后重启tomcat。
我发现在config文件夹下面的Catalina文件夹下面果然多了一个叫做 192.168.9.1
的文件夹,并且能够正常访问,这就使我发现我们的tomcat其实可以同时部署很多的项目还不互相干扰。然后接下来的配置就和热部署一样了。然后我又查了一下(tomcat的体系结构),与我之前的测试一致。
配置临时域名、Tomcat体系结构、浏览器访问WEB资源的流程图
访问Tomcat服务器有好几种方式
- 使用localhost域名访问【localhost代表本机】
- 使用ip地址127.0.0.1访问【该ip地址也是本机】
- 使用机器名称访问【只限用于本机上或者局域网】
- 使用本机IP地址访问【在cmd中输入ipconfig可以查询到本机IP地址】
- 还可以为机器配置临时域名
Tomcat体系结构
浏览器访问WEB资源的流程图
摘自知乎的一篇文章Tomcat就是这么简单 - 知乎 (zhihu.com)
动态项目结构目录
- java动态项目的目录结构
- 项目的根目录
- WEB-INF目录
- web.xml:web项目的核心配置文件
- classes目录: 放置字节码文件的目录
- lib目录:防止依赖的jar包
- WEB-INF目录
- 项目的根目录
tomcat集成到idea
点击run -> Edit Configurations
在图三中点击configure之后,找到自己安装tomcat的目录,然后一路ok就行了
集成完毕
Servlet
概念: server + applet 运行在服务器端的小程序
- servlet 就是一个接口,定义了java类被浏览器访问到(tomcat识别)的规则
- 将来我们自定义一个类,实现servlet接口,复写方法。这个类就称为servlet
快速入门
-
创建JavaEE项目
-
定义一个类,实现servlet接口
-
实现接口中的抽象方法
-
package com.ziop.web.servlet.servletDemo1; public class Demo implements Servlet { @Override public void init(ServletConfig config) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("hello servlet"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
-
-
配置servlet
-
在WEB-INF下面的web.xml里面
-
<!-- 配置servlet--> <servlet> <servlet-name>demo</servlet-name> <servlet-class>com.ziop.web.servlet.servletDemo1.Demo</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo</servlet-name> <url-pattern>/demo</url-pattern> </servlet-mapping>
-
执行原理
- 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的 Servlet的资源路径
- 查找web.xm1文件,是否有对应的<url- pattern>标签体内容。
- 如果有,则在找到对应的< servlet-class>全类名
- tomcat会将字节码文件加载进内存,并且创建其对象
- 调用其<servlet>方法
servlet生命周期
-
被创建: 执行init方法,仅仅只执行一次
-
servlet : 被创建的时机
-
默认是第一次被访问时候创建
<load-on-startup>-1</load-on-startup> //默认为-1 ,只要参数为负数就行
-
服务器启动时,创建
<load-on-startup>1</load-on-startup> // 设置成0 或者正数即可
-
-
在web.xml中的<servlet>配置
-
Servlet的init方法,只执行一次,说明一个 Servlet在内存中只存在一个对象, Servlet是单例的
- 问题:多个用户同时访问时,可能存在线程安全问题。
- 解決:定义局部变量,尽量不要在 servlet中定义成员变量。即使定义成员变量,也不要对之进行修改。
-
-
提供服务: service ,每次打开网页都会执行一次,
- 每次访问是都会被访问
-
被销毁: 执行destroy方法,只执行一次
- Servlet被销毁时执行。服务器关闭时, Servlet被销毁
- 只有服务器正常关闭时,才会执行
- 在servlet被销毁值之前进行创建,用于释放资源
支持注解配置servlet ,不需要web.xml
-
==目前我测试的Java EE8 搭配servlet4.01 可以成功==但是JavaEE9 搭配servlet5则失败了
-
步骤
-
创建一个javaEE项目
-
配置tomcat
- 首先完成idea集成tomcat
- 然后将项目于tomcat结合
- 选择自己的项目的war包,一般和模块(项目)名称一样,然后点击确认
- 然后配置自己的访问起始URL地址,点击确认
-
在src/mian/的包下面创任意创建一个类实现servlet接口
-
加上
@WebServlet
注解,参数为-
@WebServlet(name = "demo01",urlPatterns = "/Demo01") //其中demo01 为名称 ,,,Demo1 为URL地址参数
-
-
运行tomcat
- 输入链接
localhost/demo01
回车 - 当网页中什么都没有显示一片空白,则说明成功
- 输入链接
-
@WebServlet
注解的属性和作用完成了一个使用注解描述的Servlet程序开发。 使用@WebServlet将一个继承于javax.servlet.http.HttpServlet的类定义为Servlet组件。 @WebServlet有很多的属性: 1、asyncSupported: 声明Servlet是否支持异步操作模式。 2、description: Servlet的描述。 3、displayName: Servlet的显示名称。 4、initParams: Servlet的init参数。 5、name: Servlet的名称。 6、urlPatterns: Servlet的访问URL。 7、value: Servlet的访问URL。 Servlet的访问URL是Servlet的必选属性,可以选择使用urlPatterns或者value定义。 像上面的Servlet3Demo可以描述成@WebServlet(name="Servlet3Demo",value="/Servlet3Demo")。 也定义多个URL访问: 如@WebServlet(name="Servlet3Demo",urlPatterns={"/Servlet3Demo","/Servlet3Demo2"}) 或者@WebServlet(name="AnnotationServlet",value={"/Servlet3Demo","/Servlet3Demo2"})
servlet的体系结构
- Servlet--接口 (祖类)
- 五种方法需要全部实现
- GenericServlet--抽象类 (父类)
- 只需要实现service方法就行
- 其余的方法均被默认实现
- HttpServlet--抽象类 (孙类)
- Httpservlet:对http协议的一种封装,简化操作
- 定义类继承 Httpservlet
- 复写 doget/ dopost方法
- Httpservlet:对http协议的一种封装,简化操作
servlet-URLpartten相关配置
-
URLpartten:访问路径
-
一个 Servlet可以定义多个访问路径:
@ Webservlet({"/a","/b","/c"})
路径定义规则:- /xxx
- /xxx/xxx
- *.do (do仅仅是一个扩展名,可随意改, * 为通配符)
- 下面是四种案例
@WebServlet({"/a","/b","/c"}) @WebServlet({"/user/ziop"}) @WebServlet({"/user/*"}) @WebServlet({"*.do"})
-
HTTP
基础概念
-
概念: Hyper Text Transfer Protocol 超文本传输协议
-
传输协议:定义了,客户端和服务器端通信时,发送数据的格式
- 特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/响应模型: 一次请求对应一次响应
- 无状态: 每次请求相互独立,不能交互数据
- 特点:
-
历史版本
- 1.0 传输一次就 建立一次连接,断开一次链接
- 1.1: 复用连接,一次建立多次复用
请求消息数据格式
-
请求行
- 请求方式、请求URL、请求协议/版本
- 请求方式
- http协议有7中请求方式,常用的有两种
- GET
- 请求参数在请求行中。在URL后边
- 请求长度有限制
- 不太安全
- POST
- 请求参数在请求体当中
- 请求的URL长度没有限制
- 相对安全
- GET
- http协议有7中请求方式,常用的有两种
- 请求方式
- 请求方式、请求URL、请求协议/版本
-
请求头
-
请求头名称: 请求头值1,请求头值2
-
User-Agent:
-
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.55
-
浏览器告诉服务器,访问使用的浏览器版本信息
-
可以在服务器端获取该头信息,解决浏览器兼容问题
-
-
Referer:
Referer: http://localhost/index.html
- 告诉服务器,我的请求从哪里来,
- 防盗链:
- 统计工作:统计访问通过哪个网页跳转到当前网页
- 告诉服务器,我的请求从哪里来,
-
-
-
请求空行
- 就是一个空行,分割请求头和请求体
-
请求体(正文)
- get无请求体
- post有请求体
-
请求字符串
-
请求 URL: https://www.bilibili.com/video/BV1qv4y1o79t?p=243&spm_id_from=pageDriver 请求方法: GET 状态代码: 200 远程地址: 111.23.14.36:443 引用站点策略: strict-origin-when-cross-origin 请求标头 GET /index.html HTTP/1.1 Host: localhost Connection: keep-alive sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Microsoft Edge";v="92" sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.55 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Cookie: JSESSIONID=C3EB733CBB6038E6729B25D9651450B8; Hm_lvt_a5ba743d0ea57bb0c5a7ad25181e4f7b=1629253748; Hm_lpvt_a5ba743d0ea57bb0c5a7ad25181e4f7b=1629253748; UM_distinctid=17b5717468c937-0924fcaf814bb7-7e687a6e-144000-17b5717468d299; CNZZDATA1278890537=302449366-1629251829-%7C1629251829; firsturl=http%3A//localhost/index.html; qimo_seosource_7c4f1e30-c255-11ea-91a4-7f87f504790a=%E7%AB%99%E5%86%85; qimo_seokeywords_7c4f1e30-c255-11ea-91a4-7f87f504790a=; qimo_xstKeywords_7c4f1e30-c255-11ea-91a4-7f87f504790a=; href=http%3A%2F%2Flocalhost%2Findex.html; accessId=7c4f1e30-c255-11ea-91a4-7f87f504790a; bad_id7c4f1e30-c255-11ea-91a4-7f87f504790a=115b75f1-ffcc-11eb-927a-e5b8ea64086f; nice_id7c4f1e30-c255-11ea-91a4-7f87f504790a=115b75f2-ffcc-11eb-927a-e5b8ea64086f
-
Request请求原理
- tomcat 服务器会根据请求url中的资源路径,创建对应的servletDemo的对象
- tomcat服务器,会创建request和response对象,将请求的信息封装到request对象当中去
- tomcat将request和response两个对象传递给service方法,并且调用service方法
- service方法,获取到请求信息之后,通过我们写的逻辑代码对其进行操作,然后将执行之后的结果封装到response对象当中,并返回出去
- 服务器将response对象中的信息解析成响应信息,返回给用户。
reques:
- request和response对象是由服务器创建的,我们仅仅是使用这两个对象
- request对象用于获取请求信息,response用于设置响应信息
request的体系结构
-
ServletRequest对象 ————接口
| 继承
-
HttpServletResquest ————接口
| 实现
-
org.apache.catalina.connector.RequestFacade ————类(tomcat创建)
request功能:
获取请求数据
获取请求行数据
-
GET /demo
-
-
动态获取虚拟目录 req.getContextPath()
-
获取请求头数据
//getParameter
{
String user = req.getParameter("userName");
System.out.println("账号:" + user);
}
//getParameterMap
{
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keySet = parameterMap.keySet();
for (String name : keySet) {
if ("userName".equals(name)) {
String[] value = parameterMap.get(name);
for (String value1 : value) {
user = value1;
}
}
}
}
获取请求体数据
请求转发和数据共享
获取ServletContext
request.getServletContext();
响应消息
数据格式
- 响应行
- 组成: 协议/版本 响应状态码 状态码描述
- 分类
- 1XX: 服务器接收到客户端信息,但是没接收完成,等待一段时间之后,发送1XX状态码
- 2XX: 成功。 代表:200
- 3XX: 重定向。 代表:302(重定向)304(访问缓存)
- 4XX:客户端错误。
- 代表:
- 404(请求路径没有对应的资源)
- 405(请求的方式没有对应的doXXX 方法)
- 代表:
- 5XX:服务端错误。代表:500(服务器内部异常)
- 响应头
- 格式: 头名称:值
- 常见的响应头:
- Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式
- Content-length 响应的字节长度
- Content-disposition: 服务器告诉客户端以什么格式打开响应体的数据
- 值:
- in-line:默认值,直接在当前页面内打开
- attachment:;filename=XXX :以附件形式打开响应体。文件下载
- 值:
- 响应空行
- 就是一个空行
- 响应体
- 真实的传输的数据
Response对象功能
- 设置响应行
- 格式: HTTP/1.1 200 OK
- 设置状态码: setStatus(int sc)
- 设置响应头
- setHeader(String name, String value)
- 设置响应体
- 使用步骤
- 获取输出流
- 字符输出流
- PrintWriter getWriter()
- 字节输出流
- ServletOutputStream getOutputStream()
- 字符输出流
- 使用输出流,将数据输入到客户端浏览器
- 获取输出流
- 使用步骤
案例
重定向
- 重定向:资源跳转的一种方式
过程:
-
告诉浏览器重定向:状态码302
resp.setStatus(302);
-
告诉浏览器需要重定向的资源的路径:响应头的location: 重定向资源的路径
resp.setHeader("location","/RedirectDemo"); // 或者 resp.sendRedirect("/RedirectDemo");
重定向的特点:
- 重定向地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不能使用request.setAttribute 共享数据
请求转发的特点:
- 转发的地址栏不发生变化
- 转发只能访问当前服务器下面的资源
- 转发只进行一次资源的请求,可以使用request对象来共享数据
路径的写法
- 路径分类
- 相对路径: 通过相对路径不可以确定唯一资源
- 不以/开头 以.开头
- 规则: 找到当前资源和目标资源之间的相对位置关系
- ./ 为当前目录
- ../ 为上一级目录
- 绝对路径: 通过绝对路径可以找到唯一资源
- 以/开头
- 规则: 判断定义的路径是给谁用的? 判断请求将来从哪里发出
- 给客户端使用的:需要加虚拟目录(项目的访问路径)
- 建议使用虚拟目录动态获取
req.getContextPath()
- <a>、<form> 重定向
- 建议使用虚拟目录动态获取
-
给服务器用的: 不需要加虚拟目录
- 给客户端使用的:需要加虚拟目录(项目的访问路径)
- 相对路径: 通过相对路径不可以确定唯一资源
服务器输出字符数据到浏览器
-
步骤
-
获取字符输出流
PrintWrite pw = response.getWriter();
-
输出数据
pw.write("Hellow,world");
-
注意中文乱码问题
- 设置编码
-
resp.setContentType("text/html;charset=utf-8"); //在获取流之前进行设置编码格式
-
服务器输出字节数据到浏览器
-
获取字节输出流
-
ServletOutputStream sos = resp.getOutputStream();
-
-
输入数据
-
sos.write("hellow".getBytes());
-
验证码
-
本质
- 图片
-
目的
- 防止恶意表单注册
-
制作
-
// 1.创建一个能子啊内存中画图的对象 BufferedImage img = new BufferedImage(70, 30, BufferedImage.TYPE_INT_RGB); // 2.美化图片 // 2.1 填充背景色 Graphics g = img.getGraphics(); g.setColor(Color.pink); g.fillRect(0, 0, img.getWidth(), img.getHeight()); // 2.2 话边框 g.setColor(Color.BLUE); g.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1); // 2.3写字符串 String str = "VWXIJKL78lmuv6rghijklmuv6MNOABighijk5PQRghijklmuv6CDEFghSdefstGH3490"; // 生成随机数 Random random = new Random(); for (int j = 1; j <= 4; j++) { int index = random.nextInt(str.length()); char ch = str.charAt(index); g.drawString(ch + "", img.getWidth() / 5 * j, img.getHeight() / 2 + random.nextInt(10)); } // 画干扰线 for (int i = 0; i < 3; i++) { int x1 = random.nextInt(img.getWidth()); int x2 = random.nextInt(img.getWidth()); int y1 = random.nextInt(img.getHeight()); int y2 = random.nextInt(img.getHeight()); g.drawLine(x1, y1, x2, y2); } // 3. 输出到页面中展示 ImageIO.write(img, "jpg", resp.getOutputStream());
-
ServletContext
文件下载
``
Cookie 和 Session <--会话技术
会话技术概念:
- 一次会话包含多次请求和响应
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能: 在一次会话范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie
-
概念: 客户端会话技术,将数据保存在客户端
-
快速入门:
-
创建cookie对象,绑定数据
-
在demo1 中创建cookie
Cookie c = new Cookie("msg", "hellow");
-
-
发送Cookie对象
-
在demo1 中发送cookie
resp.addCookie(c);
-
-
获取Cookie对象,拿到数据
-
在demo2中拿走数据
-
Cookie[] cs = req.getCookies(); if (cs != null) { for (Cookie cookie : cs) { String name = cookie.getName(); String value = cookie.getValue(); System.out.println(name +":"+value); } }
-
-
原理
- 基于响应头 set-cookie 和 请求头 cookie 来实现的
cookie的细节
- 一次可不可以发送多个cookie
- 可以
- 可以创建多个cookie对象,使用response调用多次addCookie方法发送cookie即可。
- cookie在浏览器中保存多长时间?
- 默认情况下,当前浏览器关闭之后,cookie数据被销毁
- 设置cookie的生命周期,持久化数据
- setMaxAge:(int seconds) 设置一个int值,是cookie持久化的秒数
- 正数: 将cookie数据写到硬盘文件中,持久化存储,并且指定cookie存活时间,当时间到了之后,会从本地删除文件,cookie自动失效
- 负数: 正常情况,当浏览器关闭的时候清除所有的cookie (默认情况)
- 零:删除cookie的信息
- setMaxAge:(int seconds) 设置一个int值,是cookie持久化的秒数
- cookie 能不能存中文?
- 在 tomcat8 之前,cookie不能直接存储中文数据
- 需要将中文转码------一般采用URL编码(%E3)
- 在 tomcat8 之后,cookie可以直接存储中文数据,特殊字符还是不支持,例如空格,建议使用URL编码和解码
- 编码
URLEncoder.encode(value,"utf-8")
- 解码
URLDecoder.decode(value,"utf-8f")
- 编码
- 在 tomcat8 之前,cookie不能直接存储中文数据
- cookie共享问题
- 假设在一个tomcat服务器中,部署了多个tomcat项目,那么这些web项目中cookie能不能共享?
- 默认情况下不能共享,
- setPath(String path) :设置 cookie 的获取范围。默认情况下是当前的虚拟目录,一般项目的目录为子目录
- 扩大设置的范围,我们将path设置为根目录就行了
- 不同的服务器之间能不能共享数据?
- setDomain(String path ):如果设置一级域名相同,那么多个服务器之间的cookie 可以共享
- setDomain(".baidu.com"),那么tieba.baidu.com 和 news.baidu.com中可以共享
- setDomain(String path ):如果设置一级域名相同,那么多个服务器之间的cookie 可以共享
- 假设在一个tomcat服务器中,部署了多个tomcat项目,那么这些web项目中cookie能不能共享?
- cookie获取范围有多大
- 4K
cookie的特点和作用
特点
- cookie存储数据在客户端浏览器,容易丢失和被篡改
- 浏览器对于单个cookie 的大小有限制(4kb),以及同一个域名下的总Cookie数量也有限制(一般限制在20个以内)
作用
- cookie 一般用于存储少量不太敏感的数据
- 在不登录的情况下,完成服务器对客户端的身份识别
JSP基础
Session
-
概念:服务器端的会话技术,在一次会话的多次请求之间共享数据,将数据保存到服务器端的对象当中去,HTTPSession
快速入门:
- 获取HttpSession对象
- HttpSession session = req.getSession();
- 使用HTTPSession对象:
- Object getAttribute(String name)
- void setAttribute(String name,Object value)
- void removeAttribute(String name)
原理
- session的实现是依赖于cookie来实现的
- 获取HttpSession对象
细节
-
当客户端关闭后,服务器不关闭,两次获取 session是否为同一个?
- 默认情况下不是的,客户端关闭之后cookie已经销毁了,所以session的id已经销毁了
- 如果需要的话,可以设置cookie中存储sessionID的键持久化,来实现两次访问的session是同一个session
-
客户端不关闭,服务器关闭后,两次获取的 session是同一个吗?
- 不是同一个session,但是要确保数据不丢失
- session钝化
- 在服务器正常关闭之前,将session对象序列化到硬盘上
- session活化
- 在服务器启动后,将session文件转化问session对象即可
- session钝化
- tomcat服务器会自动帮我们执行,但是在idea部署的项目不行,单独放在tomcat下面的可以
- 不是同一个session,但是要确保数据不丢失
-
session的失效时间?
-
服务器关闭。
-
session对象调用 invalidate()。
-
sessions默认失效时间30分钟。
-
在tomcat的安装目录下的
conf\web.xml
里面搜索session会找到如下代码,配置了session的默认存活时间。 -
也可以在项目里创建web.xml 在里面配置
<session-config> <session-timeout> 30</session-timeout> </session-config>
时间可以自己改 -
<!-- ==================== Default Session Configuration ================= --> <!-- You can set the default session timeout (in minutes) for all newly --> <!-- created sessions by modifying the value below. --> <session-config> <session-timeout>30</session-timeout> </session-config>
-
-
特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
session和cookie的区别
- session存储数据在服务器端, Cookie在客户
- session没有数据大小限制, Cookie有
- session数据安全, Cookie相对于不安全
filter过滤器
概念
- 生活中的过滤器:净水器,空气净化器,土匪
- web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
- 过滤器的作用:
- 来一般用于完成通过的操作。如:登录验证
- 过滤器的作用:
快速入门
-
定义一个类,实现接口Filter
-
public class FilterDemo implements Filter
-
-
复写方法
-
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("过滤器执行了"); }
-
-
配置拦截路径
- web. xml
1. - 注解配置
@WebFilter("/*")
类注解
- web. xml
过滤器细节
web.xml配置
<filter>
<filter-name>demo2</filter-name>
<filter-class>com.ziop.filter.FilterDemo2</filter-class>
</filter>
<filter-mapping>
<filter-name>demo2</filter-name>
<!--拦截路径-->
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器执行流程
public class FilterDemo2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("对请求进行过滤");
chain.doFilter(request, response);
System.out.println("服务器做出响应了");
}
}
//执行过程
//对请求进行过滤
//CookieDemo1 的doGet被调用了
//服务器做出响应了
过滤器生命周期方法
public void init(FilterConfig filterConfig) // 初始化方法,用于服务器刚加载的时候开始执行,只执行一次
public void destroy() // 服务器正常关闭的时候执行,只执行一次,用于释放资源
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) //,每次拦截资源的时候,都要过滤,多次调用
过滤器配置详解
-
拦截路劲的配置
- 具体的路径: /index.jsp 只有访问index.jsp的时候过滤器才会被执行
- 拦截目录: /user/* 访问user 下面的资源的时候才会被拦截
- 拦截后缀: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有的资源: /* 访问所有资源时,过滤器都会被执行
==注==: 这里的拦截写的根目录是指的当前项目的根目录 而不是整个服务器的根目录
-
拦截方式的配置 : 资源被访问的方式
- 注解配置
- 设置dispatcherType配置
- REQUEST:默认值。浏览器直接请求资源
FORWARD:转发访问源
INCLUDE:包含访问资源
ERROR:错误跳转资源
ASYNC:异步访问资源
- REQUEST:默认值。浏览器直接请求资源
- 设置dispatcherType配置
- 注解配置
过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
- 过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如:AFi1ter和 Filter, Afilter就先执行了。
- web.xm1配置:< filter- mapping>谁定义在上边,谁先执行
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
代理模式--案例
-
概念:
- 真实对象:被代理的对象
- 代理对象:
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
-
实现方式:
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
- 实现步骤
- 代理对象和真实对象实现相同的接口
- 代理对象 = Proxy.newInstance();
- 使用代理对象调用方法
- 增强方法
- 增强方式
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
- 实现步骤
//接口
public interface Computer {
String sale(double money);
void show();
}
// 被代理类
public class Lenovo implements Computer{
@Override
public String sale(double money) {
System.out.println("花了" + money + "元,买了一台电脑...");
return "联想电脑";
}
@Override
public void show(){
System.out.println("展示电脑。。。");
}
}
//测试类
import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class LenovoTest {
@Test
void sale() {
Lenovo lenovo = new Lenovo();
/*
* 三个参数
* 类加载器 真实对象.getClass().getClassLoader()
* 接口数组 真实对象.getClass().getInterfaces()
* 处理器 new InvocationHandler()
*/
Computer proxy_lenove = (Computer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/**
* 代理逻辑方法
* @param proxy 代理对象
* @param method 代理对象调用的方法,被封装为对象
* @param args 方法执行时候,传递的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
if (args != null && method.getName().equals("sale")) {
args[0] = (double)args[0] * 0.85;
System.out.println("代理商:专车接你。。。。");
invoke = (String)method.invoke(lenovo, args);
System.out.println("代理商:送货上门");
return invoke + "+鼠标垫";
}else {
invoke = method.invoke(lenovo, args);
}
return invoke;
}
});
System.out.println(proxy_lenove.sale(8000));
// proxy_lenove.show();
}
}
listener: 监听器:
概念:web的三大组件之一
- 事件监听机制
- 事件: 一件事情
click
- 事件源: 事件发生的地方
button
- 监听器: 一个对象
button被click之后执行的代码
- 注册监听: 将事件、事件源、监听器绑定在一起,将事件源上发生某个事件之后,执行监听器代码
- 事件: 一件事情
案例---servletContextListener
-
作用: 监听servletContext对象的创建和销毁
-
方法:
-
contextInitialized(ServletContextEvent sce) // servletContext对象创建的时候执行的代码 contextDestroyed(ServletContextEvent sce) // servletContext对象被销毁之后执行的代码
-
-
步骤:
- 实现接口
- 复写方法
- 配置
- xml配置
- 注解配置
@WebListener
- xml配置