SpringBoot 自定义session并保存到Redis

文章目录

  • 1 实现ExpiringSession接口
  • 2 实现SessionRepository接口
  • 3 配置SpringHttpSessionConfiguration
  • 4 配置application.properties

1 实现ExpiringSession接口

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.session.ExpiringSession;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author yyb
 * @since 2018-12-20
 */
public final class DiySession implements ExpiringSession, Serializable {

    private final Logger logger = LoggerFactory.getLogger(DiySession.class);

    /**
     * session id
     */
    private String id;

    /**
     * 创建时间
     */
    private long creationTime;

    /**
     * 属性
     */
    private Map<String, Object> attributes;

    /**
     * 上一次操作时间
     */
    private long lastAccessedTime;

    /**
     * 过期时间
     */
    private int maxInactiveInterval;

    public DiySession() {
        // 这里可以改成自己sessionId的生成规则
        this("DIY-" + System.currentTimeMillis() + "-"
                + UUID.randomUUID().toString().substring(0, 8));
    }

    public DiySession(String id) {
        this.id = id;
        this.attributes = new HashMap<>();
        this.creationTime = System.currentTimeMillis();
        this.lastAccessedTime = this.creationTime;
        this.maxInactiveInterval = 1800;
    }

    public DiySession(ExpiringSession session) {
        if (session == null) {
            throw new IllegalArgumentException("session cannot be null");
        }

        this.id = session.getId();
        this.attributes = new HashMap<>();

        session.getAttributeNames().forEach(k -> {
            this.attributes.put(k, session.getAttribute(k));
        });

        this.lastAccessedTime = session.getLastAccessedTime();
        this.creationTime = session.getCreationTime();
        this.maxInactiveInterval = session.getMaxInactiveIntervalInSeconds();
    }

    @Override
    public String getId() {
        return this.id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public long getCreationTime() {
        return this.creationTime;
    }

    public void setCreationTime(long creationTime) {
        this.creationTime = creationTime;
    }

    public Map<String, Object> getAttributes() {
        return attributes;
    }

    public void setAttributes(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    public int getMaxInactiveInterval() {
        return maxInactiveInterval;
    }

    public void setMaxInactiveInterval(int maxInactiveInterval) {
        this.maxInactiveInterval = maxInactiveInterval;
    }

    @Override
    public void setLastAccessedTime(long lastAccessedTime) {
        this.lastAccessedTime = lastAccessedTime;
    }

    @Override
    public long getLastAccessedTime() {
        return this.lastAccessedTime;
    }

    @JSONField(serialize = false, deserialize = false)
    @Override
    public void setMaxInactiveIntervalInSeconds(int interval) {
        this.maxInactiveInterval = interval;
    }

    @JSONField(serialize = false, deserialize = false)
    @Override
    public int getMaxInactiveIntervalInSeconds() {
        return this.maxInactiveInterval;
    }

    @JSONField(serialize = false, deserialize = false)
    @Override
    public boolean isExpired() {
        return isExpired(System.currentTimeMillis());
    }

    @JSONField(serialize = false, deserialize = false)
    @Override
    public <T> T getAttribute(String attributeName) {
        return (T) this.attributes.get(attributeName);
    }

    @JSONField(serialize = false, deserialize = false)
    @Override
    public Set<String> getAttributeNames() {
        return this.attributes.keySet();
    }

    @Override
    public void setAttribute(String attributeName, Object attributeValue) {
        if (attributeValue == null) {
            removeAttribute(attributeName);
        } else {
            this.attributes.put(attributeName, attributeValue);
        }
    }

    @Override
    public void removeAttribute(String attributeName) {
        this.attributes.remove(attributeName);
    }

    private boolean isExpired(long now) {
        if (this.maxInactiveInterval < 0) {
            return false;
        }
        return now - TimeUnit.SECONDS.toMillis(this.maxInactiveInterval) >= this.lastAccessedTime;
    }
}

2 实现SessionRepository接口

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.session.SessionProperties;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.SessionRepository;

import java.util.concurrent.TimeUnit;

/**
 * @author yyb
 * @since 2018-12-20
 */
public class DiySessionRepository implements SessionRepository<DiySession> {

    private final Logger logger = LoggerFactory.getLogger(DiySessionRepository.class);

    private SessionProperties sessionProperties;

    private RedisTemplate<String, String> redisTemplate;

    public DiySessionRepository(RedisTemplate<String, String> redisTemplate,
                                SessionProperties sessionProperties) {
        this.redisTemplate = redisTemplate;
        this.sessionProperties = sessionProperties;
    }

    @Override
    public DiySession createSession() {
        DiySession tokenSession = new DiySession();
        tokenSession.setMaxInactiveIntervalInSeconds(sessionProperties.getTimeout());
        if (logger.isDebugEnabled()) {
            logger.debug("create session: value = " + JSON.toJSONString(tokenSession));
        }
        return tokenSession;
    }

    @Override
    public void save(DiySession session) {
        if (session == null) {
            return;
        }
        String json = JSON.toJSONString(session);
        if (logger.isDebugEnabled()) {
            logger.debug("save session: value = " + json);
        }
        
        redisTemplate.boundValueOps(session.getId())
                .set(json, sessionProperties.getTimeout(), TimeUnit.SECONDS);
    }

    @Override
    public DiySession getSession(String id) {
        BoundValueOperations boundValueOps = redisTemplate.boundValueOps(id);
        Object s = boundValueOps.get();
        if (s == null) {
            return null;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("find session: value = " + s.toString());
        }

        try {
            DiySession session = JSON.parseObject(s.toString(), DiySession.class);
            if (session == null) {
                return null;
            }

            if (session.isExpired()) {
                return null;
            }

            session.setLastAccessedTime(System.currentTimeMillis());
            return session;
        } catch (Exception e) {
            logger.error("获取session异常", e);
        }
        return null;
    }

    @Override
    public void delete(String id) {
        DiySession session = getSession(id);
        if (session == null) {
            return;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("delete session : id = " + id);
        }
        redisTemplate.delete(id);
    }
}

3 配置SpringHttpSessionConfiguration

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.session.SessionProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;

/**
 * @author yyb
 * @since 2018-12-20
 */
@Order(1)
@Configuration
@EnableScheduling
@EnableConfigurationProperties({SessionProperties.class})
public class HttpSessionConfiguration extends SpringHttpSessionConfiguration {

    @Autowired
    private SessionProperties sessionProperties;

    @Bean
    public DiySessionRepository sessionRepository(
            @Autowired RedisTemplate<String, String> redisTemplate) {
        return new DiySessionRepository(redisTemplate, sessionProperties);
    }

}

4 配置application.properties

server.session.timeout=3600
spring.session.store-type=redis
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=

你可能感兴趣的:(Java)