Maison  >  Article  >  base de données  >  Explication détaillée de la mise en œuvre Redis du partage de session

Explication détaillée de la mise en œuvre Redis du partage de session

coldplay.xixi
coldplay.xixiavant
2020-07-30 11:34:573599parcourir

Explication détaillée de la mise en œuvre Redis du partage de session

Redis implémente le partage de session

Ces derniers jours, j'ai travaillé sur un tel petit module de partage de session. Après avoir vérifié beaucoup d'informations, j'ai l'impression que c'est trop déroutant et je n'ai jamais réussi à trouver ce que je voulais. Presque toutes les méthodes de mise en œuvre sont différentes de mes idées. Ici, je vais résumer comment je le fais. utilisez Redis pour mettre en œuvre des sessions partagées afin de faciliter les demandes futures, j'espère également que cela pourra aider les amis qui ont des besoins à cet égard.

Recommandations de sujets connexes : session php (y compris des photos, des vidéos, des cas)

Parlons d'abord Jetons un coup d'œil à mon environnement de développement : nginx, redis, tomcat, utilisez moven pour construire le projet et exécutez le serveur jetty. Donc, ici, je vais également expliquer comment utiliser maven pour créer un package war et le déployer pour l'exécuter. matou.

Redis est une base de données clé-valeur Le stockage et la récupération des valeurs dépendent tous de cette clé, je vais dire quelque chose de long ici car c'est original. et professionnel, je ne le collerai pas. Je veux en savoir plus. Vous pouvez rechercher l'introduction officielle

Configuration dans pom.xml :

<!-- redis -->  
<dependency>  
<groupId>redis.clients</groupId>  
<artifactId>jedis</artifactId>  
<version>2.8.1</version>  
</dependency>  
<dependency>  
<groupId>org.springframework.data</groupId>  
<artifactId>spring-data-redis</artifactId>  
<version>1.7.2.RELEASE</version>  
</dependency>

Configurer

<!-- redis 客户端配置 -->  
   <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">  
       <property name="maxTotal" value="${jedisPoolConfig.maxTotal}"/>  
       <property name="maxIdle" value="${jedisPoolConfig.maxIdle}"/>  
       <property name="maxWaitMillis" value="${jedisPoolConfig.maxWaitMillis}"/>  
       <property name="testWhileIdle" value="true"/>  
       <property name="testOnBorrow" value="false"/>  
       <property name="testOnReturn" value="false"/>  
   </bean>  
   <bean id="readJedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">  
       <property name="hostName" value="${jedis.read.host}" />  
       <property name="port" value="${jedis.read.port}" />  
       <property name="password" value="${jedis.read.password}" />  
       <property name="timeout" value="${jedis.read.timeout}" />  
       <property name="database" value="${jedis.read.database}" />  
       <property name="poolConfig" ref="jedisPoolConfig" />  
   </bean>  
   <bean id="writeJedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">  
       <property name="hostName" value="${jedis.write.host}" />  
       <property name="port" value="${jedis.write.port}" />  
       <property name="password" value="${jedis.write.password}" />  
       <property name="timeout" value="${jedis.write.timeout}" />  
       <property name="database" value="${jedis.write.database}" />  
       <property name="poolConfig" ref="jedisPoolConfig" />  
   </bean>  
   <bean id="readRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">  
       <property name="connectionFactory" ref="readJedisConnectionFactory" />  
   </bean>  
   <bean id="writeRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">  
       <property name="connectionFactory" ref="writeJedisConnectionFactory" />  
   </bean>

dans applicationContext-redis.xml. est terminé, démarrez l'implémentation du code :

Dans LoginController :

La première étape, introduisez RedisTemplate

@Autowired  
@Qualifier("writeRedisTemplate")  
private StringRedisTemplate writeTemplate;

Il vous suffit d'introduire writeRedisTemplate ici lors de la connexion, il n'est responsable de l'écriture que lors de l'actualisation. , après avoir passé le filtre, devez-vous lire

La deuxième étape est le processus de connexion normal. Après une connexion réussie, la demande. doit également enregistrer les informations de la session

La troisième étape, définissez la valeur du cookie, stockez la valeur clé dans redis comme valeur clé pour enregistrer les informations de session utilisateur dans le cookie, et lors de l'actualisation du navigateur, le filtre Vous pouvez obtenir la valeur du cookie, puis accéder à redis pour obtenir la valeur correspondante, c'est-à-dire keyuserSession

String domain = request.getServerName();  
       String cookieId=MD5Util.MD5Encode("uasLoginer", "UTF-8");  
       //生成token,用作session在redis存储中的key值      
       StringredisSessionKey= UUID.randomUUID().toString();  
       Cookie uasLoginer = new Cookie(cookieId, redisSessionKey);  
       if (domain.startsWith("uas.")) {  
    uasLoginer.setDomain(domain.substring(4,domain.length()));  
}else {  
    uasLoginer.setDomain(domain);  
}  
       uasLoginer.setMaxAge(60000);  
       uasLoginer.setPath("/");  
       response.addCookie(uasLoginer);

Ici, le cookie est défini sur le domaine setDomain et setPath

Le quatrième étape, enregistrez les informations dans redis userSession

Écrivez redis dans RedisTemplate La valeur doit être de type String et l'objet userSession doit être converti en chaîne Json

