欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

session共享多节点部署之redis

程序员文章站 2022-03-22 21:22:47
...
第一步:导入相关依赖jar包在pom.xml文件;
<!-- redis依赖 start -->
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- spring session的依赖 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
        <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<!-- redis依赖 end -->

第二步:配置文件配置连接redis相关配置项;
#redis的ip地址 
spring.redis.host=10.4.4.11
#密码 
spring.redis.password=sdj
#端口号 
spring.redis.port=6379
#spring.redis.database=0
#spring.session.store-type=redis

#开启cookie安全
server.servlet.session.cookie.secure=false


#客户端超时时间单位是毫秒 默认是2000
redis.timeout=100000 

#最大空闲数 
redis.maxIdle=5
#最小空闲数
redis.minIdle=2 
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal 
redis.maxTotal=20
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 
redis.maxWaitMillis=1000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 
redis.testOnBorrow=true 

第三步:编写连接redis工具类 RedisConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.pay.common.util.RedisUtil;
import com.pay.common.util.UtilJedis;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
* redis配置类
*
* @author
*
*/
@Configuration
public class RedisConfig {

@Value("${redis.maxIdle}")
private Integer maxIdle;

@Value("${redis.minIdle}")
private Integer minIdle;

@Value("${redis.maxTotal}")
private Integer maxTotal;

@Value("${redis.maxWaitMillis}")
private Integer maxWaitMillis;

@Value("${redis.testOnBorrow}")
private boolean testOnBorrow;

@Value("${spring.redis.host}")
private String hostName;

@Value("${spring.redis.port}")
private Integer port;

@Value("${spring.redis.password}")
private String password;

@Value("${redis.timeout}")
private Integer timeout;

/**
* JedisPoolConfig 连接池
*
* @return
*/
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲数
jedisPoolConfig.setMaxIdle(maxIdle);
// 连接池的最大数据库连接数
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMinIdle(minIdle);
// 最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setTestOnBorrow(testOnBorrow);

return jedisPoolConfig;
}

@Bean
public JedisPool redisPoolFactory() {
JedisPool jedisPool = new JedisPool(jedisPoolConfig(), hostName, port, timeout, password, 0, "partner:1");
return jedisPool;
}

@Bean(name = "redisUtil")
public RedisUtil redisUtil() {
RedisUtil redisUtil = new RedisUtil();
redisUtil.setJedisPool(redisPoolFactory());
redisUtil.setUtilJedis(getUtilJedis());
return redisUtil;
}

@Bean(name = "utilJedis")
public UtilJedis getUtilJedis() {
return new UtilJedis();
}
}

获取图形验证码接口需要将sessionId对应的图形验证码值存入redis;
String jsessionid = session.getId();
  // 验证码保存到redis;
  redisUtil.setValAndExpire(Constants.REDIS_INVESTOR_CODE_PREFIX + jsessionid, Constants.CODE_TIMEOUT, verifyCode);


