对于像redis和mongodb这样的东西的许多客户,你通常必须创建一个单独的客户端引用,因为它是一个连接到redis / mongodb的连接池。
在Play应用程序中,如何创建一个静态引用,我可以在所有控制器或模型逻辑等中使用?
答案 0 :(得分:4)
就我而言,我使用的是光滑和MySQL,但我认为你想要实现的是类似的。我也不知道它是否是最好的解决方案......我正在定义与数据库连接的scala对象,而不是这个连接包含在特征中,而是在我需要数据库连接的地方扩展。 (中间当然是汇集框架)。
package models
import scala.slick.driver.MySQLDriver.simple._
import play.api.Play
import play.api.Play.current
import com.mchange.v2.c3p0._;
object Connection {
val databaseURL = Play.configuration.getString("db.default.url").get
val databaseUser = Play.configuration.getString("db.default.user").get
val databasePassword = Play.configuration.getString("db.default.password").get
val databaseDriver = Play.configuration.getString("db.default.driver").get
val singletonDatabase = {
val ds = new ComboPooledDataSource
ds.setDriverClass(Connection.databaseDriver)
ds.setJdbcUrl(Connection.databaseURL)
ds.setUser(Connection.databaseUser)
ds.setPassword(Connection.databasePassword)
ds.setMinPoolSize(0);
ds.setMaxPoolSize(1000);
ds.setCheckoutTimeout(3000);
ds.setAcquireIncrement(10);
ds.setMaxStatements(50);
ds.setIdleConnectionTestPeriod(60);
ds.setPreferredTestQuery("SELECT 1;");
ds.setTestConnectionOnCheckout(false);
Database.forDataSource(ds)
}
}
trait DatabaseConnector {
val database = Connection.singletonDatabase
}
答案 1 :(得分:2)
您可以通过将其创建为插件来创建单个对象。对于我的项目,我有类似的需要为RedisPool类构建单例。请参阅以下完整的工作代码:
package plugins.redis;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.Application;
import play.Configuration;
import play.Plugin;
import plugins.PluginUtils;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisPlugin extends Plugin {
private final Application application;
private JedisPool jedisPool;
private static final Logger LOGGER = LoggerFactory.getLogger("application");
//default constants for Redis
public static final String REDIS_DEFAULT_HOST="localhost";
public static final int REDIS_DEFAULT_PORT=6379;
public static final int REDIS_DEFAULT_TIMESOUT=2000;
public RedisPlugin(Application application){
this.application = application;
}
public static Integer getIntConfig(Configuration configuration, String configKey, Integer... defaultVal) {
String val = configuration.getString(configKey);
if (StringUtils.isBlank(val)) {
if(defaultVal != null && defaultVal.length>0){
return defaultVal[0];
}
return null;
} else {
return NumberUtils.toInt(val);
}
}
public static Long getLongConfig(Configuration configuration, String configKey, Long... defaultVal) {
String val = configuration.getString(configKey);
if (StringUtils.isBlank(val)) {
if(defaultVal != null && defaultVal.length>0){
return defaultVal[0];
}
return null;
} else {
return NumberUtils.toLong(val);
}
}
public static Boolean getBoolConfig(Configuration configuration, String configKey, Boolean... defaultVal) {
return BooleanUtils.toBooleanObject(configuration.getString(configKey));
}
@Override
public void onStart() {
Configuration configuration = application.configuration();
String host = getConfig(configuration, "redis.host", REDIS_DEFAULT_HOST);
if (StringUtils.isBlank(host)) {
LOGGER.error("Redis host is absent");
return;
}
Integer port = getIntConfig(configuration, "redis.port", REDIS_DEFAULT_PORT);
if (port == null) {
LOGGER.error("Redis port is absent");
return;
}
Integer timeout = getIntConfig(configuration, "redis.timeout", REDIS_DEFAULT_TIMESOUT);
if (timeout == null) {
LOGGER.error("Redis timeout is absent");
return;
}
String password = getConfig(configuration, "redis.password");
jedisPool = new JedisPool(getJedisConfig(), host, port, timeout, password);
super.onStart();
}
public JedisPool getJedisPool() {
return jedisPool;
}
@Override
public void onStop() {
jedisPool.destroy();
super.onStop();
}
@Override
public boolean enabled() {
return true;
}
public JedisPoolConfig getJedisConfig(){
JedisPoolConfig poolConfig = new JedisPoolConfig();
Configuration configuration = application.configuration();
Integer maxIdle = getIntConfig(configuration, "redis.pool.maxIdle");
if(maxIdle != null){
poolConfig.setMaxIdle(maxIdle);
}
Integer minIdle = getIntConfig(configuration, "redis.pool.minIdle");
if(minIdle != null){
poolConfig.setMinIdle(minIdle);
}
Integer numTestsPerEvictionRun = getIntConfig(configuration, "redis.pool.numTestsPerEvictionRun");
if(numTestsPerEvictionRun != null){
poolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
}
Boolean testOnBorrow = getBoolConfig(configuration, "redis.pool.testOnBorrow");
if(testOnBorrow != null){
poolConfig.setTestOnBorrow(testOnBorrow);
}
Boolean testOnReturn = getBoolConfig(configuration, "redis.pool.testOnReturn");
if(testOnReturn != null){
poolConfig.setTestOnReturn(testOnReturn);
}
Boolean testWhileIdle = getBoolConfig(configuration, "redis.pool.testWhileIdle");
if(testWhileIdle != null){
poolConfig.setTestWhileIdle(testWhileIdle);
}
Boolean lifo = getBoolConfig(configuration, "redis.pool.lifo");
if(lifo != null){
poolConfig.setLifo(lifo);
}
Long timeBetweenEvictionRunsMillis = getLongConfig(configuration, "redis.pool.timeBetweenEvictionRunsMillis");
if(timeBetweenEvictionRunsMillis != null){
poolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
}
Long softMinEvictableIdleTimeMillis = getLongConfig(configuration, "redis.pool.softMinEvictableIdleTimeMillis");
if(softMinEvictableIdleTimeMillis != null){
poolConfig.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
}
Boolean exhaustedAction = getBoolConfig(configuration, "redis.pool.blockWhenExhausted");
if(exhaustedAction != null){
poolConfig.setBlockWhenExhausted(exhaustedAction);
}
return poolConfig;
}
}
答案 2 :(得分:1)
您可以在Object
中创建连接池/客户端实例,并从控制器访问它。我个人讨厌这个解决方案,因为它使单元测试控制器非常复杂。
或者您可以更改实例化控制器以使用GlobalSettings
的方式:http://www.playframework.com/documentation/2.2.2/ScalaDependencyInjection
答案 3 :(得分:0)
在Play框架版本2.4.x中,现在内置了对单例和注入的支持。
https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection