Spring Session的理解

问题描述

于学期末有一个大实验,要求使用Java相关技术,计划采用AngularJSSpringBoot开发。html

为了提升开发效率,特意在后台启用Spring Data REST,少写了不少增删改查,不得不感叹SpringBoot是真的厉害,只在配置文件中加入如下的配置,而后就在配置的url上生成了相应实体的增删改查、分页排序接口。前端

spring:
  data:
    rest:
      base-path: /data

除了基础的代码以外,登陆也是一大问题,先后台分离如何进行用户认证呢?java

用户认证

学习了潘老师的教程以后,对Springsession管理也是有了必定了解。git

HTTP

HTTP is stateless: But while the core of HTTP itself is stateless, HTTP cookies allow the use of stateful sessions. Using header extensibility, HTTP Cookies are added to the workflow, allowing session creation on each HTTP request to share the same context, or the same state.web

HTTP是无状态的,虽然HTTP自身是无状态的,可是cookie容许有状态session的使用。经过使用Header的扩展,cookie被添加到工做流中,这些cookie容许在每个HTTP请求建立会话,去共享上下文,或共享状态。正则表达式

浏览器有cookie,服务器有sessionspring

Session

SpringBoot中,咱们使用依赖注入自动装配HttpSession,用于管理session数据库

clipboard.png

可是,Spring的全部组件,包括ControllerServiceComponent默认都是单例模式,那当多用户请求时,是如何保证这个session,就是当前用户的session呢?浏览器

Servlet

知其然,知其因此然。安全

框架只是咱们提高开发效率的一种方式,没了框架,咱们同样能够写,只是会造重复的轮子。

Java进入web领域时,全部的开发都是基于Servlet接口的,而咱们常说的Tomcat是一个Servlet容器。

由于经过HTTP协议进行数据通讯,因此经常使用的是HttpServlet抽象类。

clipboard.png

在全部的会话跟踪技术中,HttpSession对象是最强大和最通用的。

HttpSession对象在用户第一次访问网站的时候自动被建立,能够经过调用HttpServletRequestgetSession方法获取该对象。

HttpSession getSession();

能够经过HttpSessionsetAttribute方法将值放入HttpSession,该值存储在内存中,因此不要往HttpSession中放入太多数据。

void setAttribute(String name, Object value);

login

因此,最原始的写法就像下面这样,从HttpServletRequest中获取HttpSession,并设置属性。

request.getSession.setAttribute(CommonService.UserId, user.getId());

Apache Tomcat的官方文档中找到了下面一句话。

public interface HttpSession

Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user.

公共接口 HttpSession

提供一种认证跨页面或浏览Web站点的用户并存储用户相关信息的方式。

因此,我猜测,从cookiesession的绑定,应该是Tomcat为咱们处理的。

若是请求中没有cookie,在getSession时建立一个新的session给我。

若是请求中有cookie,在getSession时查询已有的session,而后把当前cookie对应的session给我。

SpringMVC

SpringMVC中,请求的分发是经过org.springframework.web.servlet.DispatcherServlet完成的。

[dɪˈspætʃə(r)] ['sɜ:vlet]
Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers or HTTP-based remote service exporters. Dispatches to registered handlers for processing a web request, providing convenient mapping and exception handling facilities.

HTTP请求的前端控制器,为了web ui控制器或者基于HTTP的其余服务,它为一个web请求注册handler,提供了方便的映射与异常处理工具。

由于控制器的方法是被DispatcherServlet所调度的,DispatcherServlet持有请求与响应对象。

因此能够直接在控制器中注入相关对象。

Spring 参考文档

能够直接注入HttpServletRequestHttpSession等对象。

相似下面:

@PostMapping("/test")
public void test(HttpServletRequest request, HttpSession session) {
}

固然,由于request中就有session,因此也能够在request中获取session

以上方法确定没问题,直接在参数列表中注入,确定线程安全。

若是改为以下写法,它仍是线程安全的吗?

@Autowired
private HttpServletRequest request;
@Autowired
private HttpSession session;

@PostMapping("/test")
public void test() {
}

Spring 中获取 request 的几种方法,及其线程安全性分析

经测试,是的。Controller是单例,可是Controller是线程安全的。

由于Spring容器在启动的时候,建立Controller实例,可是HttpServletRequestHttpSession注入的是代理对象,每次请求经过代理对象获取当前请求的requestsession

因此单例Controller能保证不一样请求有不一样的session,而且是线程安全的。

官方是更加推荐使用@Autowired注入HttpSession,由于这样注入的方式不局限于控制器内,若是Service中也想用当前的session,也能注入进来。

附加

记得以前对实体中某个属性设置not null,发现有@Column(nullable = false)@NotNull两种方法。

今天在看《SpringMVC初学指南时》明白了第二种写法。

第一种是Hibernate中的,是在插入数据库时进行验证。

第二种是SpringMVC支持的JSR(Java规范请求,Java Specification Requests)中的,用于对控制器中接收的对象进行验证。

因此实际符合需求的是@Column(nullable = false)

@PostMapping("/test")
public void test(@Valid @RequestBody Teacher teacher) {
}

JSR规范约束表

属性 描述
@AssertFalse boolean属性必须为false
@AssertTrue boolean属性必须为true
@DecimalMax 该属性值必须小于等于指定的小数
@DecimalMin 该属性值必须大于等于指定的小数
@Digits 应用于BigDecimal,约束最大整数与最大小数。
@Future 必须是将来的一个日期
@Past 必须是过去的一个日期
@Max 最大值
@Min 最小值
@NotNull 不为Null
@Null 必须为Null
@Pattern 必须匹配该正则表达式
@Size 必须在指定范围内

总结

书籍,举世之宝!
感谢河北工业大学的图书馆,有各类于开发有益的书籍,受益良多。
Facebook的全栈工程师,在遇到一个问题时,在亚马逊上买一本相关书籍,通读一晚上,而后解决问题。一块儿加油!
相关文章
相关标签/搜索