userSessionString = JSON.toJSONString(userSession);

在转Json的时候,遇到问题,导入import com.alibaba.fastjson.JSON;一直失败,发现pom中没有依赖Json的关系,如果有遇到相同的问题,可以检查下在pom.xml中是否有关于json的依赖关系,没的话,在pom.xml中导入json的依赖关系,如下:

<dependency>  
    <groupId>net.sf.json-lib</groupId>  
    <artifactId>json-lib</artifactId>  
    <version>2.3</version>  
    <classifier>jdk15</classifier>  
</dependency>

写入redis的代码如下:

writeTemplate.opsForHash().put(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey,redisSessionKey, userSessionString);  
writeTemplate.expire(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey, 1800L, TimeUnit.SECONDS);//设置redis中值的有效期

完成这一操作,用户的session信息已经存入到redis中,可在redis中查看是否存入。

第五步:进入页面后,刷新页面,请求会经过过滤器,在Filter.Java中读取redis的值并进行一些处理

在过滤器这里,就无法通过注解的方式引入redisTemplate,可以通过如下的方式引入:

BeanFactory beans = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());  
     StringRedisTemplate readTemplate = (StringRedisTemplate) beans.getBean("readRedisTemplate");  
     StringRedisTemplate writeTemplate = (StringRedisTemplate) beans.getBean("writeRedisTemplate");

过滤器从cookie中取出redis的key值,用readTemplate读出value值

String cookid=MD5Util.MD5Encode("uasLoginer", "UTF-8");  
Cookie[] cookies = req.getCookies();  
String redisSessionKey = "";  
if(cookies != null){  
    for (Cookie cookie : cookies) {  
        if(cookie.getName().equals(cookid)){  
            redisSessionKey = cookie.getValue() ;  
        }  
    }  
}  
UserSession userSession = null;  
String userSessionString = (String) readTemplate.boundHashOps(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey).get(redisSessionKey);  
if(null != userSessionString ){  
    @SuppressWarnings("static-access")  
    JSONObject obj = new JSONObject().fromObject(userSessionString);//将json字符串转换为json对象  
    userSession = (UserSession)JSONObject.toBean(obj,UserSession.class);  
    writeTemplate.expire(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey, 1800L, TimeUnit.SECONDS);  
    request.getSession().setAttribute(UasContants.USER_SESSION, userSession);  
}  
if (userSession != null) {  
    chain.doFilter(req, res);  
    return;  
}else {  
    res.sendRedirect(UasContants.LOGIN_URL);  
    return;  
}

在这里,另外附上关于web.xml关于LoginFilter的配置,有需要的可以参考下:

3e7cd2763b3efa047912466801e5e412  
eae7f28921fa176b20e23abb843be090  
    5948543310f2c9ae6eabc90d07fdac18org.springframework.web.context.ContextLoaderListenera5cb73ed00d90e1dafbf6168c4a676c2  
f26bc28f07f75d604e1d9c5e7de10123  
1d24e586ca31f4bd05eca427459d98c7  
    f573a9ccb524cb86b6b9919be70810beloginFilterb4d5e6fde2c78ede331e20c60d37da11  
    e5b954f5d6752e2b67f5dbec1cf5c85ecom.sfbest.uas.filter.LoginFilter3c5315e9114c0f42d7a83b06562caa88  
    380fae52cc7d04565d26dd4bbf4b5460  
        c13d9669d2c8f87a36a39c8f95f41552excludePaths02b9ad8b27bc78bd91c18db845cdde4a  
        f226acac8cb0e4a9d59fcba58b57a899/login,/user/login,/user/auth22c8aeb51b7638a9da01bd5a66154ac1  
    8f161518881ffd7712eaaadc573a3556  
94e66dfbd9fa8f117002935bdd35d0b3  
dd0dfb26ea66647667f179a739921d33  
    f573a9ccb524cb86b6b9919be70810beloginFilterb4d5e6fde2c78ede331e20c60d37da11  
    66e1775cbd9d5002635ae3285442ba88/*3ec4a5583206d351b61ed79c1a0f9c66  
e354d6d34e50ca0d695db95544b3672a

按照上面的配置,就可以用redis实现session共享的功能,但我在开发的时候,遇到一个蛋疼的问题,在测试环境上,

把项目部署在两台tomcat服务器上的时候,cookie里一直存不进去redis的key值,单台可以存进去,经过长期的检测,

终于发现是nginx配置出的问题,引以为戒,深深的阴影。下面我贴出我正常运行时nginx的配置代码

upstream uassessiontest.d.com {  
        server 10.103.16.226:8088;  
        server 10.103.16.226:8089;  
        }  
       server {  
                 log_format  sf_uastest  '$remote_addr - $remote_user [$time_local] "$request" '  
                                        '$status $body_bytes_sent "$http_referer" '  
                                        '"$http_user_agent" $http_cookie';  
                listen 80;  
                server_name uassessiontest.d.com;  
                access_log /var/log/nginx/uassessiontest.log sf_uastest; 
  
                location / {  
                        rewrite ^/$ /uas/ break;  
                        proxy_pass http://uassessiontest.d.com;  
                }  
        }

红色的为当初少配的部分,这些部分是的作用是往浏览器端写入cookie值。

相关学习推荐:redis视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer