JAVAJAVAJava_web Session技术
StarJava_web——Session技术
- Session当服务器运行到request.getSession()时就会被创建(当此用户Session已存在就不会再创建)
- Session默认当30分钟没人使用就会摧毁(或者你调用Session.invalidate()就会被摧毁)
- request.getSession(false)只会获取已存在的Session,就算对这个用户的Session不存在也不会创建
- Session的多长时间没人使用就摧毁可以定义在web.xml文件中
1 2 3 4
| //10分钟不使用的Session就摧毁掉 <session-config> <session-timeout>10</session-timeout> </session-config>
|
- request.getSession()是怎么样判断这个用户的session是否存在呢?
其实每一个session都有一个id号,服务器把这个id号以cookie的形式写会用户浏览器,但是这个cookie的生存时间是默认的(也就是说当用户的浏览器进程一旦终止,这个cookie也就没有了)
下面我们写一个设置session的id有效期的代码:
购买SessionDemo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package test;
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
@WebServlet("/SessionDemo") public class SessionDemo extends HttpServlet { private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String sessionid = session.getId(); Cookie cookie = new Cookie("JSESSIONID",sessionid); cookie.setPath("/day02"); cookie.setMaxAge(30*60); response.addCookie(cookie); session.setAttribute("name", "洗衣机"); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
|
结账SessionDemo1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package test;
import java.io.IOException; import java.io.PrintWriter;
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
@WebServlet("/SessionDemo1") public class SessionDemo1 extends HttpServlet { private static final long serialVersionUID = 1L;
protected 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("name"); out.write("你购买得商品为:"+product); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
|
ind.html
1 2 3 4 5 6 7 8 9 10 11
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <a href="/day02/SessionDemo">购买</a> <a href="/day02/SessionDemo1">结账</a> </body> </html>
|
response有一个方法encodeURL(示例:response.encodeURL(“/day02/SessionDemo”)),这个方法你需要提供给它一个链接,它会返回给你一个链接,返回给你的链接后面可能会把session的id追加到后面(为什么说可能,因为如果服务器检测到你带cookie来了,那就说明你的浏览器没有禁用cookie,那么session就可以正常工作,那么就不会把session的id追加到链接后面。但是如果你禁用session了,那么这个函数就会把session的id追加到你提供链接后面)。当第一次访问这个网站,服务器不知道你禁用cookie了没有,那么服务器即会给你以cookie形式返回session的id,还会给你提供的链接后面把session的id追加上去。
用session解决表单重复提交的问题
表单重复提交:当提交表单之后一旦刷新你之前做的事情就会重新做一次
或者是由于网络延迟,导致你点击提交按钮多次,都会让服务器接收到多次提交表单的信息
这个问题可以由JavaScript来解决,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript">
function dosubmit(){ var input = document.getElementById("submit"); input.disable='disable'; return true; } </script> </head> <body> <form action="/day02/SessionDemo2" method="post" onsubmit="return dosubmit()"> 用户名2:<input name="username" type="text"><br/> <input id="submit" type="submit" value="提交" ><br/> </form> </body> </html>
|
但是这种方法是不彻底的,因为JavaScript代码可以在用户浏览器上被用户更改而使得没有彻底解决问题,或者用户提交表单之后刷新,或者用户不断地点击前进和后退按钮。
在这种情况下我们使用session来解决这个问题,我们给予每一个表单一个表单号,存放到session中,如果这个表单被提交过了就把相应的表单号从session中删除,一个表单号只能用于提交一次。
formRandom.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| package test;
import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random;
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Encoder;
@WebServlet("/formRandom") public class formRandom extends HttpServlet { private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TokenRandom tr = TokenRandom.getRandom(); String token = tr.generateRandom(); request.getSession().setAttribute("token", token); request.getRequestDispatcher("/form.jsp").forward(request, response); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
} class TokenRandom{
private TokenRandom() {} private static final TokenRandom random = new TokenRandom(); public static TokenRandom getRandom() { return random; } public String generateRandom() { String token = System.currentTimeMillis()+new Random().nextInt()+""; try { MessageDigest md = MessageDigest.getInstance("md5"); byte[] md5 = md.digest(token.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(md5); }catch(NoSuchAlgorithmException e) { throw new RuntimeException(e); } } }
|
给一个Base64算法的内部实现:https://blog.csdn.net/benbenxiongyuan/article/details/7756912
SessionDemo2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package test;
import java.io.IOException; import java.io.PrintWriter;
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@WebServlet("/SessionDemo2") public class SessionDemo2 extends HttpServlet { private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); boolean b = isTokenValid(request); if(!b) { out.print("请不要重复提交"+"<br/>"); return; } request.getSession().removeAttribute("token"); System.out.println("向数据库注册用户"); }
private boolean isTokenValid(HttpServletRequest request) { String client_token = request.getParameter("token"); if(client_token==null) { return false; } String server_token = (String) request.getSession().getAttribute("token"); if(server_token==null) { return false; } if(!server_token.equals(client_token)) { return false; } return true; }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
}
|
form.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action="/day02/SessionDemo2" method="post"> <input type="hidden" name="token" value="${ token}"> 用户名2:<input name="username" type="text"><br/> <input id="submit" type="submit" value="提交" ><br/> </form> </body> </html>
|