文档章节

基于Jedis的工具类

yiguangtia
 yiguangtia
发布于 2018/12/21 10:55
字数 2724
阅读 9
收藏 0
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import com.liying.monkey.core.common.Constants.Zero;

public class RedisUtil {
    private static final Logger log = Logger.getLogger(RedisUtil.class);
    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 15 * 1000;
    //超时时间
    private static int TIMEOUT = 10 * 1000;
    
    private static JedisPool jedisPool = null;
    
    /**
     * Jedis实例获取返回码
     * 
     * @author jqlin
     *
     */
    public static class JedisStatus{
        /**Jedis实例获取失败*/
        public static final long FAIL_LONG = -5L;
        /**Jedis实例获取失败*/
        public static final int FAIL_INT = -5;
        /**Jedis实例获取失败*/
        public static final String FAIL_STRING = "-5";
    }
    
    
    private static void initialPool() {
        //Redis服务器IP
        String HOST = PropertyReader.get("redis.native.host");
        //Redis的端口号
        int PORT = NumberUtils.toInt(PropertyReader.get("redis.native.port"), 6379);
        //访问密码
        String AUTH = PropertyReader.get("redis.native.password");
        
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            //最大连接数,如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
            config.setMaxTotal(NumberUtils.toInt(PropertyReader.get("redis.native.maxTotal"), 400));
            //最大空闲数,控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
            config.setMaxIdle(NumberUtils.toInt(PropertyReader.get("redis.native.maxIdle"), 50));
            //最小空闲数
            config.setMinIdle(NumberUtils.toInt(PropertyReader.get("redis.native.minIdle"), 10));
            //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
            config.setTestOnBorrow(true);
            //在return给pool时,是否提前进行validate操作
            config.setTestOnReturn(true);
            //在空闲时检查有效性,默认false
            config.setTestWhileIdle(true);
            //表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;
            //这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
            config.setMinEvictableIdleTimeMillis(30000);
            //表示idle object evitor两次扫描之间要sleep的毫秒数
            config.setTimeBetweenEvictionRunsMillis(60000);
            //表示idle object evitor每次扫描的最多的对象数
            config.setNumTestsPerEvictionRun(1000); 
            //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
            config.setMaxWaitMillis(MAX_WAIT);
            
            if (StringUtils.isNotBlank(AUTH)) {
                jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT, AUTH);
            } else {
                jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT);
            }
        } catch (Exception e) {
            if(jedisPool != null){
                jedisPool.close();
            }
            log.error("初始化Redis连接池失败", e);
        }
    }
    
    /**
     * 初始化Redis连接池
     */
    static {
        initialPool();
    }
    
    /**
     * 在多线程环境同步初始化
     */
    private static synchronized void poolInit() {
        if (jedisPool == null) {
            initialPool();
        }
    }
    
     /**
     * 同步获取Jedis实例
     *
     * @return Jedis
     */
    public static Jedis getJedis() {
        if (jedisPool == null) {
            poolInit();
        }

        Jedis jedis = null;
        try {
            if (jedisPool != null) {
                jedis = jedisPool.getResource();
            }
        } catch (Exception e) {
            log.error("同步获取Jedis实例失败" + e.getMessage(), e);
            returnBrokenResource(jedis);
        }  
        
        return jedis;
    }
    
    /**
     * 释放jedis资源
     *
     * @param jedis
     */
    @SuppressWarnings("deprecation")
    public static void returnResource(final Jedis jedis) {
        if (jedis != null && jedisPool != null) {
            jedisPool.returnResource(jedis);
        }
    }
    
    @SuppressWarnings("deprecation")
    public static void returnBrokenResource(final Jedis jedis) {
        if (jedis != null && jedisPool != null) {
            jedisPool.returnBrokenResource(jedis);
        }
    }
    
    /**
     * 设置值
     * 
     * @param key 
     * @param value 
     * @return -5:Jedis实例获取失败<br/>OK:操作成功<br/>null:操作失败
     * @author jqlin
     */
    public static String set(String key, String value) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_STRING;
        }
         
        String result = null;
        try { 
            result = jedis.set(key, value);
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 设置值
     * 
     * @param key
     * @param value
     * @param expire 过期时间,单位:秒
     * @return -5:Jedis实例获取失败<br/>OK:操作成功<br/>null:操作失败
     * @author jqlin
     */
    public static String set(String key, String value, int expire) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_STRING;
        }
        
        String result = null;
        try { 
            result = jedis.set(key, value);
            jedis.expire(key, expire);
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }
        
        return result;
    }
    
    /**
     * 获取值
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static String get(String key) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_STRING;
        }
         
        String result = null;
        try { 
            result = jedis.get(key);
        } catch (Exception e) {
            log.error("获取值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 设置key的过期时间
     * 
     * @param key
     * @param value -5:Jedis实例获取失败,1:成功,0:失败
     * @return
     * @author jqlin
     */
    public static long expire(String key, int seconds) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_LONG;
        }
         
        long result = Zero.LONG;
        try { 
            result = jedis.expire(key, seconds);
        } catch (Exception e) {
            log.error(String.format("设置key=%s的过期时间失败:" + e.getMessage(), key), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 判断key是否存在
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static boolean exists(String key) {
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return false;
        }
         
        boolean result = false;
        try { 
            result = jedis.exists(key);
        } catch (Exception e) {
            log.error(String.format("判断key=%s是否存在失败:" + e.getMessage(), key), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 删除key
     * 
     * @param keys
     * @return -5:Jedis实例获取失败,1:成功,0:失败
     * @author jqlin
     */
    public static long del(String... keys) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_LONG;
        }
         
        long result = JedisStatus.FAIL_LONG;
        try {  
            result = jedis.del(keys);
        } catch (Exception e) {
            log.error(String.format("删除key=%s失败:" + e.getMessage(), keys), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * set if not exists,若key已存在,则setnx不做任何操作
     * 
     * @param key
     * @param value key已存在,1:key赋值成功
     * @return
     * @author jqlin
     */
    public static long setnx(String key, String value) {
        long result = JedisStatus.FAIL_LONG;
        
        Jedis jedis = getJedis();
        if(jedis == null){
            return result;
        }
         
        try { 
            result = jedis.setnx(key, value);
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * set if not exists,若key已存在,则setnx不做任何操作
     * 
     * @param key
     * @param value key已存在,1:key赋值成功
     * @param expire 过期时间,单位:秒
     * @return
     * @author jqlin
     */
    public static long setnx(String key, String value, int expire) {
        long result = JedisStatus.FAIL_LONG;
        
        Jedis jedis = getJedis();
        if(jedis == null){
            return result;
        }
        
        try {
            result = jedis.setnx(key, value);
            jedis.expire(key, expire);
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }
        
        return result;
    }
    
    /**
     * 在列表key的头部插入元素
     * 
     * @param key
     * @param values -5:Jedis实例获取失败,>0:返回操作成功的条数,0:失败
     * @return
     * @author jqlin
     */
    public static long lpush(String key, String... values) {
        long result = JedisStatus.FAIL_LONG;
        
        Jedis jedis = getJedis();
        if(jedis == null){
            return result;
        }
         
        try { 
            result = jedis.lpush(key, values);
        } catch (Exception e) {
            log.error("在列表key的头部插入元素失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 在列表key的尾部插入元素
     * 
     * @param key
     * @param values -5:Jedis实例获取失败,>0:返回操作成功的条数,0:失败
     * @return
     * @author jqlin
     */
    public static long rpush(String key, String... values) {
        long result = JedisStatus.FAIL_LONG;
        
        Jedis jedis = getJedis();
        if(jedis == null){
            return result;
        }
         
        try { 
            result = jedis.rpush(key, values);
        } catch (Exception e) {
            log.error("在列表key的尾部插入元素失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 返回存储在key列表的特定元素 
     *   
     * 
     * @param key 
     * @param start 开始索引,索引从0开始,0表示第一个元素,1表示第二个元素
     * @param end 结束索引,-1表示最后一个元素,-2表示倒数第二个元素
     * @return redis client获取失败返回null
     * @author jqlin
     */
    public static List<String> lrange(String key, long start, long end) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return null;
        }
         
        List<String> result = null;
        try { 
            result = jedis.lrange(key, start, end);
        } catch (Exception e) {
            log.error("查询列表元素失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 获取List缓存对象
     * 
     * @param key
     * @param start
     * @param end
     * @return List<T> 返回类型
     * @author jqlin
     */
    public static <T> List<T> range(String key, long start, long end, Class<T> clazz){
        List<String> dataList = lrange(key, start, end);
        if(CollectionUtils.isEmpty(dataList)){
            return new ArrayList<T>();
        }
        
        return JavaJsonConvert.json2List(dataList.toString(), clazz);
    }

    /**
     * 获取列表长度
     * 
     * @param key -5:Jedis实例获取失败
     * @return
     * @author jqlin
     */
    public static long llen(String key) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_LONG;
        }
         
        long result = 0;
        try { 
            result = jedis.llen(key);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 移除等于value的元素<br/><br/>
     *        当count>0时,从表头开始查找,移除count个;<br/>
     *        当count=0时,从表头开始查找,移除所有等于value的;<br/>
     *        当count<0时,从表尾开始查找,移除count个
     * 
     * @param key
     * @param count
     * @param value
     * @return -5:Jedis实例获取失败
     * @author jqlin
     */
    public static long lrem(String key, long count, String value) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_LONG;
        }
         
        long result = 0;
        try { 
            result = jedis.lrem(key, count, value);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 对列表进行修剪
     * 
     * @param key
     * @param start
     * @param end
     * @return -5:Jedis实例获取失败,OK:命令执行成功
     * @author jqlin
     */
    public static String ltrim(String key, long start, long end) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_STRING;
        }
         
        String result = "";
        try { 
            result = jedis.ltrim(key, start, end);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 设置对象
     * 
     * @param key
     * @param obj
     * @return
     * @author jqlin
     */
    public static <T> String setObject(String key ,T obj){  
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_STRING;
        }
         
        String result = null;
        try { 
            byte[] data=SerializeUtil.serialize(obj); 
            result = jedis.set(key.getBytes(), data);
        } catch (Exception e) {
            log.error("设置对象失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 获取对象
     * 
     * @param key
     * @return
     * @author jqlin
     */
    @SuppressWarnings("unchecked")
    public static <T> T getObject(String key){  
        Jedis jedis = getJedis();
        if(jedis == null){
            return null;
        }
         
        T result = null;
        try { 
            byte[] data = jedis.get(key.getBytes());
            if(data != null && data.length > 0){
                result=(T)SerializeUtil.unserialize(data);
            }
        } catch (Exception e) {
            log.error("获取对象失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 设置List集合(慎用)
     * 
     * @param key
     * @param dataList
     * @return
     * @author jqlin
     */
    public synchronized static <T> T setList(String key, List<T> dataList){  
        Jedis jedis = getJedis();
        if(jedis == null){
            return null;
        }
         
        T result = null;
        try { 
            List<T> list = getList(key);
            if(CollectionUtils.isNotEmpty(list)){
                dataList.addAll(list);
            }
            
            if(CollectionUtils.isNotEmpty(dataList)){
                byte[] data = SerializeUtil.serializeToList(dataList);
                jedis.set(key.getBytes(), data);
            }else{//如果list为空,则设置一个空  
                jedis.set(key.getBytes(), "".getBytes());
            }
        } catch (Exception e) {
            log.error("设置List集合失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 获取List集合(慎用)
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static <T> List<T> getList(String key){  
        Jedis jedis = getJedis();
        if(jedis == null){
            return null;
        }
         
        try { 
             byte[] data = getJedis().get(key.getBytes());  
             if(data != null && data.length > 0){
                 return SerializeUtil.unserializeToList(data);
             }
        } catch (Exception e) {
            log.error("获取List集合失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return null;
    }
    
    /**
     * 缓存Map赋值
     * 
     * @param key
     * @param field
     * @param value
     * @return -5:Jedis实例获取失败
     * @author jqlin
     */
    public static long hset(String key, String field, String value) {
        Jedis jedis = getJedis();
        if(jedis == null){
            return JedisStatus.FAIL_LONG;
        }
         
        long result = 0L;
        try { 
            result = jedis.hset(key, field, value);
        } catch (Exception e) {
            log.error("缓存Map赋值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    
    /**
     * 获取缓存的Map值
     * 
     * @param key
     * @return
     */
    public static String hget(String key, String field){
        Jedis jedis = getJedis();
        if(jedis == null){
            return null;
        }
         
        String result = null;
        try { 
            result = jedis.hget(key, field);
        } catch (Exception e) {
            log.error("获取缓存的Map值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return result;
    }
    
    /**
     * 获取map所有的字段和值
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static Map<String, String> hgetAll(String key){
        Map<String, String> map = new HashMap<String, String>();
        
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return map;
        }
         
        try { 
            map = jedis.hgetAll(key);
        } catch (Exception e) {
            log.error("获取map所有的字段和值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return map;
    }
    
    /**
     * 查看哈希表 key 中,指定的field字段是否存在。
     * 
     * @param key
     * @param field
     * @return
     * @author jqlin
     */
    public static Boolean hexists(String key, String field){
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return null;
        }
         
        try { 
            return jedis.hexists(key, field);
        } catch (Exception e) {
            log.error("查看哈希表field字段是否存在失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return null;
    }

    /**
     * 获取所有哈希表中的字段
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static Set<String> hkeys(String key) {
        Set<String> set = new HashSet<String>();
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return set;
        }
        
        try { 
            return jedis.hkeys(key);
        } catch (Exception e) {
            log.error("获取所有哈希表中的字段失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return null;
    }
    
    /**
     * 获取所有哈希表中的值
     * 
     * @param key
     * @return
     * @author jqlin
     */
    public static List<String> hvals(String key) {
        List<String> list = new ArrayList<String>();
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return list;
        }
        
        try { 
            return jedis.hvals(key);
        } catch (Exception e) {
            log.error("获取所有哈希表中的值失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return null;
    }
    
    /**
     * 从哈希表 key 中删除指定的field
     * 
     * @param key
     * @param field
     * @return  
     * @author jqlin
     */
    public static long hdel(String key, String... fields){
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return JedisStatus.FAIL_LONG;
        }
        
        try { 
            return jedis.hdel(key, fields);
        } catch (Exception e) {
            log.error("map删除指定的field失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return 0;
    }
    
    public static Set<String> keys(String pattern){
        Set<String> keyList = new HashSet<String>();
        Jedis jedis = getJedis();
        if(jedis == null){
            log.warn("Jedis实例获取为空");
            return keyList;
        }
        
        try { 
            keyList = jedis.keys(pattern);
        } catch (Exception e) {
            log.error("操作keys失败:" + e.getMessage(), e);
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }

        return keyList;
    }
    
    public static void main(String[] args) throws IOException { 
//        System.out.println(hset("map", "a","3"));
//        System.out.println(hset("map", "b","3"));
//        System.out.println(hset("map", "c","3"));
        Set<String> set = keys("lock*");
        for(String key : set){
            System.out.println(key);
        }
    }
}

© 著作权归作者所有

上一篇: Redis 单机锁实现
下一篇: spark jvm
yiguangtia
粉丝 5
博文 39
码字总数 29778
作品 0
深圳
私信 提问
Spring集成Redis方案(spring-data-redis)(基于Jedis的单机模式)(待实践)

说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点。并且会与一些低版本的Spring有冲突,要看官方文档...

easonjim
2017/10/05
0
0
Redis笔记整理(二):Java API使用与Redis分布式集群环境搭建

[TOC] Redis Java API使用(一):单机版本Redis API使用 Redis的Java API通过Jedis来进行操作,因此首先需要Jedis的第三方库,因为使用的是Maven工程,所以先给出Jedis的依赖: 基本代码示例...

xpleaf
2018/06/26
0
0
Jedis 与 ShardedJedis 设计

Jedis设计 Jedis作为推荐的java语言redis客户端,其抽象封装为三部分: 对象池设计:Pool,JedisPool,GenericObjectPool,BasePoolableObjectFactory,JedisFactory 面向用户的redis操作封装...

tantexian
2016/06/07
49
0
【Redis】- 客户端 Jedis

Redis 常用客户端: Redission、Jedis jedis 简介 redis的Java客户端,可访问、操作Redis Jedis工具类: Redis 配置 基础测试类:

ZeroneLove
02/23
0
0
Spring集成redis(Spring Data Redis)

转载地址:http://blog.csdn.net/zhu_tianwei/article/details/44923001 Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(...

Mr_zebra
2018/06/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java基础-Queue

Queue实现 1、没有实现阻塞接口的 LinkedList:实现了java.util.Queue接口和java.util.AbstractQueue接口   内置的不阻塞队列:PriorityQueue和ConcurrentLinkedQueue   PriorityQueue和...

MyOldTime
39分钟前
4
0
阿里云应用高可用 AHAS 正式商用,可一键提升云上应用可用性

在分布式架构环境下,服务间的依赖日益复杂,可能没有人能说清单个故障对整个系统的影响,构建一个高可用的分布式系统面临着很大挑战。 7月17日,阿里云应用高可用服务AHAS 正式商用,包含架...

阿里云云栖社区
42分钟前
3
0
Audio 和 Video的简单介绍

HTML多媒体 , 主要分为Audio 音频和 Video 视频。 1:Audio 基本语法 src 指定当前播放的音频文件,controls播放控制器,loop歌曲循环,autoplay自动播放 (chrome66之后被禁止)主流浏览器已...

凌兮洛
56分钟前
4
0
【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)

工作中遇到需要生成PDF。最终选择了iText。其他也有通过html再生成。感觉不太适合就用了代码实现。 使用iText 5.5.13.1版本。纯Java代码实现 1.自定义表格合并指定行列完成数据填充 2.自定义...

小帅帅丶
57分钟前
11
0
Redis HyperLogLog

关于 Redis HyperLogLog 在说明 HyperLogLog 之前,我们需要先了解一个概念:基数统计。维基百科中的解释是: cardinality of a set is a measure of the “number of elements“ of the set...

xiaomin0322
58分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部