解决浏览器和服务器间的数据共享问题。
HttpSession session=request.getSession();
HttpSession session=request.getSession(false);
false:在内存中查找,如果找不到也不创建session(只查找不创建)
session.setAttribute("name","张三");
String nameString=session.getAttribute("name");
session.removeAttribute("name");
session.getId();
a.默认存储在浏览器的缓存中,浏览器关闭即结束;如果浏览器不关闭,默认的生命周期为:由开发者决定,tomcat默认30分钟.
tomcat session生命周期设置:
b.可存储在硬盘上(一般不存储,没有必要),存储步骤如下:
Cookie cookie=new Cookie("JSESSION",session.getId());
cookie.setMaxAge(Integer.MAX_VALUE);
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
c.设置立刻失效
session.invalidate();
思路:将物品放在集合中,集合再放在session中。
(1).显示所有的书籍以及书籍信息链接,并提供查看购物车的超链。
(2).显示每一本书的详细信息,提供放入购物车的链接并提供书籍id,以及返回首页的链接。
(3).查看购物车
a.从session中获取所购书籍集合
List
if(list=null){
outer.writer("您还没有选择要购买的书籍...");
outer.writer("返回");
return 0;
}
outer.write("购买书籍如下");
for(Book book:list){
outer.write(book.getName()+":"+book.getCount()+"
"));
}
outer.write("继续购物
");
outer.write("结账
");
(4).将购买的书籍放入购物车中。
a.首先从session中拿取集合对象。
HttpSession session=request.getSeesion();
List
第一次访问时carlist不存在,需创建。
b.找到要放入购物车的商品id
String bookid=request.getParameter("id");
Book book=BookUtils.getBookById(bookid);
c.判断集合中是否已经购买了该书
//直接获得该书在集合中的索引。
int index=list.indexOf(book);//需重写equals方法,在book类中。
/*
public boolean equals(Object obj){
Book b=(Book)obj;
return id.equals(b.getId());
}
*/
如果没有购买
if(index==-1){
book.setCount(1);
list.add(book);
}else{
//书的属性是没有数量的,实际中需要另外建立类文件存储。
Book book=list.get(index);
book.setCount(book.getCount()+1);
}
d.将添加后的书籍列表存入session
session.setAttribute("carlist",list);
e.打印放入购物车成功信息,并提供返回首页按钮。
(5)结账
a.判断支付页面是否直接访问(如果直接访问,session为新创建的)
HttpSession session=request.getSession();
//判断session是否为新创建的
//实际当中不能使用该方法(如果多次刷新该页面即可破解该步骤);
if(session.isNew()){
outer.write("需要先添加购物商品...两秒后自动跳转到主页...");
response.setHeader("Refresh","2;url="+request.getContextPaht()+"/servlet/ShowAllBook");
}
b.拿到购物车中的信息并统计价格
List
float sum=0;
for(Book book:list){
sum+=book.getPrice()*book.getCount();
}
outer.writer("商品总价为:"+sum+"$
");
思路:在服务端设置”口令“,该”口令“只有一次有效期,客户端有一个和服务端相同的”口令。
第一次提交口令对比成功则提交,提交后口令失效。
第二次提交时由于口令失效不能提交。
具体实现:
(a).提交页面在生成前需先产生一个唯一的“口令”
如何生成唯一的“口令”
方式一:
String word="";
//生成一个唯一的时间值。
word=System.nanoTime()+"";
方式二:
//生成唯一的值;
word=UUID.randomUUID().toString();
//前两种可查看值,不大安全。
方式三:
byte[] bs=word.getBytes();
//数据指纹
word=System.nanoTime()+new Random().nextLong()+"";
//加密数据
MessageDigest md=MessageDegest.getInstance("MD5");
//对字节数组进行md5加密。
bs=md.degest(bs);
//将加密后的字节数组转化为string
//引入Base64Encoder: java build path ->access ->Accessable->**
BASE64Encoder base=new BASE64Encoder();
word=base.encode(bs);
将word存入session
session.setAttribute("tooken",word);
在表单中放置一个隐藏的文本框
提交时在服务端对word和session中的word进行对比,如果匹配则提交,否则不处理。
(b).在提交页面中拿到用户名和口令,再拿到session中的口令,并对比两个口令。
if(clientToken.equals(servToken)){
//保存用户。
//用户保存后将口令销毁
session.removeAttribute("token");
}else{
outer.write();
}
详细代码实现:
表单提交和口令加密部分:
1: package net.csing;
2:
3: import java.io.IOException;
4: import java.io.PrintWriter;
5: import java.security.MessageDigest;
6: import java.security.NoSuchAlgorithmException;
7: import java.util.Random;
8:
9: import javax.servlet.ServletException;
10: import javax.servlet.http.HttpServlet;
11: import javax.servlet.http.HttpServletRequest;
12: import javax.servlet.http.HttpServletResponse;
13:
14: import sun.misc.BASE64Encoder;
15:
16: public class Index extends HttpServlet {
17:
18: public void doGet(HttpServletRequest request, HttpServletResponse response)
19: throws ServletException, IOException {
20:
21: response.setContentType("text/html;charset=utf-8");
22: PrintWriter out=response.getWriter();
23: //创建口令
24: String word="";
25: word=System.nanoTime()+new Random().nextLong()+"";
26: byte[] bs=word.getBytes();
27: //加密口令
28: MessageDigest md;
29: try {
30: /*
31: * 此部分为口令加密部分。
32: */
33: md = MessageDigest.getInstance("MD5");
34: //对字节数组进行md5加密。
35: bs=md.digest(bs);
36: //将加密后的字节数组转化为string
37: //引入Base64Encoder: java build path ->access ->Accessable->**
38: BASE64Encoder base=new BASE64Encoder();
39: //编码,word为完成加密后的口令。
40: word=base.encode(bs);
41: } catch (NoSuchAlgorithmException e) {
42:
43: e.printStackTrace();
44: }
45: //向session中写入口令信息;
46: request.getSession().setAttribute("token", word);
47:
48: //设置表单提交路径和提交方式。
49: out.write("
50: out.write("用户名
");
51: //口令信息随着表单一块提交。
52: out.write("
");
53: out.write("");
54: /*
55: * 该口令只在页面刷新时生成,并写进session中;
56: * 如果同一个页面提交多次,表单中的口令为原口令,但session中的口令已经通过服务器设置失效。
57: */
58:
59: }
60:
61: public void doPost(HttpServletRequest request, HttpServletResponse response)
62: throws ServletException, IOException {
63:
64: response.setContentType("text/html");
65:
66: }
67:
68: }
69:
口令验证:
1: package net.csing;
2:
3: import java.io.IOException;
4: import java.io.PrintWriter;
5:
6: import javax.servlet.ServletException;
7: import javax.servlet.http.HttpServlet;
8: import javax.servlet.http.HttpServletRequest;
9: import javax.servlet.http.HttpServletResponse;
10: import javax.servlet.http.HttpSession;
11:
12: public class manage extends HttpServlet {
13:
14: public void doGet(HttpServletRequest request, HttpServletResponse response)
15: throws ServletException, IOException {
17: response.setContentType("text/html");
19: }
20:
21: public void doPost(HttpServletRequest request, HttpServletResponse response)
22: throws ServletException, IOException {
23:
24: //表单中设置了post提交方式,在doPost函数中处理表单信息。
25: response.setContentType("text/html;charset=utf-8");
26:
27: PrintWriter out=response.getWriter();
28: //获得表单中的口令信息;
29: String wordString=request.getParameter("token");
30: //获得session中的口令信息;
31: HttpSession session=request.getSession();
32: String word=(String)session.getAttribute("token");
33: //将session中的口令和表单中的口令进行对比。
34: //如果口令对比成功则设置该口令立即失效,该口令只能使用依次,即仅进行一次提交。
35: if(wordString.equals(word)){
36: out.write("提交成功");
37: session.removeAttribute("token");
39: }
40: //如果口令不对,则为重复提交。
41: else{
42: out.write("请不要重复提交。");
43: }
44: }
46: }
(a).告诉客户端不要禁止。
(b).URL重写
目的:在网址之后附加JSESSIONID:id;(传递本页面的JSESSION到请求的页面)
解决部分客户端浏览器禁止cookie导致session不能用。
url=request.getContextPath+"/servlet/servletDemo2";
url=response.encodeURL(url);
缺点:所有的url都需要重写,比较麻烦。
获取session的状态,防止服务器出现故障;或者服务器内存不够(服务器将释放部分内存)。
服务器重启时需将session数据存储到硬盘中防止数据丢失,重启后重新读取到内存。
session存储到硬盘的过程叫做搁置或者固化;
session从硬盘重新读取到内存的过程叫做激活或者活化;