Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: docean support redis session (#891) #892

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions jcommon/docean-plugin/docean-plugin-redisSession/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>run.mone</groupId>
<artifactId>docean-plugin</artifactId>
<version>1.6.0-jdk21-SNAPSHOT</version>
</parent>

<artifactId>docean-plugin-redisSession</artifactId>

<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>run.mone</groupId>
<artifactId>docean</artifactId>
<version>1.6.1-jdk21-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>run.mone</groupId>
<artifactId>docean-plugin-redis</artifactId>
<version>1.6.0-jdk21-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2020 Xiaomi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package run.mone.docean.plugin.redissession;

import com.xiaomi.youpin.docean.Ioc;
import com.xiaomi.youpin.docean.anno.DOceanPlugin;
import com.xiaomi.youpin.docean.plugin.IPlugin;
import com.xiaomi.youpin.docean.plugin.redis.Redis;
import lombok.extern.slf4j.Slf4j;

import java.util.Set;

/**
* @author shanwb
* @date 2024-09-03
*/
@DOceanPlugin(order = 101)
@Slf4j
public class RedisSessionPlugin implements IPlugin {


@Override
public void init(Set<? extends Class<?>> classSet, Ioc ioc) {
Redis redis = ioc.getBean(Redis.class);
if (null == redis) {
log.error("redis can not be empty");
}
RedisSessionStore redisSessionStore = new RedisSessionStore(redis);
ioc.putBean("ClusterSessionStore", redisSessionStore);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package run.mone.docean.plugin.redissession;

import com.google.gson.Gson;
import com.xiaomi.youpin.docean.mvc.session.DefaultHttpSession;
import com.xiaomi.youpin.docean.mvc.session.HttpSession;
import com.xiaomi.youpin.docean.mvc.session.ISessionStore;
import com.xiaomi.youpin.docean.plugin.redis.Redis;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
* @author shanwb
* @date 2024-09-03
*/
@Slf4j
public class RedisSessionStore implements ISessionStore {

private static final String SESSION_PREFIX = "DOCEAN_SESSION_";

private static final int SESSION_EXPIRE_SECONDS = 3600; // 默认60分钟过期

private final static Gson gson = new Gson();

private Redis redis;

public RedisSessionStore(Redis redis) {
this.redis = redis;
}

@Override
public void put(String sessionId, HttpSession session) {
try {
String key = SESSION_PREFIX + sessionId;
String value = gson.toJson(session);
redis.set(key, value, SESSION_EXPIRE_SECONDS);
} catch (Exception e) {
log.error("Error putting session to redis", e);
}
}

@Override
public void remove(String sessionId) {
try {
String key = SESSION_PREFIX + sessionId;
redis.del(key);
} catch (Exception e) {
log.error("Error removing session from redis", e);
}
}

@Override
public List<String> sessionIdList() {
return new ArrayList<>();
}

@Override
public HttpSession get(String sessionId) {
try {
String key = SESSION_PREFIX + sessionId;
String value = redis.get(key);
if (value == null) {
return null;
}
return gson.fromJson(value, DefaultHttpSession.class);
} catch (Exception e) {
log.error("Error getting session from redis", e);
return null;
}
}

@Override
public HttpSession getAndRefresh(String sessionId) {
try {
String key = SESSION_PREFIX + sessionId;
String value = redis.get(key);
if (value == null) {
return null;
}
DefaultHttpSession session = gson.fromJson(value, DefaultHttpSession.class);
redis.expire(key, SESSION_EXPIRE_SECONDS);
return session;
} catch (Exception e) {
log.error("Error getting session from redis", e);
return null;
}
}

@Override
public boolean containsKey(String sessionId) {
try {
String key = SESSION_PREFIX + sessionId;
return redis.exists(key);
} catch (Exception e) {
log.error("Error checking session existence in redis", e);
return false;
}
}
}
1 change: 1 addition & 0 deletions jcommon/docean-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<module>docean-plugin-es-antlr4</module>
<module>docean-plugin-storage</module>
<module>docean-plugin-junit</module>
<module>docean-plugin-redisSession</module>
</modules>
<dependencies>
<dependency>
Expand Down
18 changes: 17 additions & 1 deletion jcommon/docean/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,20 @@
processing, bean initialization, and loading into the container.
The plugin package has added extended support for some commonly used dependencies in projects, such as nacos, dubbo,
mybatis, and so on.
* rate limited or exceeded quota
* rate limited or exceeded quota

#Feature

## session用法
### 单机session使用
需要在ioc中加入一个bean[LocalSessionStore.java](src/main/java/com/xiaomi/youpin/docean/mvc/session/impl/LocalSessionStore.java)
ioc init时,添加扫描路径"com.xiaomi.youpin.docean.mvc.session"

### 分布式事务
1.工程中引入两个plugin:[docean-plugin-redis](../docean-plugin/docean-plugin-redis)、[docean-plugin-redisSession](../docean-plugin/docean-plugin-redisSession)
2.添加配置,开启分布式配置:ioc.putBean("$cluster-session", "true")





14 changes: 8 additions & 6 deletions jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,19 @@ private Mvc(Ioc ioc) {
}

private void setConfig(Ioc ioc) {
this.mvcConfig.setAllowCross(Boolean.valueOf(ioc.getBean(MvcConst.ALLOW_CROSS_DOMAIN, MvcConst.FALSE)));
this.mvcConfig.setDownload(Boolean.valueOf(ioc.getBean(MvcConst.MVC_DOWNLOAD, MvcConst.FALSE)));
this.mvcConfig.setUseCglib(Boolean.valueOf(ioc.getBean(MvcConst.CGLIB, MvcConst.TRUE)));
this.mvcConfig.setAllowCross(Boolean.parseBoolean(ioc.getBean(MvcConst.ALLOW_CROSS_DOMAIN, MvcConst.FALSE)));
this.mvcConfig.setDownload(Boolean.parseBoolean(ioc.getBean(MvcConst.MVC_DOWNLOAD, MvcConst.FALSE)));
this.mvcConfig.setUseCglib(Boolean.parseBoolean(ioc.getBean(MvcConst.CGLIB, MvcConst.TRUE)));

this.mvcConfig.setOpenStaticFile(Boolean.valueOf(ioc.getBean(MvcConst.OPEN_STATIC_FILE, MvcConst.FALSE)));
this.mvcConfig.setOpenStaticFile(Boolean.parseBoolean(ioc.getBean(MvcConst.OPEN_STATIC_FILE, MvcConst.FALSE)));
this.mvcConfig.setStaticFilePath(ioc.getBean(MvcConst.STATIC_FILE_PATH, MvcConst.EMPTY));

this.mvcConfig.setResponseOriginalValue(Boolean.valueOf(ioc.getBean(MvcConst.RESPONSE_ORIGINAL_VALUE, MvcConst.FALSE)));
this.mvcConfig.setResponseOriginalValue(Boolean.parseBoolean(ioc.getBean(MvcConst.RESPONSE_ORIGINAL_VALUE, MvcConst.FALSE)));
this.mvcConfig.setPoolSize(Integer.valueOf(ioc.getBean(MvcConst.MVC_POOL_SIZE, String.valueOf(MvcConst.DEFAULT_MVC_POOL_SIZE))));
this.mvcConfig.setVirtualThread(Boolean.valueOf(ioc.getBean(MvcConst.VIRTUAL_THREAD, MvcConst.TRUE)));
this.mvcConfig.setVirtualThread(Boolean.parseBoolean(ioc.getBean(MvcConst.VIRTUAL_THREAD, MvcConst.TRUE)));
this.mvcConfig.setResponseOriginalPath(ioc.getBean(MvcConst.RESPONSE_ORIGINAL_PATH, ""));
this.mvcConfig.setClusterSession(Boolean.parseBoolean(ioc.getBean(MvcConst.CLUSTER_SESSION, MvcConst.FALSE)));

ioc.publishEvent(new Event(EventType.mvcBegin, this.mvcConfig));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ public class MvcConfig implements Serializable {
*/
private String responseOriginalPath;

private boolean clusterSession;

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public class MvcContext {
*/
private boolean allowCross;

/**
* cluster session
*/
private boolean clusterSession;

public HttpSession session() {
if (null == session) {
this.session = HttpSessionManager.getSession(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public MvcRunnable(Mvc mvc, HttpServerConfig config, ChannelHandlerContext ctx,
this.context.setVirtualThread(mvc.getMvcConfig().isVirtualThread());
this.context.setPath(path);
this.context.setAllowCross(mvc.getMvcConfig().isAllowCross());
this.context.setClusterSession(mvc.getMvcConfig().isClusterSession());
this.request.setMethod(method);
this.request.setPath(path);
this.request.setBody(body);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public abstract class MvcConst {

public static final String RESPONSE_ORIGINAL_PATH = "$response-original-path";

public static final String CLUSTER_SESSION = "$cluster-session";

public static final int DEFAULT_MVC_POOL_SIZE = 200;

public static ScopedValue<MvcContext> MVC_CONTEXT = ScopedValue.newInstance();
Expand Down
Loading
Loading