1.处理Cookie
HTTP协议的无连接性要求出现一种保存C/S间状态的机制
HTTP的无连接性(客户端的浏览器可以通过输入网址连接网站服务器,当客户端从服务器上拿到内容之后,该连接就断开了,例如购物网站再一个网址选择东西之后,服务器将信息反馈给客户端,当去另一个页面结账时就会不知道你买了什么),解决办法:可以利用Cookie先将信息保存在客户端,只允许写文本文档,客户端可以阻止服务器写内容,只能拿自己webapp写入的东西。cookie分两种:属于窗口/子窗口;属于文本。
Cookie:保存到客户端的一个文本文件,与特定客户相关。
乱码的解决:
生成cookie:
java.sql中的方法 String username =URLEncoder.encoder(request.getParmeter("username"),"utf-8");
写在上述方法的最前面:
request.setCharacterEncoder("utf-8");
解析cookie:c
request.setCharacterEncoder("utf-8");
username = URLDecoder.decoder(c.getValue(),"utf-8");
Cookie以"名-值"对的形式保存数据,创建Cookie:new
seName(String name)/getName()
setValue(String value)/getValue()
setMaxAge(int age)/getMaxAge()
利用HttpServletResponse的addCookie(Cookie)方法将它设置到客户端
利用HttpServletRequest的getCookie()方法来读取客户端的所有Cookie,返回一个Cookie数组
如下例:
首先写一个设置Cookie的文件
public class SetCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 向客户端写入Cookie,共6个
for (int i = 0; i < 3; i++) {
// 3个没有设置时间的Cookie(或者设置成-1),属于本窗口及其子窗口
Cookie cookie = new Cookie("Session-Cookie-" + i, "Cookie-Value-S" + i);
response.addCookie(cookie);
// 以下3个Cookie设置了时间(3600秒,1小时),属于文本,别的窗口也可以访问到这些Cookie
cookie = new Cookie("Persistent-Cookie-" + i, "Cookie-Value-P" + i);
cookie.setMaxAge(3600);
response.addCookie(cookie);
}
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
String title = "Setting Cookies";
out.println("<html><head><title>设置Cookie</title></head>"
+ "<body>" + title + "<br>"
+ "There are six cookies associates with this page.<br>"
+ "to see them,visit the <a href='ShowCookie'>\n"
+ "<code>ShowCookie</code> servlet</a>"
+ "</body></html>");
}
}
然后读取Cookie
public class ShowCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter pw = response.getWriter();
String title = "Active Cookies";
pw.println("init");
pw.println("<html><head><title>读取客户端</title></head>"
+ title
+ "\n" + "<table border=1 align=center>\n"
+ "<TH>Cookie Name<TH>Cookie Value" + "<br>");
// 读取客户端的所有Cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Cookie cookie;
for (int i = 0; i < cookies.length; i++) {
cookie = cookies[i];
pw.println("<tr>\n" + "<td>" + cookie.getName() + "</td>\n"
+ "<td>" + cookie.getValue() + "</td></tr>\n");
}
}
pw.println("</table>\n<body><html>");
}
}
然后在浏览器上输入http://localhost:8080/TestHTTP/servlet/SetCookie就设置了cookie到客户端,点击ShowCookie
servlet 便可读取cookie
如果现在在开一个ShowCookieservlet只能看见Persistentcookie,因为在该cookie中session是没有设置生存周期,跟第一个开的网页是同步的,而persistent是有生存周期的,被存在内存中,其他网页可以读取。但是如果在第一个showcookieservlet中ctrl+n(new一个新网页),此时会显示session的内容,因为这种方式的打开是存在一种父子关系。
在内存中储存的cookie的内容:
1.如果把ShowCookie的web.xml文件的url-pattern改成/ShowServlet,意味着ShowCookie比SetCookie高一个等级,此时先访问servlet/SetCookie,在访问ShowCookie,此时ShowCookie上什么都没有。
结论:一个servlet/JSP设置的cookie能够被同一个路径下面或者是子路径下面的servlet/jsp读到(路径=URL,路径!=真实的文件路径)
2.Session
也是用来记录一系列的状态,记录在服务器端,cookie记录在客户端(可以随便改,删,不稳定)。在某段时间一连串客户端与服务器端的交易。
当访问服务器端时,服务器端会给你开一块内存,就是session,而这块内存是和浏览器的窗口或子窗口关联在一起,服务器端会给浏览器创建一个独一无二的号码,一一对应。
session两种实现方法一个通过cookie实现。二:在Jsp/Servlet中,如果浏览器不支持cookie,可以通过URL重写来实现,就是将一些额外数据追加到表示会话的每一个URL末尾,服务器在该标识符与其存储的有关的该会话的数据之间建立关联。如hello.jsp?jsessionid=1234。
规则:
如果浏览器支持cookie,创建session的时候会把session保存在cookie里
如果不支持cookie,必须自己编程使用URL重写的方式实现session,
response.encodeURL()
session不像Cookie拥有路径访问的问题,同一个Application下的Servlet/jsp可以共享同一个session,前提是同一个客户端窗口。
可以通过程序来终止一个会话,如果客户端在一定时间内没有操作,服务器会自动终止会话。
HttpServletRequest中session的管理方法
getRequestedSessionId();返回随客户端请求到来的会话ID,可能与当前会话ID相同,也可能不同。
getSession(booleanisNew);如果会话已经存在,则返回一个HttpSession,如果不存在并且isNew为true,则会新建一个HttpSession
isRequestedSessionIdFrom
isRequestedSessionIdFrom
isRequestedSessionIdVali
HttpSession的常用方法:
getCreationTime() //返回session的创建时间
getId() //拿到该session的ID号
getMaxInactiveInterval()//获得session的最大存活时间,默认是1800秒!就是说你不动浏览器,在三十分钟后它会自动消毁
isNew() //是不是新创建的
setAttribute(String, Object) //设置一个名-值对
setMaxInactiveInterval(int interval)//设置最大存活时间秒数,负值表示一直存在
getLastAccessedTime() //返回最近的一次访问时间
先设置一个SessionInfoServlet来创建session:
public class SessionInfoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession mySession = request.getSession(true);
//什么时候创建一个session,flase就是要拿这个session,如果没有不会创建,true如果没有创建一个,如果有就拿这个session
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Session Info Servlet";
out.println("<html>");
out.println("<head>");
out.println("<title>Session Info Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h3>Session Infomation</h3>");
out.println("New Session:" + mySession.isNew() + "<br>");
out.println("Session Id:" + mySession.getId() + "<br>");
out.println("Session Create Time:" + new Date(mySession.getCreationTime()) + "<br>");
out.println("Session Last Access Time:" + new Date(mySession.getLastAccessedTime()) + "<br>");
out.println("<h3>Request Infomation</h3>");
out.println("Session Id From Request:" +request.getRequestedSessionId() + "<br>");
// 返回随客户端请求到来的会话ID
out.println("Session Id Via Cookie:" +request.isRequestedSessionIdFromCookie() + "<br>");
// 当前的Session ID如果是从cookie获得,为true
out.println("Session Id Via URL:" +request.isRequestedSessionIdFromURL() + "<br>");
// 当前的Session ID如果是从URL获得,为true
out.println("Valid Session Id:" +request.isRequestedSessionIdValid() + "<br>");
out.println("</body></html>");
out.close();
}
}
网页内容:Session Infomation
New Session:true
Session Id:64164718FF1A9286F6496F79
Session Create Time:Sun May 03 17:54:02 GMT+08:00 2015
Session Last Access Time:Sun May 03 17:54:02 GMT+08:00 2015
Request Infomation
Session Id From Request:null
Session Id Via Cookie:false
Session Id Via URL:false
Valid Session Id:false
访问showCookie时,会出现cookie,说明创建session时,会把sessionID存在cookie中,当窗口关闭后该session就不存在了,当再起其他的窗口,sessionID不会相同。
当阻止所有cookie时,打开后每次刷新都会设置一个新的SessionID
如果在 out.println("《/body》《/html》");前加上out.println("《a href=" +response.encodeURL("SessionInfoServlet") +"》refresh《/a》");此时不允许Cookie的情况下,点击refresh刷新session就不会变。但在URL地址变成http://localhost:8080/TestHTTP/servlet/SessionInfoServlet;jsessionid=3021C03B1E8159DB27BC8B91
session过期:一个Session存在的时长,在web.xml中设置session
<session-config>
<session-timeout>30</session-timeout>
</session-config>
ShowSession例子程序:
public class ShowSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
String str = "Session Tracking Example";
String heading;
// 如果会话已经存在,则返回一个HttpSession;否则创建一个新的
HttpSession session = request.getSession(true);
// 从当前session中读取属性accessCount的值
Integer accessCount = (Integer) session.getAttribute("accessCount");
if (accessCount == null) {
accessCount = new Integer(0);
heading = "Welcome newUser";
} else {
heading = "Welcome Back";
accessCount = new Integer(accessCount.intValue() + 1);
}
// 向当前session中插入键(key,属性)值(value)对
session.setAttribute("accessCount", accessCount);
out.println("<html><head><title>Session追踪</title></head>"
+ "<body>" + heading + "<br>"
+ "Information on Your Session"
+ "\n" + "<table border=1 align=center>\n"
+ "<TH>Info Type<TH>Value" + "<br>"
+ "<tr>\n" + "<td>ID</td>\n"
+ "<td>" + session.getId() + "</td></tr>\n"
+ "<tr>\n" + "<td>CreatTime</td>\n"
+ "<td>" + new Date(session.getCreationTime()) + "</td></tr>\n"
//返回值是long,就是一个数值,new data将其转化成日期
+ "<tr>\n" + "<td>LastAccessTime</td>\n"
+ "<td>" + new Date(session.getLastAccessedTime()) + "</td></tr>\n"
+ "<tr>\n" + "<td>Number of Access</td>\n"
+ "<td>" + accessCount + "</td></tr>\n"
+ "</body></html>");
}
}
刷新,数字会逐一增加,当新起一个窗口显示的是0次,因为一个新的窗口就是一个新的session
修改servlet/SessionInfoServlet和/ShowSession,先用sessioninfoservlet创建session,可以用ShowSessions访问。
session的生命周期:
创建:
当客户端第一次访问某个jsp或servlet时候,服务器会为当前回话创建一个sessionid,每次客户端向服务器发送请求时,都会将此sessionid携带过去,服务器会对此sessionid进行校验,判断是否属于同一次会话。
活动:
当某次会话当中通过超链接打开的新页面属于同一次会话。
只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
除非本次会话的所有页面都关闭后再重新访问某个jsp或servlet将会创建新的会话。
注意:原有的会话还存在,只是这个旧的sessionid仍然存在于服务器端,只不过在没有客户端会携带他然后交与服务器校验。
销毁:
调用session.invalidate()方法
session过期(超时)
服务器重新启动
设置超时:
tomcat默认session超时时间是30分钟
或者1.session.setMaxInactiveInterval(时间);秒
2.web.xml配置:
<session-config>
<session-timeout>10</session-timeout>
</session-config>