Java_web——Session技术
1、Session当服务器运行到request.getSession()时就会被创建(当此用户Session已存在就不会再创建)
2、Session默认当30分钟没人使用就会摧毁(或者你调用Session.invalidate()就会被摧毁)
3、request.getSession(false)只会获取已存在的Session,就算对这个用户的Session不存在也不会创建
4、Session的多长时间没人使用就摧毁可以定义在web.xml文件中
//10分钟不使用的Session就摧毁掉 <session-config> <session-timeout>10</session-timeout> </session-config>
5、request.getSession()是怎么样判断这个用户的session是否存在呢?
其实每一个session都有一个id号,服务器把这个id号以cookie的形式写会用户浏览器,但是这个cookie的生存时间是默认的(也就是说当用户的浏览器进程一旦终止,这个cookie也就没有了)
下面我们写一个设置session的id有效期的代码:
购买SessionDemo.java
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; /** * Servlet implementation class SessionDemo */ @WebServlet("/SessionDemo") public class SessionDemo extends HttpServlet { //购买 private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub HttpSession session = request.getSession(); String sessionid = session.getId(); //获取session的id Cookie cookie = new Cookie("JSESSIONID",sessionid); //session把id写回浏览器时用的Cookie名为JSESSIONID cookie.setPath("/day02"); cookie.setMaxAge(30*60); //设置cookie有效期为30分钟 response.addCookie(cookie); session.setAttribute("name", "洗衣机"); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
结账SessionDemo1.java
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; /** * Servlet implementation class SessionDemo1 */ @WebServlet("/SessionDemo1") public class SessionDemo1 extends HttpServlet { //结账 private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub 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); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
ind.html
<!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>
5、response有一个方法encodeURL(示例:response.encodeURL("/day02/SessionDemo")),这个方法你需要提供给它一个链接,它会返回给你一个链接,返回给你的链接后面可能会把session的id追加到后面(为什么说可能,因为如果服务器检测到你带cookie来了,那就说明你的浏览器没有禁用cookie,那么session就可以正常工作,那么就不会把session的id追加到链接后面。但是如果你禁用session了,那么这个函数就会把session的id追加到你提供链接后面)。当第一次访问这个网站,服务器不知道你禁用cookie了没有,那么服务器即会给你以cookie形式返回session的id,还会给你提供的链接后面把session的id追加上去。
6、用session解决表单重复提交的问题
表单重复提交:当提交表单之后一旦刷新你之前做的事情就会重新做一次
或者是由于网络延迟,导致你点击提交按钮多次,都会让服务器接收到多次提交表单的信息
这个问题可以由JavaScript来解决,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
/* 第一种JavaScript解决表单重复提交
var issub = false;
function dosubmit(){
if(!issub){
issub=true;
return true;
}else {
return false;
}
}*/
//第二种解决表单重复提交
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
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;
/**
* Servlet implementation class formRandom
*/
//产生表单
@WebServlet("/formRandom")
public class formRandom extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//产生表单号
TokenRandom tr = TokenRandom.getRandom();
String token = tr.generateRandom();
request.getSession().setAttribute("token", token);
request.getRequestDispatcher("/form.jsp").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
class TokenRandom{
//采用单例模式:在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
/*步骤
* 1、构造方法私有化
* 2、自己创建一个
* 3、对外暴露一个方法,允许获得上面创建的对象
*/
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()+"";
//上面产生的字符串长度不一致,我们需要使用md5得到token字符串的摘要,获得的字符串md5摘要长度为128位
try {
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
//又因为我们需要获得一个字符串,所以我们采用base64把md5摘要过的byte数组转换为字符串
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
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;
/**
* Servlet implementation class SessionDemo2
*/
@WebServlet("/SessionDemo2")
public class SessionDemo2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
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;
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
form.jsp
<%@ 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>