在GenericObjectPool中创建对象 [英] Create objects in GenericObjectPool
问题描述
我正在研究 GenericObjectPool
,方法是将 Cipher
放入池中,以便可以重复使用。
GenericObjectPool< Cipher>池;
CipherFactory factory = new CipherFactory();
this.pool = new GenericObjectPool< Cipher>(factory);
pool.setMaxTotal(10);
pool.setBlockWhenExhausted(true);
pool.setMaxWaitMillis(30 * 1000);
CipherFactory
public class CipherFactory extends BasePooledObjectFactory< Cipher> {
private boolean running = false;
@Override
public Cipher create()throws Exception {
return Cipher.getInstance(DESede / CBC / NoPadding);
}
@Override
public PooledObject< Cipher> wrap(Cipher arg0){
return new DefaultPooledObject< Cipher>(arg0);
$ b @Override
public boolean validateObject(PooledObject< Cipher> p){
//确保池返回的实例是安全的
返回true;
$ b @Override
public void destroyObject(PooledObject< Cipher> p){
//销毁池中不再需要的实例。
System.out.println(destroying);
$ b @Override
public void activateObject(PooledObject< Cipher> p)throws Exception {//重新初始化一个要被池返回的实例
setRunning(true);
$ b @Override
public void passivateObject(PooledObject< Cipher> p)throws Exception {//在对象返回池后重置对象
setRunning(false);
}
public void setRunning(boolean running){
this.running = running;
}
//
}
这是我如何执行 $ b
public Key a(byte [] afyte)抛出异常{
密码cipher = null;
cipher = pool.borrowObject(); //从池中获取对象
尝试{
System.out.println(******************借用后***** ***********);
printPool();
cipher.init(Cipher.DECRYPT_MODE,mkkey,algParamSpec);
byte [] de = cipher.doFinal(afyte);
SecretKey mk = new SecretKeySpec(de,DESede);
返回mk;
} catch(Exception e){
pool.invalidateObject(cipher);
cipher = null;
} finally {
if(null!= cipher){
pool.returnObject(cipher);
System.out.println(******************返回****************);
printPool();
}
}
return(Key)cipher;
}
printPool $ b
public void printPool(){
System.out.println(用于DESede / CBC / NoPadding实例的密码池);
System.out.println(Active [+ pool.getNumActive()+]); //返回当前从该池中借用的实例的数量
System.out.println(Idle [+ pool.getNumIdle()+]); //此池中当前闲置的实例数
System.out.println(Total Created [+ pool.getCreatedCount()+]);
}
我在正确的道路上吗?是否有可能增加游泳池大小?
编辑
< http对我很好。但是,如果我有另一个方法
encryptECB(Key key,byte [] b)
,我应该怎么写? 任何帮助,将不胜感激 !
您正处于正确的轨道上。构建GenericObjectPool时,可以使用接受GenericObjectPoolConfig对象的构造函数,该对象包含对象池的所有配置值。下面的例子会让你的池在耗尽之前增长到20个连接...
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMinIdle(2);
config.setMaxIdle(5);
config.setMaxTotal(20);
GenericObjectPool< Cipher>池;
CipherFactory factory = new CipherFactory();
this.pool = new GenericObjectPool< Cipher>(factory,config);
GenericeObjectPoolConfig还有一个setBlockWhenExhausted方法来指定池到达maxTotal连接时的行为。请参阅 https ://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setBlockWhenExhausted-boolean- 了解详情。
在使用公共池时实现的模式是创建2个接口,一个用于您的池对象,另一个用于工厂...
SecretKeySpec getSecretKeySpec(byte [] bytes)抛出Exception;
}
public interface CipherFactory {
PooledCipher getCipher()throws Exception;
void close();
CipherFactory实现...
public class CipherFactoryImpl extends BasePooledObjectFactory< PooledCipher>
实现CipherFactory {
private final GenericObjectPoolConfig config;
private final GenericObjectPool< PooledCipher>池;
private final字符串转换;
private final int opmode;
私人最终钥匙;
private final AlgorithmParameters params;
private final String secretKeySpecAlgorithm;
public CipherFactoryImpl(GenericObjectPoolConfig config,String transformation,int opmode,Key key,AlgorithmParameters params,String secretKeySpecAlgorithm){
this.config = config;
this.pool = new GenericObjectPool< PooledCipher>(this,config);
this.transformation = transformation;
this.opmode = opmode;
this.key = key;
this.params = params;
this.secretKeySpecAlgorithm = secretKeySpecAlgorithm
$ b @Override
public PooledCipher create()抛出Exception {
return new PooledCipherImpl(pool,transformation,opmode, key,params,secretKeySpecAlgorithm);
}
@Override
public PooledCipher getCipher()抛出异常{
return pool.borrowObject();
$ b @Override
public void destroyObject(PooledObject< PooledCipher> p)throws Exception {
try {
PooledCipherImpl cipherImpl =(PooledCipherImpl)p。的getObject();
//根据需要用cipherImpl来销毁它
} finally {
super.destroyObject(p);
}
}
@Override
public void close(){
pool.close();
}
@Override
public PooledObject< PooledCipher> wrap(PooledCipher cipher){
返回新的DefaultPooledObject< PooledCipher>(cipher);
$ / code>
PooledCipher实现...
public class PooledCipherImpl implements PooledCipher {
private final ObjectPool< PooledCipher>池;
私有最终密码密码;
private final String secretKeySpecAlgorithm;
private boolean destroyOnClose = false;
public PooledCipherImpl(ObjectPool< PooledCipher> pool,String transformation,int opmode,Key key,AlgorithmParameters params,String secretKeySpecAlgorithm){
this.pool = pool;
this.cipher = Cipher.getInstance(transformation);
this.cipher.init(opmode,key,params);
this.secretKeySpecAlgorithm = secretKeySpecAlgorithm;
$ b $覆盖
public byte [] doFinal(byte [] bytes)throws Exception {
try {
return cipher.doFinal(bytes) ;
} catch(Exception e){
destroyOnClose = true;
throw e;
}
}
@Override
public SecretKeySpec getSecretKeySpec(byte [] bytes){
返回新的SecretKeySpec(doFinal(bytes),secretKeySpecAlgorithm);
$ b @Override
public void close()throws IOException {
try {
if(destroyOnClose){
pool.destroyObject(这个);
} else {
pool.returnObject(this);
}
} catch(Exception e){
throw new IOException(e);
$ b $ / code>
然后你构造你的CipherFactory这... ...
字符串转换=DESede / CBC / NoPadding;
String secretKeySpecAlgorithm =DESede;
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
//在这里设置poolConfig
poolConfig.setMaxTotal(20);
CipherFactory cipherFactory = new CipherFactoryImpl(poolConfig,transformation,Cipher.DECRYPT_MODE,mkkey,algParamSpec,secretKeySpecAlgorithm);
并像这样使用它...
< pre $
public key unwrapKey(byte [] tmkByte)throws Exception {
try(PooledCipher cipher = cipherFactory.getCipher()){
return cipher.getSecretKeySpec(tmkByte) ;
$ / code> 您也可以重新使用PooledCipher和CipherFactory接口来创建其他实现,如JCA。
I'm doing research on GenericObjectPool
by putting Cipher
in pool so it can be reused.
GenericObjectPool<Cipher> pool;
CipherFactory factory = new CipherFactory();
this.pool = new GenericObjectPool<Cipher>(factory);
pool.setMaxTotal(10);
pool.setBlockWhenExhausted(true);
pool.setMaxWaitMillis(30 * 1000);
CipherFactory
public class CipherFactory extends BasePooledObjectFactory<Cipher> {
private boolean running = false;
@Override
public Cipher create() throws Exception {
return Cipher.getInstance("DESede/CBC/NoPadding");
}
@Override
public PooledObject<Cipher> wrap(Cipher arg0) {
return new DefaultPooledObject<Cipher>(arg0);
}
@Override
public boolean validateObject(PooledObject<Cipher> p) {
//Ensures that the instance is safe to be returned by the pool
return true;
}
@Override
public void destroyObject(PooledObject<Cipher> p) {
//Destroys an instance no longer needed by the pool.
System.out.println("destroying");
}
@Override
public void activateObject(PooledObject<Cipher> p) throws Exception { //Reinitialize an instance to be returned by the pool
setRunning(true);
}
@Override
public void passivateObject(PooledObject<Cipher> p) throws Exception { // reset the object after the object returns to the pool
setRunning(false);
}
public void setRunning(boolean running) {
this.running = running;
}
//
}
This is how I implement ObjectPool
in my Example class
public Key a(byte[] afyte) throws Exception {
Cipher cipher = null;
cipher = pool.borrowObject(); //get the object from the pool
try {
System.out.println("****************** After borrow ****************");
printPool();
cipher.init(Cipher.DECRYPT_MODE, mkkey, algParamSpec);
byte[] de = cipher.doFinal(afyte);
SecretKey mk = new SecretKeySpec(de, "DESede");
return mk;
} catch (Exception e) {
pool.invalidateObject(cipher);
cipher = null;
} finally {
if (null != cipher) {
pool.returnObject(cipher);
System.out.println("****************** After return ****************");
printPool();
}
}
return (Key) cipher;
}
printPool
public void printPool() {
System.out.println("Pool for cipher with instances DESede/CBC/NoPadding");
System.out.println("Active [" + pool.getNumActive() + "]"); //Return the number of instances currently borrowed from this pool
System.out.println("Idle [" + pool.getNumIdle() + "]"); //The number of instances currently idle in this pool
System.out.println("Total Created [" + pool.getCreatedCount() + "]");
}
Am I on the right path ? Is it possible to increase pool size ?
Edit
The answer from @http works fine to me. But if I have another method encryptECB(Key key, byte[] b)
, how should I write ?
Any help would be appreciated !
解决方案 You are on the right track. When constructing the GenericObjectPool, you can use the constructor that accepts a GenericObjectPoolConfig object which contains all the configuration values for your object pool. The example below would let your pool grow to 20 connections before it was exhausted...
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMinIdle(2);
config.setMaxIdle(5);
config.setMaxTotal(20);
GenericObjectPool<Cipher> pool;
CipherFactory factory = new CipherFactory();
this.pool = new GenericObjectPool<Cipher>(factory, config);
GenericeObjectPoolConfig also has a setBlockWhenExhausted method to specify the behaviour when the pool has reached the maxTotal connections. See https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setBlockWhenExhausted-boolean- for details.
A pattern I implement when using commons pool is to create 2 interfaces, one for your pooled object and one for your factory...
public interface PooledCipher extends java.io.Closeable {
byte[] doFinal(byte[] bytes) throws Exception;
SecretKeySpec getSecretKeySpec(byte[] bytes) throws Exception;
}
public interface CipherFactory {
PooledCipher getCipher() throws Exception;
void close();
}
CipherFactory implementation...
public class CipherFactoryImpl extends BasePooledObjectFactory<PooledCipher>
implements CipherFactory {
private final GenericObjectPoolConfig config;
private final GenericObjectPool<PooledCipher> pool;
private final String transformation;
private final int opmode;
private final Key key;
private final AlgorithmParameters params;
private final String secretKeySpecAlgorithm;
public CipherFactoryImpl(GenericObjectPoolConfig config, String transformation, int opmode, Key key, AlgorithmParameters params, String secretKeySpecAlgorithm) {
this.config = config;
this.pool = new GenericObjectPool<PooledCipher>(this, config);
this.transformation = transformation;
this.opmode = opmode;
this.key = key;
this.params = params;
this.secretKeySpecAlgorithm = secretKeySpecAlgorithm
}
@Override
public PooledCipher create() throws Exception {
return new PooledCipherImpl(pool, transformation, opmode, key, params, secretKeySpecAlgorithm);
}
@Override
public PooledCipher getCipher() throws Exception {
return pool.borrowObject();
}
@Override
public void destroyObject(PooledObject<PooledCipher> p) throws Exception {
try {
PooledCipherImpl cipherImpl = (PooledCipherImpl)p.getObject();
// do whatever you need with cipherImpl to destroy it
} finally {
super.destroyObject(p);
}
}
@Override
public void close() {
pool.close();
}
@Override
public PooledObject<PooledCipher> wrap(PooledCipher cipher) {
return new DefaultPooledObject<PooledCipher>(cipher);
}
}
PooledCipher implementation...
public class PooledCipherImpl implements PooledCipher {
private final ObjectPool<PooledCipher> pool;
private final Cipher cipher;
private final String secretKeySpecAlgorithm;
private boolean destroyOnClose = false;
public PooledCipherImpl(ObjectPool<PooledCipher> pool, String transformation, int opmode, Key key, AlgorithmParameters params, String secretKeySpecAlgorithm) {
this.pool = pool;
this.cipher = Cipher.getInstance(transformation);
this.cipher.init(opmode, key, params);
this.secretKeySpecAlgorithm = secretKeySpecAlgorithm;
}
@Override
public byte[] doFinal(byte[] bytes) throws Exception {
try {
return cipher.doFinal(bytes);
} catch (Exception e) {
destroyOnClose = true;
throw e;
}
}
@Override
public SecretKeySpec getSecretKeySpec(byte[] bytes) {
return new SecretKeySpec(doFinal(bytes), secretKeySpecAlgorithm);
}
@Override
public void close() throws IOException {
try {
if (destroyOnClose) {
pool.destroyObject(this);
} else {
pool.returnObject(this);
}
} catch (Exception e) {
throw new IOException(e);
}
}
}
Then you construct your CipherFactory like this...
String transformation = "DESede/CBC/NoPadding";
String secretKeySpecAlgorithm = "DESede";
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// set up the poolConfig here
poolConfig.setMaxTotal(20);
CipherFactory cipherFactory = new CipherFactoryImpl(poolConfig, transformation, Cipher.DECRYPT_MODE, mkkey, algParamSpec, secretKeySpecAlgorithm);
And use it like this...
public Key unwrapKey(byte[] tmkByte) throws Exception {
try (PooledCipher cipher = cipherFactory.getCipher()) {
return cipher.getSecretKeySpec(tmkByte);
}
}
Also you can reuse the PooledCipher and CipherFactory interfaces to create other implementations, such as JCA.
这篇关于在GenericObjectPool中创建对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!