Servlet之间数据共享的实现方案
1、数据共享:OneServlet工作完毕之后,将产生的数据交给TwoServlet来使用
2、在Servlet规范中提供了四种数据共享方案:
1)ServletContext接口
2)Cookie类
3)HttpSession接口
4)HttpServletRequest接口
ServletContext接口
1、介绍:
1)来自于Servlet规范中的一个接口。在Tomcat中存在于servlet-api.jar
在Tomcat中负责提供这个接口的实现类
2)如果两个Servlet来自于同一个网站。彼此之间通过网站中的ServletContext
实例对象来实现数据共享。
3)开发人员习惯于将ServletContext对象称为【全局作用域对象】
2、工作原理:
每一个网站里面都存在一个全局作用域对象。
这个全局作用于对象【相当于】一个Map。
在这个网站中OneServlet可以将一个数据存入到全局作用域对象中,当前网站中
其他的Servlet此时都可以从全局作用域对象得到这个数据进行使用。
3、全局作用域对象的声生命周期(不是自己创建的)
1)在Http服务器启动的过程中,自动为当前网站在内存中创建一个全局作用域对象
2)在Http服务器运行期间,一个网站只有一个全局作用域对象
3)在Http服务器运行期间,全局作用域对象一直处于存活状态
4)在Http服务器准备关闭的时候,负责将当前网站中全局作用域对象进行销毁处理
******全局作用域对象的生命周期贯穿网站的整个运行期间******
4、命令实现:
【同一个网站】OneServlet将数据分享给TwoServlet
OneServlet{
protected void doGet(HttpServletRequest request,HttpServletResponse response){
//1、通过请求对象向Tomcat索要当前网站中的【全局作用域对象】
ServletContext application=request.getServletContext();
//2、将数据添加到全局作用域对象中作为【共享数据】
application.setAttribute("key1","数据");
}
}
TwoServlet{
protected void doGet(HttpServletRequest request,HttpServletResponse response){
//1、通过请求对象向Tomcat索要当前网站中的【全局作用域对象】
ServletContext application=request.getServletContext();
//2、从全局作用域对象得到指定关键字对应数据
Object obj=application.getAttribute("key1");
}
}
代码展示
public class OneServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String s="abc";
//通过请求对象获取全局作用域对象
ServletContext application=request.getServletContext();
//将数据添加到全局作用域对象中
application.setAttribute("key1",s);
}
}
public class TwoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out=null;
//通过响应对象获取全局作用域对象
ServletContext application=request.getServletContext();
//通过全局作用对象来回去数据
String s=(String)application.getAttribute("key1");
response.setContentType("text/html");
out=response.getWriter();
System.out.println(s);
out.print(s);
}
}
Cookie类
1、介绍:
1)Cookie是来自于Servlet规范中的一个工具类存在于Tomcat提供的servlet-api.jar中
2)如果两个Servlet来自于同一个网站,并且为同一个用户/浏览器提供服务,此时可以借助于
Cookie对象进行数据共享
3)Cookie存放当前用户的私人数据,在共享数据的过程中来提高服务质量
4)在现实生活的场景中,Cookie相当于用户在服务端得到的【会员卡】
2、相关原理:
用户通过浏览器第一次向myWeb网站发送请求申请OneServlet。
OneServlet在运行期间创建一个Cookie存储与当前用户相关的数据
OneServlet工作完毕之后,【将Cookie写入到响应头中】来交还给
当前浏览器。
浏览器在收到这个响应包之后,将Cookie存储在浏览器的缓存中。
一段时间之后,用户通过同一个浏览器再次向myWeb网站发送请求申请TwoServlet时。
【浏览器需要无条件的将myWeb网站之前推送过来的Cookie,写入到请求头】发送过去。
此时TwoServlet在运行时,就可以通过读取请求头中Cookie中的信息,得到OneServlet
提供的共享数据。
3、实现命令:
同一个网站中的OneServlet与TwoServlet借助于Cookie实现数据的共享方案
OneServlet(HttpServletRequest request,HttpServletResponse response){
protected void doGet{
//创建一个Cookie对象,来保存共享数据(当前用户的共享数据)
Cookie card=new Cookie("key1","abc");
Cookie card1=new Cookie("key2","efg");
****Cookie相当于一个map
****一个Cookie中只能放一个键值对
****这个键值对的key和value只能是String
****键值对中的key不能是中文
//将Cookie写入到响应头,交给浏览器
request.addCookie(card);
request.addCookie(card1);
....
}
}
浏览器向myWeb网站发送请求请求访问TwoServlet----->请求包【url:/myWeb/two method:get】
【
请求参数:***
cookie key1=abc;key2=efg
】
【】
【】
TwoServlet(HttpServletRequest request,HttpServletResponse response){
protected void doGet{
//调用请求对象从请求头得到浏览器返回的Cookie
Cookie cookieArray=request.getCookies();
//循环遍历数组得到每一个cookie
for(Cookie card:cookieArray){
String key=card.getName();
String value=card.getValue();
}
}
}
4、Cookie的销毁时机
1)默认情况下,Cookie对象是存放在浏览器的缓存中。
只有浏览器关闭,Cookie对象就被销毁。
2)在手动设置的情况下,可以要求浏览器将接受的Cookie
存放在客户端计算机的硬盘上。同时需要指定Cookie在硬盘
上的存活时间,在存活时间范围内,关闭浏览器,关闭客户端
计算机,关闭服务器,都不会导致Cookie被销毁。在存活时间
到达时,Cookie自动从硬盘上被删除。
cookie.setMaxAge(60);表示Cookie对象将在硬盘上存活60s
代码实现
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: red" align="center">登录界面</h1>
<hr>
<form action="/myWeb/one" >
<table align="center" border="1px">
<tr>
<td>用户名</td>
<td>
<input type="text" name="userName" />
</td>
</tr>
<tr>
<td>预存金额</td>
<td>
<input type="text" name="money" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="submit" />
<input type="reset" value="reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
OnsServlet
package school.xauat.controller;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class OneServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName,money;
//通过请求对象获取请求参数
userName=request.getParameter("userName");
money=request.getParameter("money");
//创建Cookie对象
Cookie cookie1=new Cookie("userName",userName);
Cookie cookie2=new Cookie("money",money);
//指定cookie对象在硬盘上存活1mins
//cookie2.setMaxAge(60);
//通过响应对象将Cookie对象放入响应头中
response.addCookie(cookie1);
response.addCookie(cookie2);
//通过请求转发的方式访问index_1.html
request.getRequestDispatcher("index_1.html").forward(request,response);
}
}
index_1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 align="center" style="color:red;">点餐界面</h1>
<hr>
<form action="/myWeb/two">
<table align="center" border="1px">
<tr>
<td><input type="radio" name="food" value="jiaozi" />饺子$30</td>
</tr>
<tr>
<td><input type="radio" name="food" value="miantiao" />面条$25</td>
</tr>
<tr>
<td><input type="radio" name="food" value="gaifan" />盖饭$20</td>
</tr>
<tr>
<td><input type="submit" value="submit" /></td>
</tr>
</table>
</form>
</body>
</html>
TwoServlet
package school.xauat.controller;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TwoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String food,userName = null;
int money=0;
Cookie newCookie=null;
PrintWriter out=null;
//通过请求对象获取请求参数
food=request.getParameter("food");
//获取请求头中的Cookie对象
Cookie[] cookies=request.getCookies();
//遍历cookies获取userName和money
for(Cookie cookie:cookies){
String key=cookie.getName();
String value=cookie.getValue();
if ("userName".equals(key)){
userName=value;
}
if ("money".equals(key)){
money=Integer.valueOf(value);
}
}
response.setContentType("text/html;charset=utf-8");
//通过响应对象获取输出流
out=response.getWriter();
//根据food的值进行不同的消费
if ("jiaozi".equals(food)){
if (money>=30){
money-=30;
newCookie=new Cookie("money",String.valueOf(money));
out.print(userName+"您好,您本次消费30元,余额为:"+money);
System.out.println(1);
}else{
out.print(userName+"您好,您的余额不足,余额:"+money);
}
}
if ("miantiao".equals(food)){
if (money>=25){
money-=25;
newCookie=new Cookie("money",String.valueOf(money));
out.print(userName+"您好,您本次消费25元,余额为:"+money);
}else{
out.print(userName+"您好,您的余额不足,余额:"+money);
}
}
if ("gaifan".equals(food)){
if (money>=20){
money-=20;
newCookie=new Cookie("money",String.valueOf(money));
out.print(userName+"您好,您本次消费20元,余额为:"+money);
}else{
out.print(userName+"您好,您的余额不足,余额:"+money);
}
}
//如果消费成功,将cookie对象通过响应对象加入到响应头中
if (newCookie!=null){
response.addCookie(newCookie);
}
}
}
HttpSession接口
1、介绍:
1)HTTPSession接口来自于Servlet规范下的一个接口,存在于Tomcat中servlet-api.jar
其相关的实现类由Http服务器提供。Tomcat提供的实现类存在于servlet-api.jar
2)如果两个Servlet来自于同一个网站,并且为同一个用户/浏览器提供服务,此时可以借助于
HTTPSession对象进行数据共享
3)开发人员习惯于将HttpSession接口修饰对象称为【会话作用域对象】
2、HttpSession与Cookie区别【面试题】
1)存储位置:
Cookie存放在客户端计算机中(浏览器内存/硬盘)
HTTPSession存放在服务端计算机的内存中
2)数据类型:
Cookie对象存储共享数据类型只能是String
HTTPSession对象可以存储任意类型的共享数据Object
3)存储的数据数量:
一个Cookie对象只能存放一个共享数据
HttpSession使用Map集合存储共享数据,所以可以存储任意数量的共享数据
4)参照物不同:
Cookie相当于客户在服务端的【会员卡】数据量不大,数据类型单一
HTTPSession相当于客户在服务端的【私人保险柜】
3、命令实现:
同一个网站下(myWeb)OneServlet将数据传递给TwoServlet
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//调用请求对象向Tomcat索要当前用户在服务端的会话作用域对象
HttpSession session=request.getSession();
//将数据添加到用户的会话作用域对象
session.setAttribute("key1",共享数据);
}
}
浏览器访问/myWeb中的TwoServlet
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//通过请求对象向Tomcat索要当前用户在服务端的会话作用域对象
HttpSession session=request.getSession();
//从会话作用域对象中得到OneServlet提供的共享数据
Object 共享数据=session.getAttribute("key1");
}
}
代码实现
下面用HttpSession接口实现购物车功能
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车</title>
</head>
<body>
<h1 style="color:red;" align="center">京东</h1>
<hr>
<table align="center" border="1px">
<thead>
<tr>
<td>商品名称</td>
<td>商品单价</td>
<td>介绍</td>
<td>加入购物车</td>
</tr>
</thead>
<tr>
<td>Dell</td>
<td>6500</td>
<td>好东西</td>
<td><a href="one?product=Dell">加入购物车</a></td>
</tr>
<tr>
<td>Lenovo</td>
<td>6000</td>
<td>好东西</td>
<td><a href="one?product=Lenovo">加入购物车</a></td>
</tr>
<tr>
<td>MacBook</td>
<td>7000</td>
<td>好东西</td>
<td><a href="one?product=MacBook">加入购物车</a></td>
</tr>
<tr>
<td colspan="4" align="center">
<a href="/myWeb/two">查看我的购物车</a>
</td>
</tr>
</table>
</body>
</html>
OneServlet
public class OneServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String product;
//通过请求对象获取请求头中的请求参数
product=request.getParameter("product");
//通过请求对象向Tomcat服务器索要会话作用域对象
HttpSession session = request.getSession();
request.getSession(false);
//将数据添加到会话作用域对象中
Integer productNum=(Integer)session.getAttribute(product);
if (productNum==null){
session.setAttribute(product,1);
}else{
session.setAttribute(product,productNum+1);
}
}
}
TwoServlet
public class TwoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象获取会话作用域对象
HttpSession session = request.getSession();
//从会话作用域对象中读取所有的key值,存放在一个枚举中
Enumeration<String> products = session.getAttributeNames();
//循环遍历所有的共享数据
while(products.hasMoreElements()){
String product=products.nextElement();
int productNum=(int)session.getAttribute(product);
System.out.println("商品名称:"+product+"商品数量:"+productNum);
}
}
}
4、Http服务器如何将用户与HttpSession关联起来
Cookie
5、getSession()和getSession(false)
1)getSession()
如果当前用户在服务端中已经拥有了自己的会话作用域对象
要求Tomcat将这个会话作用域对象进行返回。
如果当前用户在服务端尚未拥有自己的会话作用域对象。
要求Tomcat为当前用户创建一个全新的会话作用域对象。
2)getSession(false)
如果当前用户在服务端中已经拥有了自己的会话作用域对象
要求Tomcat将这个会话作用域对象进行返回。
如果当前用户在服务端尚未拥有自己的会话作用域对象。
此时Tomcat将返回一个null。
6、HttpSession销毁时机
1、用户与HttpSession关联时使用的Cookie只能存放在浏览器的缓存中。
2、在浏览器关闭的时候,意味着用户与他的HttpSession关系被切断。
3、Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时,并不会导致Tomcat将浏览器关联的HttpSession进行销毁
4、为了解决这个问题,Tomcat会为每一个HttpSession对象设置【空闲时间】,这个空闲时间默认是30mins,如果当前HttpSession对象
空闲时间达到了30mins,此时Tomcat认为用户已经放弃了自己的HttpSession,此时Tomcat就会销毁掉这个HeepSession。
7、HttpSession空闲时间的手动设置
在当前网站下/web/WEB-INF/web.xml
<session-config>
<session-timeout>5</session-timeout><!--当前网站中每一个session最大的空闲时间是5mins-->
</session-config>
HttpServletRequest接口
1、介绍:
1)在同一个网站中,如果两个Servlet之间是通过【请求转发】的方式进行调用的
他们彼此之间将共享同一个请求协议包,而一个请求协议包只对应一个请求对象,因此
这个两个Servlet共享同一个请求对象,此时可以利用这个请求对象在两个Servlet之间
实现数据共享。
2)在请求对象实现Servlet之间的数据共享的功能时,开发人员将请求对象称为【请求作用域对象】
2、命令实现:
OneServlet同过请求转发申请调用TwoServlet时,需要给TwoServlet提供共享数据
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//将数据添加到请求作用域对象中的attribute属性中
request.setAttribute("key1",数据);//数据类型可以使任意类型的Object
//向Tomcat申请调用TwoServlet
//通过请求对象生成申请资源文件报告
request.getRequestDispatcher("/two").forward(request,response);
}
}
TwoServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//从当前请求对象中得到OneServlet写入的共享数据
Object obj=request.getAttribute("key1");
}
}
代码实现
OneServlet
public class OneServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//将共享数据添加到请求作用域对象的attribute属性中
request.setAttribute("key",500);
//通过请求转发的方式调用TwoServlet
RequestDispatcher report=request.getRequestDispatcher("/two");
report.forward(request,response);
}
}
TwoServlet
public class TwoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象获取共享数据
Integer num=(Integer) request.getAttribute("key");
System.out.println(num);
}
}