您的位置:首页 > 编程语言 > Java开发

JavaWeb开发中的会话技术[Cookie/Session]

2016-04-20 14:19 746 查看

会话

会话:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。

会话过程中要解决的一些问题:

每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自回产生一些数据,程序要想办法为每个用户保存这些资源。电商中的保存用户的购买的商品。

保存会话数据的两种技术

Cookie:Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去,这样web资源处理的就是用户自己的数据。

Session:Session是服务器技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他的web资源再从用户各自德尔session中取出数据为用户服务。

Cookie

Cookie的访问过程:



javax.servlet.http.Cookie类用于创建一个Cookie,response接口也定义了一个addCookie方法,它用于在其响应头中增加一个相应的
Set-Cookie
头字段。同样在request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。

Cookie类的方法有(最好查看其API):

public Cookie(String name, String value)

setValue 与 getValue

setMaxAge 与 getMaxAge() [秒]

setPath 与 getPath

setDomain 与 getDomain

getName

一个Cookie是一个键值对。

通过Cookie可以保存用户的信息,示例:保存用户的上次的访问的时间并显示出来(通过request获取请求头中带有的Cookie,再通过response的响应头将Cookie值返回给浏览器):

package com.hsx.cookie;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

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 com.hsx.constant.MyConstant;

/**
* 保存用户的上次的访问的时间并显示出来
* @author hsx
*
*/
public class CookieDemo1 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("您上次获取的时间是:");
// 从客户端的请求获取指定的cookie
Cookie[] cookies = request.getCookies();
System.out.println(cookies); // 第一次访问时cookie的值可能为null
for (int i = 0; cookies != null && i < cookies.length; i++) {
Cookie cookie = cookies[i];
System.out.println(cookie.getName());
if (MyConstant.LAST_ACCESS_TIME.equals(cookie.getName())) {
long value = Long.parseLong(cookie.getValue());
out.println(new Date(value).toLocaleString());
}
}
// 把当前的时间写给客户端
Cookie cookie1 = new Cookie(MyConstant.LAST_ACCESS_TIME, System.currentTimeMillis() + "");
cookie1.setPath(request.getContextPath());
cookie1.setMaxAge(10 * 24 * 60 * 60); //存活的时间,默认浏览器的进程
response.addCookie(cookie1);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

this.doGet(request, response);
}

}

--------------------------------------------------------

/**
* 常量接口设计模式(这里只是设置了Cookie的name值)
* @author hsx
*
*/
public interface MyConstant {

String LAST_ACCESS_TIME = "lastAccessTime";
}


Cookie细节:

获取Cookie采用:request.getCookies();

设置Cookie采用:response.addCookie(cookie);

一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(name)和设置值(value)。

一个Web站点可以给一个Web浏览器发送多个Cookie,一个Web浏览器也可以存储多个Web站点提供的Cookie。

浏览器一般存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

如果创建了一个Cookie,并将它发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该Cookie存储在磁盘上,则需要使用maxAge(默认是浏览器的进程),并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该Cookie。

path:默认是产生cookie的应用的访问路径,删除Cookie时,path必须一致,否则不会删除。在应用程序中设置Cookie时[cookie.setPath(“xxx”)]注意:

如果设置了路径,只能被包含的此路径的资源访问。

如果设置的路径是”/servletCS”,该Cookie只能被servletCS这个应用访问。

如果设置的路径是”/servletCS2”,虽然是servletCS应用产生的Cookie,但是该Cookie只能被servletCS2这个应用访问,servletCS是访问不到的。

cookie.setPath(request.getContextPath())
这条语句设置的Cookie是本身这个应用的。由此可得:
request.getContextPath()
是获取该应用[项目]的路径。

如果设置的路径是
cookie.setPath("http://localhost:8080/")
或者
cookie.setPath("/")
这条语句设置的Cookie能被”http://localhost:8080/“下的所有的应用访问。

如果设置的路径是
cookie.setPath("http://localhost:8080/ServletCS/servlet/")
这条语句设置的Cookie能只能被该Servlet访问;即某个Servlet的
url-pattern
配置是servlet2,则该servlet2都不能访问其Cookie。

总结:Cookie是否能被访问到是根据其设置的路径而言的。

//--- 删除指定的cookie  cookie.setMaxAge(0);---//
// 先获取指定的Cookie
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (MyConstant.LAST_ACCESS_TIME.equals(cookie.getName())) {
//设置其maxAge(0):必须有path一致
cookie.setMaxAge(0);
cookie.setPath(request.getContextPath());
//写个客户端
response.addCookie(cookie);
}
}


Cookie应用

模拟用户名登陆,始终保存用户的用户名[CookieDemo2中输入用户名,提交到CookieDemo3中,CookieDemo3对其用户名的Cookie做永久保存,在以后访问CookieDemo2时,用户名能显示出来]

