杰瑞科技汇

Redis如何实现Java Session共享?

Of course! Using Redis to store Java web application sessions is a very common and powerful pattern, especially in distributed and microservices architectures. It's often called Session Clustering or Session Replication.

Redis如何实现Java Session共享?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the why, how, and what of using Redis for Java sessions.


Why Use Redis for Sessions?

Before diving into the code, let's understand the benefits:

  1. Scalability & High Availability: In a traditional web server (like Tomcat), sessions are stored in the server's memory. If you have multiple servers behind a load balancer, a user's request might go to Server A, but their next request could go to Server B, which doesn't have their session. Redis acts as a central, shared session store, solving this "sticky session" problem. You can scale your application servers horizontally without worrying about session affinity.
  2. Performance: Redis is an in-memory data store, making it extremely fast for session read/write operations. It's significantly faster than persisting sessions to a database or the local filesystem.
  3. Resilience: If one of your application servers crashes, the user's session data is not lost because it's safely stored in Redis. The load balancer can seamlessly route the user's next request to a healthy server, which will retrieve the session from Redis.
  4. Simplicity: It's much simpler to set up and manage than complex database-based session persistence mechanisms.

Core Concepts

  • Session ID: A unique string (e.g., A9F5C8D1E3B7492A) that is sent to the client (usually in a cookie) and used by the server to look up the session data.
  • Session Data: A map of key-value pairs (e.g., userId, username, shoppingCart) associated with a session ID.
  • Session Expiration: Sessions should not live forever. Redis allows you to set a Time-To-Live (TTL) on each session key, so it automatically gets deleted after a period of inactivity.

How It Works: The Flow

  1. First Request: A user visits your application for the first time.
    • The server creates a new session.
    • It serializes the session data (the Map of attributes).
    • It stores this serialized data in Redis using a unique session ID as the key.
    • It sets an expiration time on the Redis key (e.g., 30 minutes).
    • It sends the session ID back to the client in a JSESSIONID cookie.
  2. Subsequent Requests: The user makes another request.
    • The browser automatically sends the JSESSIONID cookie.
    • The server intercepts the request, extracts the session ID, and looks up the session data in Redis.
    • It deserializes the data from Redis and loads it into the HttpSession object for the request.
    • If the user updates their session (e.g., adds an item to a cart), the server updates the in-memory HttpSession object. The library (like Spring Session) will then automatically sync these changes back to Redis.

Implementation with Spring Boot (The Easiest Way)

Spring Boot and Spring Data make this incredibly simple. The magic is powered by Spring Session.

Step 1: Add Dependencies

In your pom.xml, add the following dependencies:

Redis如何实现Java Session共享?-图2
(图片来源网络,侵删)
<!-- For Spring Session and Redis integration -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- For connecting to Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- For building a web application -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Step 2: Configure Redis

In your application.properties or application.yml file, point to your Redis instance.

application.properties

# Redis server configuration
spring.redis.host=localhost
spring.redis.port=6379
# Optional: if your Redis requires a password
# spring.redis.password=yourpassword
# Session configuration
# This is the key! It tells Spring Session to use Redis.
spring.session.store-type=redis
# How long sessions should live before expiring (in seconds)
spring.session.timeout=1800 

Step 3: Create a Configuration Class

This is the most crucial step. You need to annotate a configuration class with @EnableRedisHttpSession. This annotation does all the heavy lifting.

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession // This single annotation enables Redis-backed HTTP sessions!
public class HttpSessionConfig {
    // No other code is needed in this class.
}

That's it for the configuration! Spring Session will now automatically:

  • Create a RedisTemplate to serialize/deserialize session objects.
  • Provide a SessionRepositoryFilter that intercepts all requests.
  • Replace the default HttpSession implementation with a custom one that reads from and writes to Redis.

Step 4: Use the Session in Your Controller

Now you can inject the standard HttpSession object into your controllers, and it will automatically be backed by Redis.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpSession;
@RestController
public class SessionController {
    @GetMapping("/set")
    public String setAttribute(HttpSession session) {
        session.setAttribute("user", "John Doe");
        session.setAttribute("loginTime", System.currentTimeMillis());
        return "Attribute 'user' and 'loginTime' have been set in the session.";
    }
    @GetMapping("/get")
    public String getAttribute(HttpSession session) {
        String user = (String) session.getAttribute("user");
        Long loginTime = (Long) session.getAttribute("loginTime");
        if (user != null) {
            return "User from session: " + user + ", Login Time: " + loginTime;
        } else {
            return "No 'user' attribute found in session.";
        }
    }
    @GetMapping("/invalidate")
    public String invalidateSession(HttpSession session) {
        session.invalidate();
        return "Session has been invalidated.";
    }
}

Step 5: Verify in Redis

  1. Run your Spring Boot application.
  2. Open a browser and navigate to http://localhost:8080/set.
  3. Open the Redis CLI (redis-cli) and run the KEYS * command. You will see a key that looks something like spring:session:sessions:xxxxxxxxxxxxxxxxxxxxxx.
  4. Use the GET command to inspect the value: GET spring:session:sessions:xxxxxxxxxxxxxxxxxxxxxx. You'll see the serialized session data.
  5. You can also see the expiration time with the TTL command: TTL spring:session:sessions:xxxxxxxxxxxxxxxxxxxxxx.

Serialization (A Crucial Detail)

By default, Spring Session uses Java's JdkSerializationRedisSerializer. This works but has drawbacks:

  • Not Human-Readable: The data in Redis is binary gibberish.
  • Security Risk: It can lead to remote code execution vulnerabilities if an attacker can manipulate session data.

Recommended Alternative: JSON Serialization

It's highly recommended to use a JSON serializer like Jackson.

  1. Add Jackson Dependency (it's usually included with spring-boot-starter-web).
  2. Create a Custom Configuration:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession
public class HttpSessionConfig {
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer(ObjectMapper objectMapper) {
        // Use Jackson2JsonRedisSerializer for human-readable and secure JSON serialization
        return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
    }
    // You might also need to configure the ObjectMapper bean
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

Now, when you look at your session data in Redis, it will be clean, readable JSON.


Advanced Configuration & Libraries

  • Spring Security: If you're using Spring Security, it integrates seamlessly with Spring Session. You can store SecurityContext (which holds the authenticated Principal) in the Redis-backed session. This is a very common and powerful setup.
  • Tomcat Manager: If you're not using Spring, you can configure the standard Tomcat Manager to use Redis. Libraries like tomcat-redis-session-manager exist for this purpose. The configuration is more manual and less integrated than the Spring approach.

Summary

Feature Description
Why? Scalability, high availability, performance, and resilience for distributed apps.
How? Use a library like Spring Session to intercept HTTP requests and delegate session storage to Redis.
Implementation (Spring) Add spring-session-data-redis dependency, configure Redis properties, and add @EnableRedisHttpSession.
Key Benefit You can use the standard HttpSession API, and the library handles the Redis communication in the background.
Best Practice Use JSON serialization instead of the default Java serialization for better readability and security.
分享:
扫描分享到社交APP
上一篇
下一篇