1.SpringSession简介
1.0.Web项目中的作用域
在Java的Web项目中,提供了3个容器用来存储数据, 方便在各层调用时传递信息.
这些容器包含:
HttpServletRequest request; // 一次请求, 遇到 response 或者 生成页面(页面代码)
HttpSession session; // 一次会话
ServletContext application; // 上下文
这些容器通过 相应的方法操作数据:
.setAttribute("key", value); // 存入数据
.getAttribute("key"); // 取出数据
.removeAttribute("key"); // 从容器中取出数据
由于这些容器所影响的范围各不相同, 所以也叫作用域;
其中session 是跨越同一用户的多次请求来记录数据, 所以常用来记录用户各自的信息.
1.1.HttpSession
HTTP是无状态协议,当一次请求Rquest遇到响应Response后,保存的信息就会消失。第二次请求, 就是一新的请求, 不会保持任何与第一次请求相关的内容。
HttpSession( 简称 session ) 在 Cookie的配合下就能解决这个问题。
当客户端浏览器第一次访问服务器时,服务器会为客户端创建一个session对象, 这个session对象有唯一的sessionId作为标识, 在响应时把sessionId通过Cookie响应给客户端。在服务器session对象可以保存用户信息等信息, 然后把session对象放到session池中,注意,只有在第一次访问时,服务器才会创建session,给客户端响应sessionId。从此以后就不会了!
当客户端再次访问服务器时,会在请求头信息中带着sessionId给服务器,服务器通过sessionId到session池中找到session对象,进而得到在session中保存的信息, 这就可以完成会话跟踪了。也就是说,服务器端保存的是session对象,而客户端只有sessionId。每次访问都需要通过客户端的sessionId来匹配服务器端的session对象!这样用户在session中保存的数据就可以再次被使用了。
在 Controller 加入下面的方法
@RequestMapping("/testSession")
public String testSession(HttpSession session, ModelMap modelMap){
System.out.println("session.getId() = " + session.getId());
modelMap.put("sessionid", session.getId());
return "test";
}
@RequestMapping("/testCookie")
public String testCookie(HttpSession session, ModelMap modelMap){
System.out.println("session.getId() = " + session.getId());
modelMap.put("sessionid", session.getId());
return "test";
}
添加 页面 test.html, 在页面中加入
<span th:text="${sessionid}"></span> :
<a th:href="@{/testCookie}">testCookie</a>
打开开发者工具, 再查看cookie中的信息
再 打开 网络 , 点击 testCookie 超链接
查看 请求头信息
1.2.session 与 cookie
什么是Cookie?
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端会把Cookie保存起来。Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。
session 与 cookie 两者的区别:在安全和性能方面考虑
1、cookie数据存放在客户端,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑性能应当使用cookie。
4、不同浏览器对cookie的数据大小限制不同,个数限制也不相同。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、可以考虑将登陆信息等重要信息存放为session,不重要的信息可以放在cookie中。
两者的联系:
1、都是用来记录用户的信息,以便让服务器分辨不同的用户。
2、可以搭配使用,但都有自己的使用局限,要考虑到安全和性能的问题。
1.2.1.自定义 cookie 存储信息
在 controller 的方法中增加 :
// 将接收到的用户登录信息再保存到cookie中, 返回给浏览器
Cookie cookieUsername = null;
Cookie cookiePassword = null;
Cookie cookieRememberMe = null;
System.out.println("rememberMe:" + rememberMe);
if("true".equals(rememberMe)) {
cookieUsername = new Cookie("username", tchUser);
cookiePassword = new Cookie("password", tchPass);
cookieRememberMe = new Cookie("rememberMe", rememberMe);
// 定义保存时长 单位: 秒
cookieUsername.setMaxAge(60*60*24*30);
cookiePassword.setMaxAge(60*60*24*30);
cookieRememberMe.setMaxAge(60*60*24*30);
response.addCookie(cookieUsername);
response.addCookie(cookiePassword);
response.addCookie(cookieRememberMe);
}else {
cookieUsername = new Cookie("username", tchUser);
cookiePassword = new Cookie("password", tchPass);
cookieRememberMe = new Cookie("rememberMe", rememberMe);
cookieUsername.setMaxAge(0);
cookiePassword.setMaxAge(0);
cookieRememberMe.setMaxAge(0);
response.addCookie(cookieUsername);
response.addCookie(cookiePassword);
response.addCookie(cookieRememberMe);
}
在登录页面中html部分 , 通过表单提交将Controller传递信息
<form name="info" th:action="@{/login}" method="post" >
<div class="form-group has-feedback">
<input type="text" name="tchUser" id="user" class="form-control" required placeholder="账号">
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" name="tchPass" id="pass" class="form-control" required placeholder="密码" >
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label>
<input type="checkbox" name="rememberMe" value="true"> 记住账号
</label>
</div>
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">登 录</button>
</div>
</div>
</form>
在 登录页面的javascript脚本中 , 从cookie中取出数据
$(function(){
// console.log(document.cookie);//username=admin; password=111211
var name = getCookie('username');
var pass = getCookie('password');
var rememberMe = getCookie('rememberMe');
if("true" == rememberMe){
$("#user").val(name);
$("#pass").val(pass);
// $("#rm").prop("checked", "checked");
$('input').iCheck('check')
}else{
$("#user").val("");
$("#pass").val("");
// $("#rm").prop("checked", false);
}
});
//根据key得到cookie中的值
function getCookie(c_name) {
if(document.cookie.length > 0) {
c_start = document.cookie.indexOf(c_name + "=");//获取字符串的起点
if(c_start != -1) {
c_start = c_start + c_name.length + 1;//获取值的起点
c_end = document.cookie.indexOf(";", c_start);//获取结尾处
if(c_end == -1) c_end = document.cookie.length;//如果是最后一个,结尾就是cookie字符串的结尾
return decodeURI(document.cookie.substring(c_start, c_end));//截取字符串返回
}
}
return "";
}