Servlet第四天会话与状态
什么是会话?
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
会话过程中要解决的一些问题?
- 每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据。
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
1.案例:返回上次访问时间
public class CookieTest extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<a href='/day07/CookieTest2'>清除上次访问时间</a>");
out.print("你上次访问时间是:");
// 获得用户的时间cookie
//获取cookie数组
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().equals("lastAccessTime")) {
// 获取上次访问的时间
long value = Long.parseLong(cookies[i].getValue());
Date date = new Date(value);
out.print(date.toLocaleString());
}
}
// 返回新的访问时间
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()
+ "");
// setMaxAge() 设置有效期 单位是秒 默认有效期是浏览器进程
cookie.setMaxAge(30 * 24 * 3600);
// 设置cookie path
cookie.setPath("/day07");
response.addCookie(cookie);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.Cookie细节
一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
注意,删除cookie时,path必须一致,否则不会删除(默认:产生cookie服务器资源所在path)
删除上次访问时间
public class CookieTest2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()
+ "");
// 设置有效期
cookie.setMaxAge(0);
cookie.setPath("/day07");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
Session生命周期:
session创建:当客户端访问服务器,服务器端还没有该会话的session对象时,创建。request.getSession()--创建
session销毁:三种情况:1.服务器停止,2.session.invalidate 3.session过期(session.setMaxInactiveInterval)、配置web.xml(单位分钟 ,默认30分钟)
案例 1:购买商品
/**
* 购买商品
*
* @author malinkang
*
*/
public class SessionTest extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取用户的Session
HttpSession session = request.getSession();
// 获取Session Id
String sessionid = session.getId();
//session将id存入cookie 从而区分是那个用户的session
Cookie cookie = new Cookie("JSESSIONID", sessionid);
cookie.setPath("/day07");
cookie.setMaxAge(30 * 60);
response.addCookie(cookie);
// 获取Session的重载形式
// request.getSession(false);
//
session.setAttribute("product", "洗衣机");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
public class SessionTest2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
String product = (String) session.getAttribute("product");
out.write("你购买的商品是" + product);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
浏览器禁用cookie处理方案:
案例:防止表单提交
客户端防止提交
<script type="text/javascript">
var isCommitted false;
function checkPost(){
if(!isCommitted){
isCommitted=true;
return true;
}else{
return false;
}
}
</script>
服务端防止重复提交
1.表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
2.当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
在下列情况下,服务器程序将拒绝用户提交的表单请求:
1.存储Session域中的表单标识号与表单提交的标识号不同
2.当前用户的Session中不存在表单标识号
3.用户提交的表单数据中没有标识号字段
工具类:
import java.util.UUID;
//令牌
public class TokenProcessor {
// 生成唯一标识
public static String getToken() {
// UUID技术
return UUID.randomUUID().toString();
}
}
表单提交
<%
//获取令牌
String token=TokenProcessor.getToken();
session.setAttribute("session_token",token);
%>
<form method="post" action="/day07/SessionTest3" onsubmit="return checkPost()">
用户名:<input type="text" name="username"/>"
密码:<input type="text" name="password"/>
<input type="hidden" name="token" value="<%=token %>"/>
<input type="submit" value="登陆"/>
</form>
处理方法
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 模拟网路延时
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String token = request.getParameter("token");
String session_token = (String) request.getSession().getAttribute(
"session_token");
request.getSession().removeAttribute("session_token");
if (token.equals(session_token)) {
String username = request.getParameter("username");
System.out.println(username);
}
}
案例三:用户登陆注销
登陆界面
<form action="/day07/LoginServlet" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="提交"/>"
</form>"
登陆处理:
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
String password = request.getParameter("password");
DB db = new DB();
List<User> users = db.getAll();
for (User user : users) {
if (username.equals(user.getUsername())
&& password.equals(user.getPassword())) {
request.getSession().setAttribute("user", user);
response.sendRedirect("/day07/index.jsp");
return;
}
}
out.write("用户名或密码错误");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
class DB {
private static List<User> list = new ArrayList<User>();
static {
list.add(new User("aaa", "123"));
list.add(new User("bbb", "123"));
list.add(new User("ccc", "123"));
}
public static List<User> getAll() {
return list;
}
}
跳转到首页处理: 欢迎你:${user.username}
注销 :删除session
案例四:用户一次验证