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

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 類(lèi)

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

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 ;
    }
}

下面是序列化工具類(lèi)

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 的依賴(lài)

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

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

創(chuàng)建一個(gè)配置類(lèi) 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)文章

  • 詳解IntelliJ IDEA 自定義方法注解模板

    詳解IntelliJ IDEA 自定義方法注解模板

    本篇文章主要介紹了IntelliJ IDEA 自定義方法注解模板,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java Map.entry案例詳解

    Java Map.entry案例詳解

    這篇文章主要介紹了Java Map.entry案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • SpringBoot根據(jù)注解動(dòng)態(tài)執(zhí)行類(lèi)中的方法實(shí)現(xiàn)

    SpringBoot根據(jù)注解動(dòng)態(tài)執(zhí)行類(lèi)中的方法實(shí)現(xiàn)

    本文主要介紹了SpringBoot根據(jù)注解動(dòng)態(tài)執(zhí)行類(lèi)中的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • 如何為Spark Application指定不同的JDK版本詳解

    如何為Spark Application指定不同的JDK版本詳解

    這篇文章主要給大家介紹了關(guān)于如何為Spark Application指定不同的JDK版本的相關(guān)資料,文中通過(guò)示例代碼將解決的方法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面來(lái)隨著小編一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • 使用@Value注入map、List,yaml格式方式

    使用@Value注入map、List,yaml格式方式

    這篇文章主要介紹了使用@Value注入map、List,yaml格式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之在線蛋糕銷(xiāo)售商城的實(shí)現(xiàn)

    Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之在線蛋糕銷(xiāo)售商城的實(shí)現(xiàn)

    這是一個(gè)使用了java+JSP+Springboot+maven+mysql+ThymeLeaf+FTP開(kāi)發(fā)的在線蛋糕銷(xiāo)售商城,是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有線上蛋糕商城該有的所有功能,感興趣的朋友快來(lái)看看吧
    2022-01-01
  • Java編程中的equals方法使用全解

    Java編程中的equals方法使用全解

    這篇文章主要介紹了Java編程中的equals方法使用全解,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • Java面試題之HashMap 的 hash 方法原理是什么

    Java面試題之HashMap 的 hash 方法原理是什么

    那天,小二去蔚來(lái)面試,面試官老王一上來(lái)就問(wèn)他:HashMap 的 hash 方法的原理是什么?當(dāng)時(shí)就把裸面的小二給蚌埠住了,這篇文章將詳細(xì)解答該題目
    2021-11-11
  • spring boot加載freemarker模板路徑的方法

    spring boot加載freemarker模板路徑的方法

    這篇文章主要介紹了spring boot加載freemarker模板路徑的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Java大文件分片上傳超詳細(xì)教程(minio版)

    Java大文件分片上傳超詳細(xì)教程(minio版)

    Minio是一個(gè)開(kāi)源的分布式對(duì)象存儲(chǔ)系統(tǒng),它允許用戶在存儲(chǔ)服務(wù)上存儲(chǔ)和檢索數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java大文件分片上傳(minio版)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08

最新評(píng)論