tomcat的运行原理
当用户发起请求时,会访问我们像tomcat注册的端口,任何程序想要运行,都需要有一个线程对当前端口号进行监听,tomcat也不例外。
当监听线程知道用户想要和tomcat连接连接时,那会由监听线程创建socket连接,socket都是成对出现的,用户通过socket像互相传递数据。
当tomcat端的socket接受到数据后,此时监听线程会从tomcat的线程池中取出一个线程执行用户请求。
在我们的服务部署到tomcat后,线程会找到用户想要访问的工程,然后用这个线程转发到工程中的controller,service,dao中,并且访问对应的DB,在用户执行完请求后,再统一返回。
再找到tomcat端的socket,再将数据写回到用户端的socket,完成请求和响应。
通过以上讲解,我们可以得知 每个用户其实对应都是去找tomcat线程池中的一个线程来完成工作的, 使用完成后再进行回收,既然每个请求都是独立的,所以在每个用户去访问我们的工程时,我们可以使用threadlocal来做到线程隔离,每个线程操作自己的一份数据。
使用ThreadLocal保存用户登录信息
1. 为什么使用ThreadLocal
很多项目中需要在代码中使用当前登录用户的信息,但是又不方便把保存用户信息的session对象传来传去,这种情况下,就可以考虑使用 ThreadLocal。ThreadLocal是一个依附于本地线程的变量,按照我的理解,每次对服务器请求,都会使用到一个线程,ThreadLocal的作用就是在这个线程的使用过程中只为这个线程所用。
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?
JDK 中自带的ThreadLocal
类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
2. 使用ThreadLocal替代Session的好处
在同一个线程中可以很方便的获取用户信息,不需要频繁的传递session。
threadlocal本质上是以线程为key存储元素,用户信息保存在线程中,用户的每一次请求,就是一个线程,保存了用户信息,方便我们在后续操作获取用户登录信息。
当请求结束,我们会把保存的用户信息清除掉,防止内存泄漏。
3. ThreadLocal类:
1 | /** |
温馨小贴士:关于threadlocal
在threadLocal中,无论是他的put方法和他的get方法, 都是先从获得当前用户的线程,然后从线程中取出线程的成员变量map,只要线程不一样,map就不一样,所以可以通过这种方式来做到线程隔离
自定义LoginInterceptor登录拦截器实例配置
自定义拦截器需要实现HandleInterceptor接口
三个方法的运行顺序为: preHandle -> postHandle -> afterCompletion;
- 如果preHandle返回值为false,三个方法仅运行preHandle;
- 如果运行拦截放行后的代码出错,则不会执行postHandle;
- 自定义拦截器实例需要实现HandleInterceptor接口;
- 注入到 ioc 自定义拦截器配置需要使用到 拦截器实例;
LoginInterceptor.java
1 | public class LoginInterceptor implements HandlerInterceptor { |
WebMvcConfigurer自定义拦截器配置
让拦截器生效:
1 |
|