最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot使用redis實(shí)現(xiàn)session共享功能

 更新時(shí)間:2024年05月10日 09:51:02   作者:編程小猹  
這篇文章主要介紹了pringboot項(xiàng)目使用redis實(shí)現(xiàn)session共享,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

1.安裝redis,并配置密碼

這里就不針對(duì)于redis的安裝約配置進(jìn)行說(shuō)明了,直接在項(xiàng)目中使用。

redis在windows環(huán)境下安裝:Window下Redis的安裝和部署詳細(xì)圖文教程_Redis_腳本之家 (jb51.net)

2.pom.xml文件中引入需要的maven

     <dependency>
		<groupId>redis.clients</groupId>
		<artifactId>jedis</artifactId>
		<version>2.9.0</version>
	</dependency>

3.在項(xiàng)目的配置文件中加入redis的配置

redis:
  database: 0
  host: localhost
  password: 123456
  pool:
    max-active: 8
    max-idle: 8
    max-wait: -1
    min-idle: 0
  port: 6379
  timeout: 3000

4.添加redis的配置文件放在項(xiàng)目的config文件夾下

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
/**
 * @author kjz
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
 
	@Value("${redis.host}")
	private String host;
 
	@Value("${redis.port}")
	private int port;
 
	@Value("${redis.timeout}")
	private int timeout;
 
	@Value("${redis.pool.max-idle}")
	private int maxIdle;
 
	@Value("${redis.pool.max-wait}")
	private long maxWaitMillis;
 
	@Value("${redis.password}")
	private String password;
 
	@Bean
	public JedisPool redisPoolFactory() {
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxIdle(maxIdle);
		jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
 
		JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout);
		return jedisPool;
	}
 
	@Bean
	public RedisConnectionFactory redisConnectionFactory() {
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxIdle(maxIdle);
		jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
		JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig);
		jedisConnectionFactory.setHostName(host);
		jedisConnectionFactory.setPort(port);
		jedisConnectionFactory.setTimeout(timeout);
		jedisConnectionFactory.setPassword(password);
		return jedisConnectionFactory;
	}
 
}

5.具體實(shí)現(xiàn)思路(手動(dòng)實(shí)現(xiàn))

實(shí)現(xiàn)思路

創(chuàng)建一個(gè)過(guò)濾器,攔截除了登錄之外的所有請(qǐng)求,判斷請(qǐng)求中是否存在cookie,如果存在cookie則判斷redis中是否存在以cookie為key的鍵值對(duì)數(shù)據(jù),如果有則取出對(duì)應(yīng)的value同時(shí)對(duì)這個(gè)key的過(guò)期時(shí)間進(jìn)行續(xù)期,如果沒(méi)有則返回一個(gè)響應(yīng),說(shuō)明登錄已經(jīng)過(guò)期了,將Value就是session進(jìn)行Jason反序列化得到session對(duì)象,然后把Session綁定到當(dāng)前的請(qǐng)求中,如果不存在cookie,則直接返回一個(gè)響應(yīng),說(shuō)明還未登錄。如果是登錄請(qǐng)求的話,直接到controller中進(jìn)行登錄校驗(yàn),讓深沉的session通過(guò)json序列化放到redis中,并且以u(píng)uid為key,同時(shí),返回給前端一個(gè)cookie字段,cookie字段的值就是uuid,請(qǐng)求完成之后,在過(guò)濾器中將會(huì)話數(shù)據(jù)session更新到redis中。

下面是思路流程圖

代碼實(shí)現(xiàn)

創(chuàng)建過(guò)濾器 SessionFilter

import com.fasterxml.jackson.databind.ObjectMapper;
import redis.clients.jedis.Jedis;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
public class SessionFilter implements Filter {
 
    private JedisPool jedisPool;
    private ObjectMapper objectMapper;
    private static final String LOGIN_PATH = "/login";
    private static final int SESSION_EXPIRATION_TIME = 30 * 60; // 30 minutes in seconds
 
    public SessionFilter(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
        this.objectMapper = new ObjectMapper();
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
 
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
 
        String requestUri = httpRequest.getRequestURI();
 
        if (requestUri.equals(LOGIN_PATH)) {
            // 直接轉(zhuǎn)發(fā)到登錄控制器
            chain.doFilter(request, response);
        } else {
            // 檢查 Cookie
            Cookie[] cookies = httpRequest.getCookies();
            String sessionId = null;
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if ("SESSIONID".equals(cookie.getName())) {
                        sessionId = cookie.getValue();
                        break;
                    }
                }
            }
 
            if (sessionId != null) {
                try (Jedis jedis = jedisPool.getResource()) {
                    String sessionDataJson = jedis.get(sessionId);
                    if (sessionDataJson != null) {
                        // 續(xù)期
                        jedis.expire(sessionId, SESSION_EXPIRATION_TIME);
 
                        // 反序列化 Session
                        Map<String, Object> sessionAttributes = objectMapper.readValue(sessionDataJson, Map.class);
                        HttpSessionWrapper wrappedSession = new HttpSessionWrapper(sessionAttributes);
                        request.setAttribute("httpSession", wrappedSession);
 
                        // 繼續(xù)執(zhí)行過(guò)濾器鏈
                        chain.doFilter(request, response);
 
                        // 更新 Session 到 Redis
                        if (wrappedSession.isDirty()) {
                            jedis.set(sessionId, objectMapper.writeValueAsString(wrappedSession.getSessionData()));
                        }
                    } else {
                        // 登錄過(guò)期
                        httpResponse.setContentType("application/json");
                        httpResponse.getWriter().write("{\"error\": \"Session expired\"}");
                    }
                } catch (Exception e) {
                    // 處理異常
                    e.printStackTrace();
                    httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                }
            } else {
                // 未登錄
                httpResponse.setContentType("application/json");
                httpResponse.getWriter().write("{\"error\": \"Not logged in\"}");
            }
        }
    }
 
    // ... 其他 Filter 方法 ...
}

注冊(cè)過(guò)濾器

在 Spring 配置中注冊(cè)過(guò)濾器:

@Bean
public FilterRegistrationBean<SessionFilter> sessionFilterRegistration(SessionFilter sessionFilter) {
    FilterRegistrationBean<SessionFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(sessionFilter);
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
}

創(chuàng)建 HttpSessionWrapper 類

將session和sessionid封裝到這個(gè)類里面

import javax.servlet.http.HttpSession;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
 
public class HttpSessionWrapper implements HttpSession {
 
    private final Map<String, Object> attributes;
    private boolean dirty;
 
    public HttpSessionWrapper(Map<String, Object> attributes) {
        this.attributes = attributes;
        this.dirty = false;
    }
 
    // ... 實(shí)現(xiàn) HttpSession 接口的方法 ...
 
    public void setAttribute(String name, Object value) {
        attributes.put(name, value);
        dirty = true;
    }
 
    public Map<String, Object> getSessionData() {
        return attributes;
    }
 
    public boolean isDirty() {
        return dirty;
    }
 
    // ... 其他方法 ...
}

登錄控制器

@RestController
public class LoginController {
 
    @PostMapping("/login")
    public HttpServletResponse login(HttpServletRequest request, HttpServletResponse response) {
        // ... 登錄邏輯 ...
 
        // 創(chuàng)建新的會(huì)話
        String sessionId = UUID.randomUUID().toString();
        Map<String, Object> sessionAttributes = new HashMap<>();
        // 填充會(huì)話屬性
        sessionAttributes.put("user", user);
 
        // 使用 JsonUtil 序列化會(huì)話并存儲(chǔ)到 Redis
        String sessionDataJson = JsonUtil.obj2String(sessionAttributes);
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.setex(sessionId, SESSION_EXPIRATION_TIME, sessionDataJson);
        } catch (Exception e) {
            // 處理異常
            e.printStackTrace();
            return "Error";
        }
 
        // 創(chuàng)建 Cookie 并設(shè)置給客戶端
        Cookie sessionCookie = new Cookie("SESSIONID", sessionId);
        sessionCookie.setPath("/");
        sessionCookie.setHttpOnly(true); // 確保 Cookie 不會(huì)被 JavaScript 訪問(wèn)
        sessionCookie.setSecure(true); // 確保 Cookie 在 HTTPS 連接中傳輸
        response.addCookie(sessionCookie);
 
        return HttpServletResponse ;
    }
}

下面是序列化工具類

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
 
 
/**
 *@author kjz
 */