/*---------------CookieDemo2---------------------*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String name = "";
String rem = "";

// 从Cookie中获取用户名
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (MyConstant.USER_NAEM.equals(cookie.getName())) {
name = cookie.getValue();
rem = "checked='checked'";
}
}

// 显示出登陆页面
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>用户登陆</title></head>");
out.println("<body>");
out.println("<form action='/servletCS/CookieDemo3' method='post'>");
out.println("<table width='400' border='1'>");
out.println("<tr>");
out.println("<td>用户名</td>");
out.println("<td><input type='text' name='username' value='" + name + "'/></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td>密码</td>");
out.println("<td><input type='password' name='password'/></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan='2'><input type='checkbox' name='remember' " + rem + " />记住用户名</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan='2'><input type='submit' value='go'/></td>");
out.println("</tr>");
out.println("</table>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
}

/*------------------CookieDemo3--------------------------*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Cookie cookie = null;
String remember = request.getParameter("remember");
System.out.println(remember);
if (remember != null) {
cookie = new Cookie(MyConstant.USER_NAEM, request.getParameter("username"));
cookie.setPath(request.getContextPath());
cookie.setMaxAge(Integer.MAX_VALUE); //永久保存
response.addCookie(cookie);
}
out.println(cookie.getName() + "<br/>");
out.println(cookie.getValue());
}

/*--------------------常量接口设计模式------------------------*/
public interface MyConstant {

String USER_NAEM = "username";
}


Seesion

session的访问过程



在Web开发中,服务器可以为每一个用户浏览器创建一个会话对象(Session对象),注意:一个浏览器独占一个Session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的Session中,当用户使用浏览器访问其他程序时,其他程序可以从用户的Session中取出该用户的数据,为用户服务。

Session和Cookie的主要区别在于:

Cookie是把用户的数据写给用户的浏览器。

Seesion技术把用户的对象写到用户独占的session中。

Session对象是由服务器创建的,开发人员可以调用request对象的getSession方法得到session对象。

Session技术实际上用的Cookie技术。图解说明:

注意:

IE7及以下版本,新开的窗口都会开启一次新会话。

每一个客户端都有各自的Session对象,以SeesionID标识。

Seesion技术实际上是借助Cookie技术实现的,在创建Session对象时,会将该Session对象的ID以Cookie的JSESSIONID=SessionID的形式写给客户端。

session的原理图:



Session默认何时时效?时间到了,就会失效,默认是30分钟。更改Session的默认时间:

在web.xml文件的根元素中增加,单位为分钟。

<session-config>
<session-timeout>1s</session-timeout>
</session-config>


注意:

request.getSession(); // 要是没有Session对象,就立马创建Session对象
request.getSession(false); // 设置了false,要是没有Session对象,不会创建session对象。


IE禁用Cookie后的session处理

解决方案:URL重写(以下方法先检查浏览器是否禁用Cookie,若禁用Cookie那么会在地址栏上加上jsesssionid=xxx,若没有禁用Cookie那么不加jsessionid–>很智能。注意:当禁用Cookie后,要对所有的URL进行重写)

response.encodeRedirectURL(java.lang.String url); //用于对sendRedirect方法后的url地址进行重写。

response.encodeURL(java.lang.String url); //用于对表单action和超链接的url地址进行重写。

String url1 = request.getContextPath() + "/PayServlet";
url1 = response.encodeURL(url1);
out.println("<br/><a href='" + url1 + "'>结账</a>");


案例:

/*-----IndesServlet-----显示所有的商品,提供购买链接 -- 放入购物车*/

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>商品</title></head>");
out.println("<body>");
// 显示所有的商品
List<String> productList = Product.getAllProduct();
out.println("本站有以下好商品:<br/>");
for (String product : productList) {
out.println(product);
String url = request.getContextPath() + "/BuyServlet?name=" + product;
url = response.encodeURL(url); //禁用浏览器的Cookie时使用的
out.println("<a href='" + url + "'>购买</a><br/>");
}
// 转向结账
String url1 = request.getContextPath() + "/PayServlet"; url1 = response.encodeURL(url1); out.println("<br/><a href='" + url1 + "'>结账</a>");
out.println("</body>");
out.println("</html>");
out.close();

/*-----BuyServlet-----购买的Servlet,将商品加入购物车*/

String productName = request.getParameter("name");
productName = new String(productName.getBytes("ISO-8859-1"), "UTF-8");

// 查看Session中是否有购物车
HttpSession session = request.getSession();
Object object = session.getAttribute(MyConstant.MY_CART);
if (null != object) {// 有:取出来,放商品
List<String> cartList = (List<String>) object;
cartList.add(productName);
}
else {// 没有,先构件购物车
List<String> cartList = new ArrayList<String>();
cartList.add(productName);
session.setAttribute(MyConstant.MY_CART, cartList);
}

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("您已经购买了:" + productName);
String url = request.getContextPath() +"/IndesServlet";
url = response.encodeURL(url);
out.println("<br/><br/><a href='"+ url +"'>继续购买</a>");

/*-----PayServlet-----显示购物车中的商品*/

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(false); //只是取
if (session == null) {
out.println("您还未购物");
}
else {
List<String> myCartList = (List<String>) session.getAttribute(MyConstant.MY_CART);
out.println("您购买了以下商品:<br/>");
for (Object object : myCartList) {
out.println(object + "<br/>");
}
}
out.close();


Session开发中遇到的问题?

内存中的Session非常多,怎么办?

用户在购物中,服务器停了该web应用(或者重启了),那么用户购物车中的东西怎么办?

解决办法:将内存中的Session持久化。

何时session会被持久化?[具体是根据服务器的实现定的,对用户来说完全是透明的]

当服务器停止当前应用

内存中的session对象太多

session长时间没有活动(并没有被销毁)

何时会被激活?

当前web应用又启动了

用户又开始使用了(鼠标、键盘又开始使用了)

session中的序列与反序列基本图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: