RedisSession (自定义)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了 RedisSession (自定义),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8602字,纯文字阅读大概需要13分钟。
内容图文
![RedisSession (自定义)](/upload/InfoBanner/zyjiaocheng/880/84fdbf62db9d45899cc3eff00308aabe.jpg)
RedisSession (自定义)
疯狂创客圈 Java 高并发【 亿级流量聊天室实战】实战系列 【博客园总入口 】
架构师成长+面试必备之 高并发基础书籍 【Netty Zookeeper Redis 高并发实战 】
疯狂创客圈 高并发 环境 视频,陆续上线:
- Windows Redis 安装(带视频)
- Linux Redis 安装(带视频)
- Windows Zookeeper 安装(带视频)
- Linux Zookeeper 安装(带视频)
- RabbitMQ 离线安装(带视频)
- Nacos 安装(带视频)
- ElasticSearch 安装, 带视频**
小视频以及所需工具的百度网盘链接,请参见 疯狂创客圈 高并发社群 博客
场景和问题
一般,大家获取 Session 的方式: session = request.getSession(), 是通过HttpServletRequest 获取的,因为每次用户请求过来,我们服务端都会获取到请求携带的唯一 SessionId。
如果自定的 HttpSession的,所以我们还要自定义一个 HttpServletRequest 的包装类,使得每次请求获取的都是我们自己的HttpSession。
还有一点 ,如何 使用HttpServletRequest 包装类呢?
还需要自定义一个 Filter,这个Filter不干其它的事情,就负责把HttpServletRquest 换成我们自定义的包装类。
第一步 ,定义一个 RedisHttpSession
RedisHttpSession 实现 HttpSession 接口 ,选择Redis存储属性,达到分布式的目标。
session在 Redis中 选择的 Hash 结构存储,以 sessionId 作为Key,有些方法不需要实现。
//首先我说过,HttpSession是不能注入属性的,所以就需要依赖 上面定义的那个 工具类,获取bean
//如果不加此注解,你的属性就会为空,获取不到
@DependsOn("applicationContextUtil")
@SpringBootConfiguration
public class CustomRedisHttpSession implements HttpSession {
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
private Cookie[] cookies;
//sessionId
private String sessionId;
public CustomRedisHttpSession(){}
public CustomRedisHttpSession(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,String sid){
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
this.cookies = cookies;
this.sessionId =sid;
}
/**
* 获取指定属性值
* @param key 属性key
* @return key对应的value
*/
@Override
public Object getAttribute(String key) {
if(sessionId != null){
return sessionRedisTemplate.opsForHash().get(sessionId,key);
}
return null;
}
/**
* 之前说过了,此类属性不能注入,只能通过手动获取
*/
@SuppressWarnings("unchecked")
private final RedisTemplate<String,Object> sessionRedisTemplate =
=ApplicationContextUtil.getBean("sessionRedisTemplate",RedisTemplate.class);
//sessionId 的前缀
private static final String SESSIONID_PRIFIX="yangxiaoguang";
/**
* 设置属性值
* @param key key
* @param value value
*/
@Override
public void setAttribute(String key, Object value) {
if (sessionId != null) {
sessionRedisTemplate.opsForHash().put(sessionId, key, value);
}else{
//如果是第一次登录,那么生成 sessionId,将属性值存入redis,设置过期时间,并设置浏览器cookie
this.sessionId = SESSIONID_PRIFIX + UUID.randomUUID();
setCookieSessionId(sessionId);
sessionRedisTemplate.opsForHash().put(sessionId, key, value);
sessionRedisTemplate.expire(sessionId, sessionTimeout, TimeUnit.SECONDS);
}
}
//session的过期时间,8小时
private final int sessionTimeout=28800;
//将sessionId存入浏览器
private void setCookieSessionId(String sessionId){
Cookie cookie = new Cookie(SESSIONID,sessionId);
cookie.setPath("/");
cookie.setMaxAge(sessionTimeout);
this.httpServletResponse.addCookie(cookie);
}
/**
* 移除指定的属性
* @param key 属性 key
*/
@Override
public void removeAttribute(String key) {
if(sessionId != null){
sessionRedisTemplate.opsForHash().delete(sessionId,key);
}
}
}
第2步 ,定义一个 ServletRequestWrapper
如果自定的 HttpSession的,所以我们还要自定义一个 HttpServletRequest 的包装类,使得每次请求获取的都是我们自己的HttpSession。
public class CustomSessionHttpServletRequestWrapper extends HttpServletRequestWrapper{
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
//自定义Session
private CustomRedisHttpSession customRedisHttpSession;
public CustomSessionHttpServletRequestWrapper(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
super(httpServletRequest);
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
Cookie[] cookies = httpServletRequest.getCookies();
String sid= getCookieSessionId(cookies);
this.customRedisHttpSession = new
CustomRedisHttpSession(httpServletRequest,httpServletResponse,sid);
}
//这个方法就是最重要的,通过它获取自定义的 HttpSession
@Override
public HttpSession getSession() {
return this.customRedisHttpSession;
}
//浏览器的cookie key
private static final String SESSIONID="xyzlycimanage";
//从浏览器获取SessionId
private String getCookieSessionId(Cookie[] cookies){
if(cookies != null){
for(Cookie cookie : cookies){
if(SESSIONID.equals(cookie.getName())){
return cookie.getValue();
}
}
}
return null;
}
}
如果从header 中获取 sessiondi,也是类似的:
public class CustomSessionHttpServletRequestWrapper extends HttpServletRequestWrapper{
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
//自定义Session
private CustomRedisHttpSession customRedisHttpSession;
public CustomSessionHttpServletRequestWrapper(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
super(httpServletRequest);
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
String sid= request.getHeader("SESSION_ID");
this.customRedisHttpSession = new
CustomRedisHttpSession(httpServletRequest,httpServletResponse,sid);
}
//这个方法就是最重要的,通过它获取自定义的 HttpSession
@Override
public HttpSession getSession() {
return this.customRedisHttpSession;
}
//浏览器的cookie key
private static final String SESSIONID="xyzlycimanage";
//从浏览器获取SessionId
private String getCookieSessionId(Cookie[] cookies){
if(cookies != null){
for(Cookie cookie : cookies){
if(SESSIONID.equals(cookie.getName())){
return cookie.getValue();
}
}
}
return null;
}
}
第三步: 定义一个 Filter 类
还有一点 ,如何 使用HttpServletRequest 包装类呢?
还需要自定义一个 Filter,这个Filter不干其它的事情,就负责把HttpServletRquest 换成我们自定义的包装类。
/**
* 此过滤器拦截所有请求,也放行所有请求,但是只要与Session操作的有关的请求都换被
* 替换成:CustomSessionHttpServletRequestWrapper包装请求,
* 这个请求会获取自定义的HttpSession
*/
public class CustomSessionRequestFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain)
throws IOException, ServletException {
//将请求替换成自定义的 CustomSessionHttpServletRequestWrapper 包装请求
HttpServletRequest customSessionHttpServletRequestWrapper =
new CustomSessionHttpServletRequestWrapper
((HttpServletRequest)servletRequest,(HttpServletResponse)servletResponse);
filterChain.doFilter(customSessionHttpServletRequestWrapper,
httpServletResponse);
//替换了 请求哦
filterChain.doFilter(customSessionHttpServletRequestWrapper,servletResponse);
}
/**
* init 和 destroy 是管理 Filter的生命周期的,与逻辑无关,所以无需实现
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
}
四步 装载 Filter 类
可以独立加载,也可以放在springsecurity 的配置类中。
如果放在springsecurity 的配置类,具体如下:
package com.gsafety.pushserver.message.config;
//...
@EnableWebSecurity()
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(
//...
"/actuator/hystrix",
"/actuator/hystrix.stream",
"/v2/api-docs",
"/swagger-resources/configuration/ui",
"/swagger-resources",
"/swagger-resources/configuration/security",
"/swagger-ui.html")
.permitAll()
// .antMatchers("/image/**").permitAll()
// .antMatchers("/admin/**").hasAnyRole("ADMIN")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().disable()
.sessionManagement().disable()
.and()
.logout().disable()
.addFilterBefore(new CustomSessionRequestFilter(), SessionManagementFilter.class)
.sessionManagement().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
//....
"/actuator/hystrix.stream",
"/actuator/hystrix",
"/api/mock/**",
"/v2/api-docs",
"/swagger-resources/configuration/ui",
"/swagger-resources",
"/swagger-resources/configuration/security",
"/api/gemp/duty/info/user/login",
"/swagger-ui.html",
"/css/**",
"/js/**",
"/images/**",
"/webjars/**",
"**/favicon.ico"
);
}
}
具体,请关注 Java 高并发研习社群 【博客园 总入口 】
最后,介绍一下疯狂创客圈:疯狂创客圈,一个Java 高并发研习社群 【博客园 总入口 】
疯狂创客圈,倾力推出:面试必备 + 面试必备 + 面试必备 的基础原理+实战 书籍 《Netty Zookeeper Redis 高并发实战》
疯狂创客圈 Java 死磕系列
Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战
- Netty 源码、原理、JAVA NIO 原理
- Java 面试题 一网打尽
疯狂创客圈 【 博客园 总入口 】
内容总结
以上是互联网集市为您收集整理的 RedisSession (自定义)全部内容,希望文章能够帮你解决 RedisSession (自定义)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。