@Slf4j
public class JsonUtil {
 
    private static ObjectMapper objectMapper = new ObjectMapper();
 
    static{
        //對(duì)象的所有字段全部列入
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
    }
 
    public static <T> String obj2String(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj :  objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("Parse Object to String error",e);
            return null;
        }
    }
 
    /**
     * 格式化json串,看起來(lái)比較好看,但是有換行符等符號(hào),會(huì)比沒(méi)有格式化的大
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2StringPretty(T obj){
        if(obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj :  objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("Parse Object to String error",e);
            return null;
        }
    }
 
 
    public static <T> T string2Obj(String str,Class<T> clazz){
        if(StringUtils.isEmpty(str) || clazz == null){
            return null;
        }
 
        try {
            return clazz.equals(String.class)? (T)str : objectMapper.readValue(str,clazz);
        } catch (Exception e) {
            log.warn("Parse String to Object error",e);
            return null;
        }
    }
 
 
    public static <T> T string2Obj(String str, TypeReference<T> typeReference){
        if(StringUtils.isEmpty(str) || typeReference == null){
            return null;
        }
        try {
            return (T)(typeReference.getType().equals(String.class)? str : objectMapper.readValue(str,typeReference));
        } catch (Exception e) {
            log.warn("Parse String to Object error",e);
            return null;
        }
    }
 
    /**
     * 轉(zhuǎn)換集合
     * List<User></>
     * @param str
     * @param collectionClass
     * @param elementClasses
     * @param <T>
     * @return
     */
    public static <T> T string2Obj(String str,Class<?> collectionClass,Class<?>... elementClasses){
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass,elementClasses);
        try {
            return objectMapper.readValue(str,javaType);
        } catch (Exception e) {
            log.warn("Parse String to Object error",e);
            return null;
        }
    }
}