第四步: 拦截器处理 LoginInterceptor;
public class LoginInterceptor extends HandlerInterceptorAdapter {

@Autowired
private RedisUtil redisUtil;

//public static String timeOutTemp;
/**
* session超时时间
*/
@Value("${cookie.timeout}")
protected String timeout;
@Autowired
private Environment env;


HttpSession session = request.getSession();
Object username = session.getAttribute(Constants.LOGIN_USER_NAME);
// 分布式环境部署sessionId读取redis存储登录对象信息;
String jsessionid = request.getSession().getId();
// 读取缓存redis登陆态信息
String loginUserInfo = (String) redisUtil.getObject(Constants.SESSION_AUTH + jsessionid);
LoginUserInfo lu = null;
if (StringUtils.isNotBlank(loginUserInfo) && null != JSONValidator.from(loginUserInfo)
&& JSONValidator.from(loginUserInfo).validate()) {
lu = JSON.parseObject(loginUserInfo, LoginUserInfo.class);
}



/**
* 判断同一个登录账号是否在多个浏览器客户端登录成功;
*
* @Title: checkSessionId
* @Description: (校验sessionId是否过期失效)
* @param loginId   String
* @param sessionId String
* @return boolean 返回类型
*/
private boolean checkSessionId(String loginId, String sessionId, HttpServletRequest request) {
boolean flag = true;
// 根据登录查询用户信息,判断userName与sessionId存储在redis中的登录账号名称是否一致;
String jsessionid = request.getSession().getId();
String loginUserInfo = (String) redisUtil.getObject(Constants.SESSION_AUTH + jsessionid);
LoginUserInfo auth = JSON.parseObject(loginUserInfo, LoginUserInfo.class);
if(null == auth) {
return false;
}
//登录账号多端登录,自动踢出系统;
String userName = auth.getLoginName();
String storeRedisJsessionid = redisUtil.getKeyValue(Constants.REDIS_LOGIN_PREFIX + userName);

//     LogUtil.MSG.info("checkSessionId is start 请求报文:sessionId=" + sessionId+"userName="+LogUtil.getName(loginId));
//   LogUtil.MSG.info("checkSessionId is end 响应报文:" + LogUtil.printReqMsg(userInfo));
if (null != auth && jsessionid.equals(storeRedisJsessionid)) {
// 同一客户端登录(当前登录账号对应的sessionId值与数据库存储的Jsessionid一致)
} else {
// 更新数据库sessionId
flag = false;
}
return flag;
}

第五步: 登录接口处理LoginController;
@RequestMapping(value = "/login.action", method = RequestMethod.POST)
@ResponseBody
public String login(HttpServletRequest request, String randomCode) {
LogUtil.MSG.info("【用户输入验证码】 randomCode:【{}】", randomCode);
Map<String, String> map = new HashMap<String, String>();
try {
String sessionId = request.getSession().getId();
LogUtil.MSG.debug("sessionId:{}", sessionId);
//String verifyCode = (String) request.getSession().getAttribute(Constants.SESSION_RANDOMCODE);
String verifyCode = redisUtil.getKeyValue(Constants.REDIS_INVESTOR_CODE_PREFIX + sessionId);
Boolean isResponseCorrect = checkVerifyCode(randomCode, verifyCode);
if (isResponseCorrect) {
request.getSession().removeAttribute(Constants.SESSION_RANDOMCODE);


request.getSession().setAttribute(Constants.LOGIN_USER_INFO, lu);
request.getSession().setAttribute(Constants.LOGIN_USER_NAME, userName);
request.getSession().setAttribute(Constants.OPERATE_DATE, String.valueOf(new Date().getTime()));
        request.getSession().setAttribute(Constants.LOGIN_USER_ID, String.valueOf(lu.getOperatorId()));

//登录成功将用户对象存入redis;
//String redisKey = userName;
String jsessionid = sessionId;
redisUtil.setValAndExpire(Constants.REDIS_LOGIN_PREFIX + userName, Constants.REDIS_TIMEOUT, jsessionid);
// 登录信息放入redis
redisUtil.setExObject(Constants.SESSION_AUTH + jsessionid, Constants.REDIS_TIMEOUT, JSONObject.toJSONString(lu));




第六步退出登录接口处理 logout;
@RequestMapping(value = "/logout.action")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
//退出登录从redis中删除;
String jsessionid = session.getId();
// 读取缓存redis登陆态信息
redisUtil.del(Constants.SESSION_AUTH + jsessionid);
String userName = (String) session.getAttribute("userName");
if (userName != null) {
session.removeAttribute("userName");
}
String redirectUrl = "/";
String profile = env.getProperty("spring.cloud.config.profile");
if(!"dev".equals(profile)) {
String contenxtPath = request.getContextPath();
contenxtPath = "/".equals(contenxtPath) || "".equals(contenxtPath) ? contenxtPath + "/" + EnvProperties.getDomain() : contenxtPath;
redirectUrl = contenxtPath;
}
return "redirect:" + redirectUrl;
}


相关标签: redis