于学期末有一个大实验,要求使用Java
相关技术,计划采用AngularJS
与SpringBoot
开发。html
为了提升开发效率,特意在后台启用Spring Data REST
,少写了不少增删改查,不得不感叹SpringBoot
是真的厉害,只在配置文件中加入如下的配置,而后就在配置的url
上生成了相应实体的增删改查、分页排序接口。前端
spring: data: rest: base-path: /data
除了基础的代码以外,登陆也是一大问题,先后台分离如何进行用户认证呢?java
学习了潘老师的教程以后,对Spring
的session
管理也是有了必定了解。git
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
,服务器有session
。spring
在SpringBoot
中,咱们使用依赖注入自动装配HttpSession
,用于管理session
。数据库
可是,Spring
的全部组件,包括Controller
、Service
、Component
默认都是单例模式,那当多用户请求时,是如何保证这个session
,就是当前用户的session
呢?浏览器
知其然,知其因此然。安全
框架只是咱们提高开发效率的一种方式,没了框架,咱们同样能够写,只是会造重复的轮子。
在Java
进入web
领域时,全部的开发都是基于Servlet
接口的,而咱们常说的Tomcat
是一个Servlet
容器。
由于经过HTTP
协议进行数据通讯,因此经常使用的是HttpServlet
抽象类。
在全部的会话跟踪技术中,HttpSession
对象是最强大和最通用的。
HttpSession
对象在用户第一次访问网站的时候自动被建立,能够经过调用HttpServletRequest
的getSession
方法获取该对象。
HttpSession getSession();
能够经过HttpSession
的setAttribute
方法将值放入HttpSession
,该值存储在内存中,因此不要往HttpSession
中放入太多数据。
void setAttribute(String name, Object value);
因此,最原始的写法就像下面这样,从HttpServletRequest
中获取HttpSession
,并设置属性。
request.getSession.setAttribute(CommonService.UserId, user.getId());
在Apache Tomcat
的官方文档中找到了下面一句话。
public interface HttpSessionProvides 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
站点的用户并存储用户相关信息的方式。
因此,我猜测,从cookie
到session
的绑定,应该是Tomcat
为咱们处理的。
若是请求中没有cookie
,在getSession
时建立一个新的session
给我。
若是请求中有cookie
,在getSession
时查询已有的session
,而后把当前cookie
对应的session
给我。
在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
持有请求与响应对象。
因此能够直接在控制器中注入相关对象。
能够直接注入HttpServletRequest
、HttpSession
等对象。
相似下面:
@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
实例,可是HttpServletRequest
和HttpSession
注入的是代理对象,每次请求经过代理对象获取当前请求的request
或session
。
因此单例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 |
必须在指定范围内 |
书籍,举世之宝!
感谢河北工业大学的图书馆,有各类于开发有益的书籍,受益良多。