6.利用Spring Session Data Redis框架實(shí)現(xiàn)

引入Spring Session Data Redis 的依賴

 <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>2.7.0</version>
    </dependency>

創(chuàng)建Spring Session的配置類

創(chuàng)建一個(gè)配置類 SessionConfig,使用 @EnableRedisHttpSession 注解來(lái)啟用 Spring Session 的 Redis 支持:

import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@EnableRedisHttpSession
public class SessionConfig {
 
    // 配置會(huì)話過(guò)期時(shí)間(例如,設(shè)置為 1800 秒,即 30 分鐘)
    @Bean
    public RedisHttpSessionConfiguration redisHttpSessionConfiguration() {
        RedisHttpSessionConfiguration configuration = new RedisHttpSessionConfiguration();
        configuration.setMaxInactiveIntervalInSeconds(1800);
        return configuration;
    }
 
    // 如果你使用的是 Spring Boot 2.3 或更高版本,你可能需要定義這個(gè) Bean 來(lái)避免警告
    @Bean
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }
}

@EnableRedisHttpSession 是一個(gè)方便的注解,它做了以下幾件事情:

  1. 啟用 Spring Session 的支持,使得 HttpSession 能夠被 Spring Session 管理。
  2. 配置 Redis 作為會(huì)話數(shù)據(jù)的存儲(chǔ)后端。
  3. 注冊(cè)一個(gè) SessionRepositoryFilter 的 Bean,這個(gè) Filter 負(fù)責(zé)攔截請(qǐng)求,并將標(biāo)準(zhǔn)的 HttpSession 替換為 Spring Session 的實(shí)現(xiàn)。

Session的創(chuàng)建存儲(chǔ)和獲取

做完上面的配置之后,你可以像使用常規(guī) HttpSession 一樣使用 Spring Session。每次修改會(huì)話時(shí),Spring Session 都會(huì)自動(dòng)將這些更改同步到 Redis。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
import javax.servlet.http.HttpSession;
 
@RestController
public class SessionController {
 
    @GetMapping("/setSession")
    public String setSession(HttpSession session) {
        session.setAttribute("message", "Hello, Redis Session!");
        return "Session set in Redis";
    }
 
    @GetMapping("/getSession")
    public String getSession(HttpSession session) {
        return "Session message: " + session.getAttribute("message");
    }
}

