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>
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/14531478.html