想来也不少伙伴像我一样,一直在找完美的JFinal-undertow分布式session解决方案。之前有伙伴使用拦截器的方式曲线救国去实现分布式session,虽然确实也能实现,但个中滋味,只有自己知道。
经过一番研究,在@JFinal和@SuperEric的帮助下,完美解决了JFinal-undertow的分布式session问题。
首先,去github上下一个别人扩展好的一个RedisSessionManager,下载地址:
https://github.com/coat/undertow-redis-session
这上面下的,只需要使用到里面的RedisSessionManager这个一个类文件。其他的都可以不要。
我是用这个文件,然后自己又扩展了一些功能,这里就不再献丑了。
然后再创建一个RedisSessionManagerFactory类,代码如下:
import java.net.URI; import io.undertow.server.session.SessionCookieConfig; import io.undertow.server.session.SessionManager; import io.undertow.servlet.api.Deployment; import io.undertow.servlet.api.SessionManagerFactory; public class RedisSessionManagerFactory implements SessionManagerFactory { private URI redisUri; public RedisSessionManagerFactory(URI redisUri) { this.redisUri = redisUri; } @Override public SessionManager createSessionManager(Deployment arg0) { SessionCookieConfig sessionConfig = new SessionCookieConfig(); sessionConfig.setCookieName("session"); return new RedisSessionManager(redisUri, sessionConfig); } }
最后在MainConfig里的main方法里这么写:
public static void main(String[] args) { UndertowServer.create(MainConfig.class,"undertow.properties") .configWeb(builder -> { Prop p = PropKit.use(ConstantConfig.CONFIG_FILE).appendIfExists(ConstantConfig.CONFIG_FILE_PRO); String deployMode = p.get("deploy.mode", ConstantConfig.DEPLOY_NORMAL); String sessionStorage = p.get("deploy.session.storage", ""); boolean isDistributed = ConstantConfig.DEPLOY_DISTRIBUTED.equals(deployMode); //如果是分布式部署,并且session被配置到redis if(isDistributed && "redis".equals(sessionStorage)) { try { String redisHost = p.get("deploy.session.redis.host", "127.0.0.1"); String redisPort = p.get("deploy.session.redis.port", "6379"); String redisDb = p.get("deploy.session.redis.db", "0"); String redisUri = "redis://"+redisHost+":"+redisPort+"/"+redisDb; builder.getDeploymentInfo().setSessionManagerFactory(new RedisSessionManagerFactory(new URI(redisUri))); } catch (URISyntaxException e) { e.printStackTrace(); } } // 配置WebSocket需使用ServerEndpoint注解 builder.addWebSocketEndpoint("cn.york.common.websocket.WebSocketEndpoint"); }) .start(); }
这里只是我这里写的方法,因为我要判断是单机部署,还是分布式部署。这里仅供参考。主要是这句代码:
builder.getDeploymentInfo().setSessionManagerFactory(new RedisSessionManagerFactory(new URI(redisUri)));
先把你的redis启动起来,然后再启动你的程序,打开浏览器,看看是不是一切都清爽了。
使用这种方法,你之前的getSessionAttr,setSessionAttr等一系列操作完全不用修改。你就当是单机一样使用就行了。
再次体现了JFinal的开发初衷:极简!
builder.getDeploymentInfo().setSessionManagerFactory(...)
很有探索精神,收藏点赞,以后有用