有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在GenericObject池中创建对象

我正在对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);

密码工厂

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) 个答案

  1. # 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-

    我在使用commons pool时实现的一个模式是创建两个接口,一个用于池对象,一个用于工厂

    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();
    }
    

    密码工厂实现

    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);
        }
    }
    

    池密码实现

    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);
            }
        }
    }
    

    然后你像这样建造密码工厂

    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