HTTP协议: *****
超文本传输协议 , 是一个应用层的网络传输协议 !
特点:
1. 简单, 快速.
2. 无连接协议 , 每次连接服务器只处理一次客户端的请求 ,处理完毕, 立即断开.
3. 无状态协议 , 处理请求, 以及进行响应时 ,没有记忆能力 !
4. 支持多种不同的数据提交方式 ,GET/POST 等等
5. 数据传输很灵活, 支持任意数据类型 .
**HTTP协议的组成部分 *******
1. 请求
请求由四部分组成:
- 请求头
请求头部的信息, 由一个个的键值对组成 , 描述的是有关客户端的信息.
- 请求体
GET请求没有请求体. 当请求方式为POST时 ,存在请求体, 请求体是用于存储数据的数据容器 !
- 请求空行
请求头部与请求体之间的一行空白
- 请求行
由一个个的键值对组成, 描述的是:描述了请求的方式,远端服务器地址 ,以及所使用的协议版本等信息.
2. 响应
响应由三部分组成:
- 响应头
响应头部的信息, 由一个个的键值对组成, 描述的是有关服务器的信息.
- 响应体
服务器给客户端回复的主体内容 .
- 响应行
描述了响应的协议版本, 响应状态码, 以及响应成功或失败的相关解释.
开发环境下: 代码部署到服务器后, 访问的路径: http://ip地址:端口号/项目名/文件名.后缀名
**HttpServlet 类 *****
简介:
是JavaWeb中的 三大组件之一 .
本质上: 就是一个运行在tomcat中的 java类
作用:
用于处理客户端的请求, 以及对客户端进行响应 .
步骤:
1. 编写一个类, 继承自HttpServlet
2. 重写父类的service(HttpServletRequest request,HttpServletResponse response)方法
3. 在service方法中 对用户进行响应.
案例:
public class Servlet1 extends HttpServlet{
/**
* @param request : 请求对象 , 包含了请求相关的所有信息
* @param response : 响应对象 , tomcat提供的用于给客户端响应内容的 各种工具.
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置响应的 编码格式 以及 响应的内容类型
response.setContentType("text/html;charset=utf-8");
//2. 获取用于打印响应体的 打印流
PrintWriter pw = response.getWriter();
//3. 打印一些准备响应的内容
pw.println("<h1>从前有座山 , 山上有座尼姑庵 ! 庵里有个老尼姑 ...</h1>");
pw.flush();
//当service方法执行完毕后, tomcat会将我们准备好的响应体发送给浏览器
}
}
将编写好的servlet 映射到一个网址上: *****
web3.0之前版本:
修改项目中的配置文件 web.xml
在web.xml根节点中 加入:
1. servlet节点 ,用于将serlvet类告知tomcat
<servlet>
<servlet-name>任意的标识符,给servlet起别名</servlet-name>
<servlet-class>包名.类名<servlet-class>
</servlet>
2. servlet-mapping , 通过别名告知tomcat ,某servlet的映射网址
映射网址 ,通常以/开头 , 例如: /demo1 , 访问网址: http://ip地址:端口号/项目名/demo1
<servlet-mapping>
<servlet-name>要添加映射网址的别名</servlet-name>
<url-pattern>/映射的网址</url-pattern>
</servlet-mapping>
web3.0+ 版本:
通过WebServlet注解:
**案例:**
@WebServlet("/hello2")
public class Servlet2 extends HttpServlet{
/**
* @param request : 请求对象 , 包含了请求相关的所有信息
* @param response : 响应对象 , tomcat提供的用于给客户端响应内容的 各种工具.
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置响应的 编码格式 以及 响应的内容类型
response.setContentType("text/html;charset=utf-8");
//2. 获取用于打印响应体的 打印流
PrintWriter pw = response.getWriter();
//3. 打印一些准备响应的内容
pw.println("<script>alert('恭喜你, 获得奖品: 苹果笔记本电脑一台 , 现金1980 ,请输入银行卡密码领取')</script>");
pw.println("<input ><button οnclick='alert(\"哈哈哈哈哈哈哈,你真信啊\")'>提交</button>");
pw.flush();
//当service方法执行完毕后, tomcat会将我们准备好的响应体发送给浏览器
}
}
Servlet的生命周期 ***
指的是 Servlet从创建 到 消亡的 周期!
Servlet的创建时机: 默认情况 , 当用户第一次访问Servlet的映射地址时 . 对象创建.
Servlet的销毁时机: 当tomcat关闭, 或 项目从tomcat删除时. Servlet被销毁.
三个方法的体现:
1. init方法 : 此方法在对象创建后, 执行.
2. service方法 : 服务方法,当用户每一次访问时, 执行, 用于处理用户的请求, 以及对用户进行响应 .
3. destroy方法 : 当tomcat关闭 或 项目从tomcat删除时 执行;
ServletConfig对象 了解
是Servlet的配置对象, 每一个Servlet都拥有一个ServletConfig .
我们在web.xml中 进行Servlet配置时. 可以向一个Servlet中 添加初始化的参数.
这些参数以键值对的形式存储在ServletConfig中
在web.xml中 , 向ServletConfig 存储数据的格式:
<servlet>
...
<!-- init-param标签可以存在多个, 每一个init-param都表示一个键值对 -->
<init-param>
<param-name>键</param-name>
<param-value>值</param-value>
</init-param>
</servlet>
在Servlet中 得到ServletConfig对象的方式:
方式1与方式2是互斥的.
方式1.
在Servlet中, 重写生命周期init(ServletConfig config)方法 , 使用方法参数中的config对象
方式2.
在Servlet的任意代码位置 , 通过getServletConfig();方法. 得到对象
从ServletConfig 取出数据的格式:
String value = config对象.getInitParameter(String name);
调整 Servlet的创建时机 (懒汉 变 饿汉)
在web.xml中 . 配置servlet时.
<servlet>
<servlet-name...
<servlet-class...
<load-on-startup>数字</load-on-startup>
</servlet>
load-on-startup:
取值为数字: (默认值为-1)
当值为负数时: 懒汉模式, 第一次请求时加载 ,
当值≥0时 , 描述的是请求的顺序, 值越小越早加载.
如果多个servlet值相同: 按照web.xml中servlet的配置顺序 自上而下加载.
**如何接收用户 表单 的参数 *****
1. 根据一个name , 接收单个参数
String value = request.getParameter(String name);
2. 根据一个name , 接收一组参数
String[] values = request.getParameterValues(String name);
HttpGET请求 与 HttpPOST请求的区别: *****
GET请求:
- 请求的参数 ,以键值对的形式 存储在网址中 ,在网址中, 编写在?后, 由1个或多个键值对组成, 键与值之间使用等号连接, 多个键值对之间使用&分割.
- 只能传输字符串类型的参数.
- 网址的最大长度为4kb 通常支持的文字 2048 个文字
- 数据传输不安全
tomcat8+版本 : GET请求不会乱码
POST请求:
- 请求的数据, 以键值对的形式存储在请求体中,
- 请求体是一个单独的数据包 , 较GET请求而言, 安全.
- 可以传输任意类型的数据
- 数据的大小 ,理论上是无上限的.
tomcat8+版本 : Post请求默认编码为 ISO-8859-1 (不支持中文)
什么样的请求是GET
以我们目前所学习的技术来说 , 除了表单提交时method=“POST” ,其他的访问方式都是GET请求
例如:
- 点击超链接 访问
- 通过js: window.location.href='' 访问
- 浏览器中输入网址 + 回车
- 表单提交时 ,method="GET" 或 默认
- ajax的get请求
- Java代码的URL类的GET请求.
什么样的请求时PSOT
1. 表单提交时method="POST"
2. ajax的post请求
3. Java代码的URL类的POST请求.
请求的乱码问题 ***
解决乱码的两种格式:
格式1.
可用于tomcat8版本之前的GET请求乱码 以及 所有版本的POST请求乱码:
解决方案: 将乱码的文字, 按照乱码的编码ISO-8859-1转换为字节数组, 再按照正常的编码UTF-8组装为文字;
案例:
//1. 接收用户传递的参数
String username = request.getParameter("username");
//解决乱码
{
//1. 将乱码的文字, 通过ISO-8859-1编码 打碎成字节数组
byte[] bytes = username.getBytes("ISO-8859-1");
//2. 通过UTF-8编码, 将字节数组 重新组装为 正常文字
username = new String(bytes, "UTF-8");
}
格式2.
格式1 解决乱码适用于参数较少的情况, 如果参数过多, 解决起来极其麻烦.
tomcat为我们提供了 设置请求体编码的方式:
格式: request.setCharacterEncoding("UTF-8");
注意: 只有POST请求 ,才有请求体!
解决请求乱码的代码, 必须运行在获取参数之前
**响应的乱码问题 ***
方式1.
设置网页的内容类型, 以及 网页的编码格式:
response.setContentType("text/html;charset=utf-8");
方式2.
设置网页的编码格式 (因为没有设置网页内容类型为html , 所以浏览器解析时也是乱码)
response.setCharacterEncoding("UTF-8");
注意:
设置响应乱码的两种方式, 都必须写在 响应内容之前 !
**
线程安全问题 :
**
Servlet的service方法, 每次被请求时, 调用.
这个调用很特殊 , 是在新的子线程中调用的 , 当service方法执行完毕, 子线程死亡了.
可以简单的理解为: service方法每次执行都是一个新的线程.
@WebServlet("/s1.do")
public class Servlet1 extends HttpServlet {
//剩余票数
private int count = 10;
Object o = new Object();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
synchronized (o) {
if(count>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("恭喜你, 有票, 正在出票...");
count--;
System.out.println("出票完成, 剩余票数:"+count);
}else {
System.out.println("很遗憾, 无票");
}
}
}
}
请求的 转发 *****
概念: 一个web组件 将未处理完毕的请求, 通过tomcat转交给另一个web组件处理.
步骤:
1. 获取请求转发器
RequestDispatcher rd = request.getRequestDispatcher("转发的地址");
2. 通过转发器 发起转发
rd.forward(request,response);
简写步骤:
request.getRequestDispatcher("转发的地址").forward(request,response);
转发流程:
步骤1. 当浏览器访问服务器中tomcat时
步骤2. tomcat将请求信息, 与响应工具进行封装, 传递给我们的Servlet的service方法进行处理
步骤3. 我们在service方法中, 得到请求转发器, 通过请求转发器 告知 tomcat , 请求转发的地址.
步骤4. tomcat接收到请求转发需求, 会重新封装请求信息, 将请求对象 与 响应对象 传递给 转发地址的Servlet的service方法进行处理
特点:
1. 转发过程中, 多个Servlet之间共享一份请求信息, 共享一个响应对象.
2. 转发只能发生在同一个服务器中. (转发无法实现跨域)
3. 无论转发发生多少次 ,对于浏览器来说! 只发起过一次请求 , 并且只接到了一次响应.
4. 相对于重定向来说, 效率更高.
请求的 重定向 *****
概念: 响应时 , 告知浏览器新的请求地址, 浏览器接收到 自动请求新的地址 !
步骤:
response.sendRedirect("重定向地址");
重定向流程:
步骤1. 当浏览器访问服务时, 服务器对浏览器响应一个302的状态码, 以及一个location的地址
步骤2. HTTP协议约定 , 当浏览器接收到302状态码时 ,会自动寻找location地址, 并发起新的请求.(相当于 控制用户浏览器 自动完成页面的跳转操作.)
特点
1. 重定向会产生新的请求 和 新的响应.
2. 使用重定向, 可以在多个服务器之间发生( 可以实现跨域操作 )
3. 浏览器地址栏的内容 会发生改变.
4. 相对于请求转发而言, 效率较低.
注意:
1. 在一次用户的操作中, 可以无限制的进行转发和重定向, 但是记住: 一定要存在出口.
2. 当servlet中的请求已经被转发 / 重定向后, 在此servlet后续的代码中不能再进行响应 !
HttpServletRequest 类常用操作: 了解
1. 获取访问的客户端ip地址
String ip = request.getRemoteAddr();
2. 获取客户端访问的地址 (有可能因为服务器映射了多个域名, 多个用户的访问地址 不同)
request.getRequestURI();
3. 获取服务器的名称 (通常获取的是ip)
request.getServerName();
4. 获取端口号
request.getServerPort();
5. 获取请求的方式
String method = request.getMethod();
6. 获取get请求的参数列表 (网址中?后面的部分)
String params = request.getQueryString();
三个将请求对象 作为数据容器使用的方法:
1. 存储数据
request.setAttribute(String key,Object value);
2. 获取数据
Object value = request.getAttribute(String key);
3. 删除数据
request.removeAttribute(String key);
ServletContext 上下文 了解
每一个Servlet都是一个独立的用于处理请求的 对象.为了便于多个Servlet之间的数据交流 ,javaWeb提供了一个上下文对象ServletContext !我们在任何的Servlet代码中, 都可以获得这个ServletContext对象 , 且每一个Servlet获取的都是同一份ServletContext对象.上下文对象, 类似于我们SE所学习的MAP集合, 是一个键值对的容器.
作用:
ServletContext是Servlet之间通信的桥梁, 用于多个Servlet之间信息的共享.如何从Servlet中得到上下文对象 了解
格式:
ServletContext context = getServletContext();
ServletContext的常用方法 熟悉
1. 存储数据
context.setAttribute(String key,Object value);
2. 获取数据
Object value = context.getAttribute(String key);
3. 删除数据
context.removeAttribute(String key);
4. 获取项目运行时的 文件夹 绝对路径
String path = context.getRealPath("/");
//因为一个项目 只有一个ServletContext对象, 且在项目启动时创建了,项目销毁时销毁.
//所以我们在一次项目启动的过程中, 一个Servlet存储的数据, 任何Servlet都可以获取到.
会话跟踪 ( 状态管理 ) *
HTTP协议是无状态的 , 我们的服务器在与客户端进行交互时, 没有记忆.
两种方式来实现状态管理:
1. Cookie技术: 将状态 , 存储到客户端中
2. Session技术: 将id存储在客户端中, 将状态存储在服务器中.
Cookie技术 ***
技术实现步骤以及原理:
1. 当服务器向客户端响应时,可以向响应头部加入Cookie,每一个Cookie表示一个键值对.
2. 浏览器在接收到响应后,如果存在Cookie,则会将Cookie存储在文本文件中(.txt)存储时,会存储的信息有: 服务器的域,路径,Cookie键,Cookie的值,存储时长...
3. 当浏览器向客户端请求时,会遍历 Cookie的文本文件,将匹配新请求地址的Cookie携带上,放在请求头部,发送给服务器!
Cookie匹配的规则:*
当cookie存储的域相同时, 路径匹配时 才会将Cookie发送给服务器.
如何创建Cookie ***
Cookie在Java中的体现 就是一个表示键值对的 Java类, 类名为: Cookie .
格式:
Cookie cookie = new Cookie(String name,String value);
如何将Cookie添加到响应头部
通过响应对象, 将Cookie添加到响应头部
格式:
response.addCookie(Cookie cookie);
一次响应, 可以添加n个cookie .
如果浏览器中已经存储过与某个Cookie的name相同的Cookie , 再次存储时会覆盖value
如何从请求头部 得到之前存储的所有Cookie
因为一个域 和 路径下, 可能存在多个Cookie , 所以获取的不是单个Cookie , 而是一个数组:
Cookie[] cookies = request.getCookies();
// 如果从未存储过, 则返回的数组值是 null
得到Cookie后, 如何取出其中的键和值. ***
获取Cookie的键:
String name = cookie.getName();
获取Cookie的值:
String value = cookie.getValue();
如何调整Cookie存储时长. ***
cookie.setMaxAge(int 秒);
传入的值:
- 负数 : 默认-1 , 表示浏览会话结束时 删除.
- 正数 : 存活的秒数, 例如: 60*60*24*365*10 表示十年.
- 0 : 经常用于覆盖一个cookie时使用, 作用为0秒后删除 (立即删除)
Cookie存储时, 路径问题的解决. *
路径匹配的规则:
- Cookie的替换: 只能由相同域 , 相同路径的 完成替换.
- Cookie的获取: 只能由相同域 , 相同路径或子路经 获取
例如:
A地址: localhost/x/a.do
B地址: localhost/x/b.do
C地址: localhost/c.do
A存储数据时: a/b可以获取 ,a/b可以替换. c不能获取 也不能替换.
C存储数据时: a/b/c可以获取 , c可以替换.
Cookie的路径问题, 经常影响我们的开发 .
JavaWeb 给我们提供了一个Cookie的方法, 用于设置Cookie的路径.
通常我们会将cookie的路径设置为/ (根路径)
格式: cookie.setPath("/");
Cookie的优缺点: *****
缺点:
1. Cookie存储的数据类型有限制 , 只能是字符串
2. 数据存储的大小 ,有限制, 最大为4kb
3. 数据存储在用户的计算机上 , 不安全
4. 受限于用户的浏览器设置, 当浏览器禁止使用Cookie时 , cookie就无法再存储了.
优点:
数据存储在客户端 , 分散了服务器的压力.
Session技术 (会话) *****
基于Cookie实现的技术 , 是Java中的一个键值对的容器. 就像我们常用的Map集合.
技术原理:
1. 浏览器访问服务器时,服务器可以选择创建Session对象.
2. session对象在创建时,会生成一个id,我们称其为sessionid,sessionid是Session的密钥,是唯一的!
3. session创建完毕后,会自动将sessionid以cookie的形式存储到用户的浏览器中.
4. 当浏览器再次访问服务器时,会自动携带sessionid发送给服务器.
5. 服务器得到sessionid后,会去自动匹配找到对应的session对象,供用户使用.
如何获取session对象 ***
在Java中, session是一个Java对象, 对象的类型为: HttpSession
获取Session对象的格式:
格式1. 无参方法:
HttpSession session = request.getSession();
内部调用了 一参方法, 且传入true
格式2. 一参方法
HttpSession session = request.getSession(boolean isNew);
用于获取session 参数:
true: 根据当前浏览器传入的sessionid ,寻找session对象并返回 . 如果不存在 , 则创建新的session并返回
false: 根据当前浏览器传入的sessionid ,寻找session对象并返回 . 如果不存在 , 则返回null;
session的常用方法 ***
1. 存储数据
session.setAttribute(String key,Object value);
2. 获取数据
Object value = session.getAttribute(String key);
3. 删除数据
session.removeAttribute(String key);
4. 销毁session (应用场景: 百分之99的情况是: 退出登录)
session.invalidate();
session的存活时长 熟悉
session的默认时长为: 30分钟!
指的是: 举例用户的上一次访问大于30分钟后, session自动删除.
设置Session时长:
方式1. 修改单个session的时长:
session.setMaxInactiveInterval(int 秒);
方式2. 修改tocmat下, 所有session的默认时长:
独立环境: 寻找到tomcat/conf/web.xml文件
开发环境: 寻找到Servers项目中的 web.xml
修改web.xml中 session-config节点
<session-config>
<session-timeout>数值分钟</session-timeout>
</session-config>
session的优缺点 *****
优点:
1. 数据存储在服务器中, 安全.
2. session存储时的值类型为: Object , 可以存储任意类型数据.
3. 可存储的数据大小, 理论上是无上限的.
缺点:
数据在服务器的内存中存储,内存通常是有限的,会对服务器造成大量的压力.很容易耗尽服务器资源.
Cookie结束和Session技术不是互斥的. 熟悉
Cookie和session是结合使用的.
通常:
对于安全不敏感的数据 . 建议使用Cookie存储
对于安全敏感的数据, 建议使用session存储
对于安全敏感, 且较大的数据, 存储在数据库.