1 Web会话技术
1.1 会话概述
web会话可简单理解为:用户开一个浏览器,访问某一个web网站,在这个网站点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话.
例如:
1. 打开浏览器
2. 访问京东, 此时 与京东网站 产生了会话
3. 访问京东的具体商品页面; 或 其他页面; 或访问了其他网站, 此时,一直会与京东网站保持着会话连接
4. 关闭浏览器, 此时 与京东网站的会话结束;
重写打开浏览器,再次访问京东, 这就是第二次会话了
打开浏览器,建立会话,只要浏览器关闭,会话就结束了
1.2 Java Web开发中使用的会话技术
在客户端与服务器端交互的过程中,通常会产生一些数据, 为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。
而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。
Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。
- Cookie对象: 客户端浏览器的会话技术,它可以把服务器传递过来的一些数据记录在客户端浏览器中。
- Session对象: 服务器端的会话技术, 它可以把同一用户与服务器多次请求响应的一些数据记录在服务器Session域中, 实现该用户在本次会话中, 可随时获取Session域中的数据, 满足多次请求响应之间 进行数据传递、访问使用.
2 Cookie技术
2.1 Cookie概述
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
2.2 服务器向浏览器发送Cookie
把服务器端想要保存在客户端的数据, 通过Cookie来完成; 保存在客户端的数据 都是较小的文本数据.
实现步骤:
- 创建Cookie对象,直接new Cookie(String key,String value)
- 将Cookie数据保存到客户端, 使用response对象方法 addCookie()
实例:
/**
* Cookie对象: 小甜点
* Cookie对象是容器,存储数据,键值对
* 数据产生在服务器端,数据放在客户端浏览器保存
* Cookie类构造方法:
* Cookie(String name,String value) 传递键值对
*
* 响应对象 response
* 方法 addCookie( Cookie cookie )
* 响应头中
*/
@WebServlet(urlPatterns = "/sendCookie")
public class SendCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建Cookie对象,存储键(名字)值对
Cookie cookie = new Cookie("heima","java");
Cookie cookie2 = new Cookie("heima2","java2");
//响应对象,将Cookie数据,响应回客户端
response.addCookie(cookie);
response.addCookie(cookie2);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3 服务器获取浏览器携带的Cookie
浏览器在访问服务器的时候, 会携带保存的Cookie数据, 服务器端可使用request对象获取Cookie数据; Cookie数据放在请求头
实现步骤:
- 使用Request对象 getCookies()方法, 获取浏览器携带的所有Cookie数据
- 遍历拿到每一个Cookie对象, 获取Cookie的键, 获取Cookie的值
API:
-
request对象方法
Cookie[] getCookies() 获取多个Cookie,返回的是Cookie对象数组
-
Cookie对象方法
String getName()获取Cookie的键 String getValue()获取Cookie中的值
代码演示:
/**
* 获取客户端的Cookie数据
* 客户端访问服务器的时候,会有Cookie数据
* 浏览器会将Cookie数据,放在HTTP协议的请求头中
* request对象获取请求头数据 (Cookie)
* 方法: Cookie[] getCookies() 获取到浏览器中的Cookie,返回的是数组
*
* 浏览器中没有了Cookie(手动删除),request对象获取不到Cookie,返回的数组null
*/
@WebServlet(urlPatterns = "/getCookie")
public class GetCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取客户端的Cookie数据
Cookie[] cookies = request.getCookies();
//遍历数组,取出Cookie中的键和值
for(Cookie cookie : cookies){
//取出的是每个Cookie对象
String name = cookie.getName();//Cookie中的键
String value = cookie.getValue();//Cookie中的值
System.out.println(name+"::"+value);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.4 Cookie中使用中文问题(扩展)
/**
* Cookie可以存储中文数据的,不建议
* 键不能是中,值可以是中文
*
* Tomcat8.5版本开始,可以直接使用中文的
* 8.5版本之前,不允许直接写中文的
*
* 中文 转码UTF-8码, -4 -5 -6 转成十六进制 A1%E3%F1
*/
@WebServlet(urlPatterns = "/chineseCookie")
public class ChineseCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str = "中文";
str = URLEncoder.encode(str,"utf-8");
System.out.println(str); // %E4%B8%AD%E6%96%87
/*Cookie cookie = new Cookie("china",str);
response.addCookie(cookie);*/
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies){
String value = URLDecoder.decode(cookie.getValue(),"utf-8");
System.out.println( cookie.getName()+"::"+value );
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.5 Cookie的携带路径
Cookie数据放在请求头, 浏览器访问服务器,每次都会携带所有的Cookie进行访问吗?
结论: Cookie数据在哪里产生的,在哪里访问才携带
* Cookie的携带路径
* 演示:
* 浏览器先访问的是 /web03/pathCookie
* 第二次访问的是 /web03/pathCookie
* 第三次访问的是 /web03/a.jsp
* 第四次访问的是 /web03/abc/b.jsp
*
* 浏览器都携带Cookie数据 (请求头有!)
* Cookie的数据是在哪个路径下产生的呢: /web03
* 凡是访问的是 /web03的下的任意资源,都携带
*
* 演示:
* 浏览器先访问的是 /web03/abc/pathCookie (请求头有!)
* 第二次访问的是 /web03/abc/pathCookie (请求头有!)
* 第三次访问的是 /web03/abc/b.jsp (请求头有!)
* 第四次访问的是 /web03/a.jsp (请求没有!)
*
* Cookie的产生路径: /web03/abc
* 凡是访问的是 /web03/abc 下的任意资源,都携带
* 最后一次,访问的是 /web03/a.jsp 浏览器没有携带Cookie
*
* 我们开发中,需要的是只要Cookie访问的是/web03就要携带
* 不管你是在哪里产生
*
* Cookie对象的方法设置Cookie的携带路径: setPath
让指定的Cookie, 可以在WEB应用下的任意资源都携带
- Cookie对象
//方法: setPath("cookie的携带路径") 用于设置cookie携带路径, 若参数写成 request.getContextPath() 代表web应用下任意资源都携带本Cookie
代码演示:
@WebServlet(urlPatterns = "/abc/pathCookie")
public class PathCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("path","cookiePath");
//设置Cookie携带路径,只要是/web03就携带
//写的是web应用程序名称 request对象方法 getContextPath()
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.6 Cookie的生存时间
浏览器中Cookie是有生存时间的, 默认是当前会话.浏览器关闭,该会话结束.
可以通过更改Cookie的生存时间, 来延长Cookie的生存时间
-
Cookie对象
//方法: setMaxAge(int 秒) 更改Cookie的生存时间, 参数单位: 秒
代码演示:
/**
* Cookie的生命周期
*
* Cookie是会话对象
* 会话(浏览器访问服务器,不关闭浏览器,一次会话)
* 一旦关闭浏览器,Cookie对象就死亡
*
* 设置Cookie的生存时间
* Cookie对象方法 setMaxAge(int 秒)
* Cookie过时时间,到时间,不是删除cookie,而是不会携带访问
*/
@WebServlet(urlPatterns = "/lifeCookie")
public class LifeCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("heima","java");
//Cookie携带路径
cookie.setPath( request.getContextPath() );
//设置Cookie的生存时间
cookie.setMaxAge(60*10);
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.7 删除Cookie
* 清除Cookie
* 采用的是覆盖原理
* 保证: 被覆盖的Cookie和新Cookie的携带路径要相同,键名也要相同
* 新Cookie的生存时间写0
@WebServlet(urlPatterns = "/clearCookie")
public class ClearCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("heima","");
cookie.setPath(request.getContextPath());
cookie.setMaxAge(0);
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3 Session技术
3.1 Session概述
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。(检验该客户通行证信息cookie是否与该客户档案session一致)
3.2 Session域对象
session对象是HttpSession接口的实现类对象, session对象由tomcat引擎创建. 实现将某些数据放入session中,供同一用户的不同页面使用
- 作用域范围 : 一次会话有效(浏览器不关闭), 和请求次数无关的
- 四个域对象的作用范围大小排序
ServletContext > session > request > pageContext
实现步骤:
- 使用Request的getSession() 当session存在时返回该session,否则新建一个session并返回该对象
- 通过session对象的setAttribute\getAttribute 进行数据的存取
API:
- 域对象存储数据: setAttribute(String key,String value)
- 取出域对象数据: Object getAttribute(String key)
- 移除域对象数据: removeAttribute(String key)
@WebServlet(urlPatterns = "/session1")
public class Session1Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取HttpSession接口实现类对象
HttpSession session = request.getSession();
//向session域对象存储键值对
session.setAttribute("ses","sesValue");
//取出session域对象的数据
Object o = session.getAttribute("ses");
System.out.println(o);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.3 持久化Session对象
发现关闭浏览器再次打开访问时,session域中原有数据不存在了. 现在想要session实现关闭浏览器继续可以访问数据.
每个session对象都有个唯一标识 JSESSIONID, 服务通过Cookie对象, 将JSESSIONID存储在客户端Cookie中, 就可以实现持久化Session对象.
实现步骤:
- 获取JSESSIONID, 通过session对象中的getID()方法
- 创建Cookie对象, 将JSESSIONID 存入Cookie
- 使用response对象, 将cookie 响应回浏览器
API:
-
session对象
String getID() 获取session对象的唯一编码,返回String
代码演示:
@WebServlet("/save")
public class SaveSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("heima","javaee");
String sessionId = session.getId();
System.out.println("sessionId = " + sessionId);
//创建Cookie
Cookie cookie = new Cookie("JSESSIONID", sessionId);
cookie.setPath( request.getContextPath());
cookie.setMaxAge(60*10);
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.4 session生命周期
- session创建时机
1:这个浏览器在servlet中第一次使用session时候,通过getSession方法创建;
2:这个浏览器第一次访问jsp的时候,服务器也会为这个浏览器创建一个session对象;
- session销毁时机
1:程序员调用invalidate方法;(立刻销毁)
2:设置的存活时间到了;(默认是30分钟)
3:服务器非正常关闭;(突然断电)
注意事项:
1:正常关闭服务器,session不会销毁,而是直接序列化到硬盘上,下一次服务器启动的时候,会重新创建出来;
2:如果浏览器单方面关闭会话,服务器上对应的session不会死亡 ,但是会导致服务器给浏览器创建的JSESSIONID的cookie死亡,当cookie死亡后,会导致浏览器无法找到上一个session对象,会造成服务器中session死亡的假象;
3.5 cookie和session的区别
1、存放位置不同
Cookie保存在客户端,Session保存在服务端。
2 、存取方式的不同
Cookie中只能保管ASCII字符串,假如需求存取Unicode字符或者二进制数据,需求先进行编码。Cookie中也不能直接存取Java对象。若要存储略微复杂的信息,运用Cookie是比拟艰难的。
而Session中能够存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也能够直接保管Java Bean乃至任何Java类,对象等,运用起来十分便当。能够把Session看做是一个Java容器类。
3、安全性(隐私策略)的不同
Cookie存储在浏览器中,对客户端是可见的,客户端的一些程序可能会窥探、复制以至修正Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。 假如选用Cookie,比较好的方法是,敏感的信息如账号密码等尽量不要写到Cookie中。最好是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只要本人能读得懂。而假如选择Session就省事多了,反正是放在服务器上,Session里任何隐私都能够有效的保护。
4、有效期上的不同
只需要设置Cookie的过期时间属性为一个很大很大的数字,Cookie就可以在浏览器保存很长时间。 由于Session依赖于名为JSESSIONID的Cookie,而Cookie JSESSIONID的过期时间默许为–1,只需关闭了浏览器(一次会话结束),该Session就会失效。
5、对服务器造成的压力不同
Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。
4 JSP基本入门
4.1 JSP概述
JSP全名是Java Server Pages,称为Java的动态服务器端网页技术。
Java程序直接嵌入到了HTML中, 页面称为jsp页面, JSP文件的扩展名为.jsp。
4.2 JSP中编写java代码
常用格式一: <% java代码段 %>
- 作用1: 当请求该JSP页面时, 会执行<% %>中的java代码
- 作用2: 拼接java逻辑代码, 实现嵌套html标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
常用格式一: <% java代码段 %>
- 作用1: 当请求该JSP页面时, 会执行<% %>中的java代码
- 作用2: 拼接java逻辑代码, 实现嵌套html标签
--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 作用1: 当请求该JSP页面时, 会执行<% %>中的java代码 --%>
<%-- 控制台打印5次Hello jsp --%>
<%
for(int i=0; i<5; i++){
System.out.println("Hello JSP");
}
%>
<%--作用2: 拼接java逻辑代码, 实现嵌套html标签--%>
<%--JSP页面中, 使用h3标签, 打印5次Hello JSP --%>
<% for(int i=0; i<5; i++){ %>
<h3>hello JSP</h3>
<% } %>
</body>
</html>
常用格式二: <%= java的表达式内容 %>
- 作用: 当请求该JSP页面时,会把<%= %>中的java的表达式内容输出到浏览器页面, 可用来替代response对象向页面输出内容
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
常用格式二: <%= java的表达式内容 %>
- 作用: 当请求该JSP页面时,会把<%= %>中的java的表达式内容输出到JSP页面, 可用来替代response对象向页面输出内容
--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%= 123 %>
<%= "hello" %>
<%= Math.random() %>
<%= new Date().toLocaleString() %>
<%= request.getContextPath() %>
</body>
</html>
JS表达式 格式三: <%! java语句; %>
(不常用)
作用: 用于 定义成员变量, 例如 <%! int i=100; %>
jsp页面中的注释格式:
<!-- HTML中的注释 -->
JSP中存在,翻译后的.java存在,浏览器源码中存在
<%
//
/* */
%>
JSP中存在,翻译后的.java存在,浏览器查看源码中没有
<%-- JSP特有注释 --%>
只在JSP源代码中出现(建议使用)
4.3 JSP页面的执行原理
通过上述的体验jsp之后,我们发现jsp真的非常厉害. 既可以编写java代码, 也可以编写html代码,还可以使用request对象.
- 如何实现的呢? 我们来看执行原理图, 再去看代码
观看java源文件后,得出小结:
- jsp之所以可以直接使用request对象,是因为JSP本质就是Servlet, 我们自己编写的代码全部都落入到了service方法内部,在service方法内部一开始就已经声明了request等对象了。
- jsp之所以可以编写html代码,其本质上也是类似我们使用Servlet直接输出的。
<html>
<head>
<title>Title</title>
</head>
<body>
<!--
JSP页面的执行原理
Java代码,归JVM运行,需要编译为class文件
C:\Users\shisongonly\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_5_32_JavaWeb_4\work\Catalina\localhost\web03\org\apache\jsp\jsp
直接使用Tomcat运行,文件会在Tomcat的work目录下
c.jsp 被翻译为 c_jsp.java 编译为 c_jsp.class
jsp本质就是Servlet!!
< % %> 嵌入的Java代码,被翻译到Servlet的service方法
< %=%> 被翻译到Servlet的service方法,添加输出流
< %! %> 代码,会翻译到Servlet的成员变量,不会在service方法中
-->
<%
String str = "abcdef111";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("2019-1-1");
%>
<%=str %>
<br>
<%=str.length()%>
<%! double d = 1;%>
</body>
</html>
4.4 JSP九大内置对象(也称为隐式对象)
对象名 | 功能 | 类型 | 作用域 |
---|---|---|---|
request | 向客户端请求数据 | javax.servlet.ServletRequest | Request |
response | 封装了jsp产生的响应,然后被发送到客户端以响应客户的请求 | javax.servlet.SrvletResponse | Page |
pageContext | 为JSP页面包装页面的上下文。管理对属于JSP中特殊可见部分中己经命名对象的f访问 | javax.servlet.jsp.PageContext | Page |
session | 用来保存每个用户的信息,以便跟踪每个用户的操作状态 | javax.servlet.http.HttpSession | Session |
application | 应用程序对象 | javax.servlet.ServletContext | Application |
out | 向客户端输出数据 | javax.servlet.jsp.JspWriter | Page |
config | 表示Servlet的配置,当一个Servlet初始化时,web容器把某些信息通过此对象传递给这个Servlet | javax.servlet.ServletConfig | Page |
page | Jsp实现类的实例,它是jsp本身,通过这个可以对它进行访问 | javax.lang.Object | Page |
exception | 反映运行的异常 | javax.lang.Throwable | Page |