欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

1.安裝redis,并配置密碼

這里就不針對于redis的安裝約配置進行說明了,直接在項目中使用。

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.在項目的配置文件中加入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的配置文件放在項目的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.具體實現(xiàn)思路(手動實現(xiàn))

實現(xiàn)思路

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

下面是思路流程圖

代碼實現(xiàn)

創(chuàng)建過濾器 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í)行過濾器鏈
                        chain.doFilter(request, response);
 
                        // 更新 Session 到 Redis
                        if (wrappedSession.isDirty()) {
                            jedis.set(sessionId, objectMapper.writeValueAsString(wrappedSession.getSessionData()));
                        }
                    } else {
                        // 登錄過期
                        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 方法 ...
}

注冊過濾器

在 Spring 配置中注冊過濾器:

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

創(chuàng)建 HttpSessionWrapper 類

將session和sessionid封裝到這個類里面

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;
    }
 
    // ... 實現(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)建新的會話
        String sessionId = UUID.randomUUID().toString();
        Map<String, Object> sessionAttributes = new HashMap<>();
        // 填充會話屬性
        sessionAttributes.put("user", user);
 
        // 使用 JsonUtil 序列化會話并存儲到 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 不會被 JavaScript 訪問
        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{
        //對象的所有字段全部列入
        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串,看起來比較好看,但是有換行符等符號,會比沒有格式化的大
     * @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框架實現(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)建一個配置類 SessionConfig,使用 @EnableRedisHttpSession 注解來啟用 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 {
 
    // 配置會話過期時間(例如,設(shè)置為 1800 秒,即 30 分鐘)
    @Bean
    public RedisHttpSessionConfiguration redisHttpSessionConfiguration() {
        RedisHttpSessionConfiguration configuration = new RedisHttpSessionConfiguration();
        configuration.setMaxInactiveIntervalInSeconds(1800);
        return configuration;
    }
 
    // 如果你使用的是 Spring Boot 2.3 或更高版本,你可能需要定義這個 Bean 來避免警告
    @Bean
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }
}

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

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

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

做完上面的配置之后,你可以像使用常規(guī) HttpSession 一樣使用 Spring Session。每次修改會話時,Spring Session 都會自動將這些更改同步到 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實現(xiàn)session共享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot redis session共享的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot自定義動態(tài)數(shù)據(jù)源的流程步驟

    SpringBoot自定義動態(tài)數(shù)據(jù)源的流程步驟

    動態(tài)數(shù)據(jù)源,本質(zhì)上是把多個數(shù)據(jù)源存儲在一個?Map?中,當(dāng)需要使用某一個數(shù)據(jù)源時,使用?key?獲取指定數(shù)據(jù)源進行處理,本文將給大家介紹一下SpringBoot自定義動態(tài)數(shù)據(jù)源的流程步驟,需要的朋友可以參考下
    2024-06-06
  • Java Synchronized鎖失敗案例及解決方案

    Java Synchronized鎖失敗案例及解決方案

    這篇文章主要介紹了Java Synchronized鎖失敗案例及解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java異常處理實例分析

    Java異常處理實例分析

    這篇文章主要介紹了Java異常處理,實例分析了java異常處理的常見用法,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • 詳解Java 序列化與反序列化(Serialization)

    詳解Java 序列化與反序列化(Serialization)

    這篇文章主要介紹了Java 序列化與反序列化(Serialization),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí) 吧
    2019-03-03
  • Java并發(fā)編程示例(五):線程休眠與恢復(fù)

    Java并發(fā)編程示例(五):線程休眠與恢復(fù)

    這篇文章主要介紹了Java并發(fā)編程示例(五):線程休眠與恢復(fù),在本節(jié),我們將開發(fā)一個程序,使用sleep()方法來實現(xiàn)每秒鐘打印一次當(dāng)前時間,需要的朋友可以參考下
    2014-12-12
  • drools規(guī)則動態(tài)化實踐解析

    drools規(guī)則動態(tài)化實踐解析

    這篇文章主要為大家介紹了drools規(guī)則動態(tài)化實踐解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • java實現(xiàn)貪吃蛇極速版

    java實現(xiàn)貪吃蛇極速版

    這篇文章主要為大家分享了java貪吃蛇極速版,貪吃蛇經(jīng)典手機游戲,既簡單又耐玩,本文用java來實現(xiàn)下貪吃蛇小游戲,感興趣的小伙伴可以參考下
    2015-12-12
  • springboot 如何解決static調(diào)用service為null

    springboot 如何解決static調(diào)用service為null

    這篇文章主要介紹了springboot 如何解決static調(diào)用service為null的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring實戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作示例

    Spring實戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作示例

    這篇文章主要介紹了Spring實戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作,結(jié)合實例形式分析了Spring協(xié)調(diào)作用域不同步的Bean相關(guān)配置及使用技巧,需要的朋友可以參考下
    2019-11-11
  • Springcloud eureka搭建高可用集群過程圖解

    Springcloud eureka搭建高可用集群過程圖解

    這篇文章主要介紹了Springcloud eureka搭建高可用集群過程圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04

最新評論