Создание объектов в GenericObjectPool
я провожу исследование на GenericObjectPool
положить Cipher
в пуле, поэтому его можно использовать повторно.
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;
}
//
}
вот как я реализую ObjectPool
в своем пример класс
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() + "]");
}
Я на правильном пути ? Можно ли увеличить размер пула ?
редактировать
ответ от @http отлично работает для меня. Но если у меня есть другой метод encryptECB(Key key, byte[] b)
, как я должен писать ?
любая помощь будет оценили !
1 ответов
вы на правильном пути. При построении GenericObjectPool можно использовать конструктор, который принимает объект GenericObjectPoolConfig, содержащий все значения конфигурации для пула объектов. Пример ниже позволит вашему пулу вырасти до 20 соединений, прежде чем он будет исчерпан...
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 также имеет метод setBlockWhenExhausted, чтобы указать поведение, когда пул достиг соединений maxTotal. Видеть https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setBlockWhenExhausted-boolean- для деталей.
шаблон, который я реализую при использовании общего пула, заключается в создании 2 интерфейсов, одного для вашего объединенного объекта и одного для вашей фабрики...
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...
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...
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);
}
}
}
затем вы строите свой CipherFactory вроде этого...
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);
и используйте его так...
public Key unwrapKey(byte[] tmkByte) throws Exception {
try (PooledCipher cipher = cipherFactory.getCipher()) {
return cipher.getSecretKeySpec(tmkByte);
}
}
также можно повторно использовать интерфейсы PooledCipher и CipherFactory для создания других реализаций, таких как JCA.