以上就是SpringBoot使用redis實(shí)現(xiàn)session共享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot redis session共享的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java分割字符串多種方法(附例子)

    java分割字符串多種方法(附例子)

    這篇文章主要給大家介紹了關(guān)于java分割字符串多種方法的相關(guān)資料,Java中有多種方法可以實(shí)現(xiàn)字符串分割,文中將每張方法都給出了代碼示例,需要的朋友可以參考下
    2023-10-10
  • 14個(gè)編寫Spring MVC控制器的實(shí)用小技巧(吐血整理)

    14個(gè)編寫Spring MVC控制器的實(shí)用小技巧(吐血整理)

    這篇文章主要介紹了14個(gè)編寫Spring MVC控制器的實(shí)用小技巧(吐血整理),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • SpringBoot項(xiàng)目中實(shí)現(xiàn)接口冪等的五種方法

    SpringBoot項(xiàng)目中實(shí)現(xiàn)接口冪等的五種方法

    本文介紹了SpringBoot項(xiàng)目中實(shí)現(xiàn)接口冪等性的五種主要方案,Token令牌機(jī)制、數(shù)據(jù)庫(kù)唯一約束、樂(lè)觀鎖、分布式鎖和請(qǐng)求摘要,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-10-10
  • Java后端中dto、vo、entity的區(qū)別淺析

    Java后端中dto、vo、entity的區(qū)別淺析

    這篇文章主要給大家介紹了關(guān)于Java后端中dto、vo、entity區(qū)別的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-01-01
  • MybatisPlus實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離的示例詳解

    MybatisPlus實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離的示例詳解

    Mybatis Plus對(duì)Mybatis做了無(wú)侵入的增強(qiáng),非常的好用,今天就給大家介紹它的其中一個(gè)實(shí)用功能:數(shù)據(jù)權(quán)限插件,感興趣的可以跟隨小編一起了解下
    2024-04-04
  • Java數(shù)組與字符串深入探索使用方法

    Java數(shù)組與字符串深入探索使用方法

    在今天的文章中,我將為你詳細(xì)講述Java學(xué)習(xí)中重要的一節(jié) [ 數(shù)組與字符串 ] ,帶你深入了解Java語(yǔ)言中數(shù)組的聲明、創(chuàng)建和初始化方法,字符串的定義以及常用到的操作方法
    2022-07-07
  • Java中的LinkedHashSet集合解讀

    Java中的LinkedHashSet集合解讀

    這篇文章主要介紹了Java中的LinkedHashSet集合解讀,LInkedHashSet這個(gè)容器不知道大家在平時(shí)的工作用的多嗎,反正我基本上沒(méi)有用過(guò),所以,本文主要對(duì)于它的特點(diǎn)、使用場(chǎng)景、實(shí)現(xiàn)原理,做一個(gè)講解,希望對(duì)大家平時(shí)的工作有所幫助,需要的朋友可以參考下
    2023-09-09
  • Java Swagger使用教程

    Java Swagger使用教程

    Swagger是一個(gè)規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 Restful 風(fēng)格的 Web 服務(wù)。總體目標(biāo)是使客戶端和文件系統(tǒng)作為服務(wù)器以同樣的速度來(lái)更新。文件的方法、參數(shù)和模型緊密集成到服務(wù)器端的代碼,允許API來(lái)始終保持同步
    2022-07-07
  • springboot項(xiàng)目Redis統(tǒng)計(jì)在線用戶的實(shí)現(xiàn)示例

    springboot項(xiàng)目Redis統(tǒng)計(jì)在線用戶的實(shí)現(xiàn)示例

    最近做個(gè)項(xiàng)目需要統(tǒng)計(jì)在線用戶,本文主要介紹了springboot項(xiàng)目Redis統(tǒng)計(jì)在線用戶的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • 使用Spring Security和JWT實(shí)現(xiàn)安全認(rèn)證機(jī)制

    使用Spring Security和JWT實(shí)現(xiàn)安全認(rèn)證機(jī)制

    在現(xiàn)代 Web 應(yīng)用中,安全認(rèn)證和授權(quán)是保障數(shù)據(jù)安全和用戶隱私的核心機(jī)制,Spring Security 是 Spring 框架下專為安全設(shè)計(jì)的模塊,具有高度的可配置性和擴(kuò)展性,而 JWT則是當(dāng)前流行的認(rèn)證解決方案,所以本文介紹了如何使用Spring Security和JWT實(shí)現(xiàn)安全認(rèn)證機(jī)制
    2024-11-11

最新評(píng)論

台中市| 兴和县| 天水市| 武汉市| 灌云县| 通化县| 藁城市| 开平市| 灯塔市| 张家界市| 同德县| 延寿县| 仪征市| 隆安县| 祥云县| 犍为县| 西畴县| 清涧县| 屯门区| 韩城市| 保定市| 平顺县| 内丘县| 阿拉尔市| 临潭县| 巴林右旗| 固安县| 锦屏县| 九龙县| 石狮市| 会宁县| 乡城县| 东阳市| 林周县| 安义县| 高碑店市| 罗甸县| 保德县| 南溪县| 丰镇市| 苍溪县|