对用户登录输入密码错误限制

package com.comtop.map.pub.security;

import com.comtop.map.pub.cache.redis.JedisTemplate;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher {

    private static final Logger log = LoggerFactory.getLogger(RetryLimitCredentialsMatcher.class);

    private static final String NAMESPACE = "passwordRetryCache:";

    private JedisTemplate jedisTemplate;

    public RetryLimitCredentialsMatcher(JedisTemplate jedisTemplate) {
        this.jedisTemplate = jedisTemplate;
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        RestUsernamePasswordToken rupToken = (RestUsernamePasswordToken) token;

        String source = rupToken.getSource();
        String loginType = rupToken.getLoginType();
        boolean pcLogin = RestUsernamePasswordToken.LOGIN_SOURCE_PC.equals(source) && RestUsernamePasswordToken.LOGIN_SOURCE_PC.equals(loginType);

        if (!pcLogin) {
            return super.doCredentialsMatch(token, info);
        }
        String username = (String) token.getPrincipal();
        String redisKey = NAMESPACE + username;
        Object retryCount = jedisTemplate.getObject(redisKey);
        if (retryCount == null) {
            retryCount = 0;
            jedisTemplate.setexObject(redisKey, 600, retryCount);
        }
        int max = 5;
        int current = (int) retryCount + 1;
        if (current > max) {
            log.warn("username: " + username + " tried to login more than 5 times in period");
            throw new ExcessiveAttemptsException("您的用户名或密码错误次数已满,将锁定10分钟。");
        }
        jedisTemplate.setexObject(redisKey, 600, (int) retryCount + 1);
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            //clear retry data
            jedisTemplate.del(redisKey);
        } else {
            int remain = max - current;
            if (remain == 0) {
                throw new ExcessiveAttemptsException("您的用户名或密码错误次数已满,将锁定10分钟。");
            } else {
                throw new ExcessiveAttemptsException("您的用户名或密码错误,还有" + remain + "次机会。");
            }
        }
        return true;
    }

    /**
     * 根据用户名 解锁用户
     */
    public void unlockAccount(String username){
        jedisTemplate.del(NAMESPACE + username);
    }
}
package com.comtop.map.pub.config;

import com.comtop.map.pub.cache.redis.JedisTemplate;
import com.comtop.map.pub.security.Passwords;
import com.comtop.map.pub.security.RetryLimitCredentialsMatcher;
import com.comtop.map.pub.security.shiro.*;
import com.comtop.map.pub.security.shiro.cookie.CustomSysCookie;
import com.comtop.map.pub.security.shiro.session.AngWebSessionManager;
import com.comtop.map.pub.security.shiro.session.CustomSysSessionFactory;
import com.comtop.map.pub.security.shiro.subject.CustomSysSubjectFactory;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("shiroDbRealm") ShiroDbRealm shiroDbRealm,
                                           @Qualifier("defaultWebSessionManager") SessionManager sessionManager,
                                           @Qualifier("customShiroCacheManager") CacheManager cacheManager,
                                           @Qualifier("customSysSubjectFactory") CustomSysSubjectFactory subjectFactory) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setSessionManager(sessionManager);
        manager.setRealm(shiroDbRealm);
        manager.setCacheManager(cacheManager);
        manager.setSubjectFactory(subjectFactory);
        return manager;
    }

    @Bean(name = "customSysSubjectFactory")
    public CustomSysSubjectFactory customSysSubjectFactory() {
        return new CustomSysSubjectFactory();
    }

    @Bean(name = "shiroDbRealm")
    public ShiroDbRealm shiroDbRealm(@Qualifier("credentialsMatcher") RetryLimitCredentialsMatcher credentialsMatcher) {
        ShiroDbRealm realm = new ShiroDbRealm();
        realm.setCredentialsMatcher(credentialsMatcher);
        return realm;
    }

    @Bean(name = "defaultWebSessionManager")
    public SessionManager sessionManager(@Qualifier("customSysSessionFactory") CustomSysSessionFactory sessionFactory,
                                         @Qualifier("customSessionIdCookie") Cookie sessionIdCookie,
                                         @Qualifier("customShiroSessionDAO") SessionDAO sessionDAO,
                                         @Value("${shiro.session.timeout:300000}") int sessionTimeout) {
        AngWebSessionManager sessionManager = new AngWebSessionManager();
        sessionManager.setGlobalSessionTimeout(sessionTimeout);
        sessionManager.setSessionIdCookie(sessionIdCookie);
        sessionManager.setSessionDAO(sessionDAO);
        sessionManager.setSessionValidationSchedulerEnabled(false);
        sessionManager.setSessionFactory(sessionFactory);
        return sessionManager;
    }

    @Bean(name = "customSysSessionFactory")
    public CustomSysSessionFactory customSysSessionFactory(){
        return new CustomSysSessionFactory();
    }

    @Bean(name = "customSessionIdCookie")
    public Cookie cookie() {
        CustomSysCookie simpleCookie = new CustomSysCookie("Agrant");
        simpleCookie.setPath("/");
        return simpleCookie;
    }

    @Bean(name = "customShiroSessionDAO")
    public SessionDAO sessionDAO(@Qualifier("shiroSessionRepository") ShiroSessionRepository shiroSessionRepository,
                                 @Qualifier("sessionIdGenerator") SessionIdGenerator sessionIdGenerator) {
        CustomShiroSessionDAO sessionDAO = new CustomShiroSessionDAO();
        sessionDAO.setShiroSessionRepository(shiroSessionRepository);
        sessionDAO.setSessionIdGenerator(sessionIdGenerator);
        return sessionDAO;
    }

    @Bean(name = "sessionIdGenerator")
    public SessionIdGenerator sessionIdGenerator() {
        return new CustomSessionIdGenerator();
    }

    @Bean(name = "shiroSessionRepository")
    public ShiroSessionRepository shiroSessionRepository(JedisTemplate jedisTemplate) {
        return new JedisShiroSessionRepository(jedisTemplate);
    }

    @Bean(name = "customShiroCacheManager")
    public CacheManager cacheManager(@Qualifier("jedisShiroCacheManager") ShiroCacheManager shiroCacheManager) {
        CustomShiroCacheManager cacheManager = new CustomShiroCacheManager();
        cacheManager.setShiroCacheManager(shiroCacheManager);
        return cacheManager;
    }

    @Bean(name = "jedisShiroCacheManager")
    public ShiroCacheManager shiroCacheManager(JedisTemplate jedisTemplate) {
        return new JedisShiroCacheManager(jedisTemplate);
    }

    @Bean(name = "credentialsMatcher")
    public RetryLimitCredentialsMatcher hashedCredentialsMatcher(JedisTemplate jedisTemplate) {
        // 设定Password校验的Hash算法与迭代次数.
        RetryLimitCredentialsMatcher credentialsMatcher = new RetryLimitCredentialsMatcher(jedisTemplate);
        credentialsMatcher.setHashAlgorithmName(Passwords.HASH_ALGORITHM);
        credentialsMatcher.setHashIterations(Passwords.HASH_INTERATIONS);
        return credentialsMatcher;
    }

    @Bean("managePerms")
    public ManagePerms managePerms(){
        return new ManagePerms();
    }

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager,
                                              @Qualifier("managePerms") ManagePerms managePerms,
                                              @Qualifier("restAnonymousFilter") Filter restApi) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(manager);
        shiroFilterFactoryBean.setLoginUrl("/login/timeout");
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        Map filters = new HashMap<>();
        filters.put("restApi", restApi);
        shiroFilterFactoryBean.setFilters(filters);
        LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/ueditor/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/docs.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**",   "anon");
        filterChainDefinitionMap.put("/v2/api-docs", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");

        filterChainDefinitionMap.put("/captcha", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/login/**", "anon");
        filterChainDefinitionMap.put("/unauthorized", "anon");
        filterChainDefinitionMap.put("/api/download/history", "user");

        filterChainDefinitionMap.putAll(managePerms.getUri());

        filterChainDefinitionMap.put("/api/**", "anon");
        filterChainDefinitionMap.put("/admin/**", "restApi");
        filterChainDefinitionMap.put("/developer/**", "restApi");
        filterChainDefinitionMap.put("/**", "user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean(name = "restAnonymousFilter")
    public Filter restAnonymousFilter() {
        return new RestAnonymousFilter();
    }

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
package com.comtop.map.pub.security;


import com.comtop.map.pub.security.shiro.CaptchaUsernamePasswordToken;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.apache.commons.lang3.StringUtils;

/**
 * rest服务登录新增客户端id字段
 */
@JsonIgnoreProperties(value = { "password", "principal", "credentials", "tenantId" })
public class RestUsernamePasswordToken extends CaptchaUsernamePasswordToken {

    /** 登陆来源  pc端 */
    public static final String LOGIN_SOURCE_PC = "PC";

    /** 登陆来源 手机端 */
    public static final String LOGIN_SOURCE_MOBILE = "MOBILE";

    /** 默认使用用户名或密码方式登录 */
    public static final String LOGIN_TYPE_DEFAULT = "DEFAULT";

    /** 4A账号登陆 */
    public static final String LOGIN_TYPE_4A = "4A";

    /** 短信验证码登陆 */
    public static final String LOGIN_TYPE_SMSCODE = "SMS_CODE";


    /** 序列串 */
    private static final long serialVersionUID = 7648265740211328498L;
    
    /** 是否是token登录,这个在根据token登录时候很有用。因为token登录时不知道用户密码,所有用该配置项来取消配置 */
    private String loginType = LOGIN_TYPE_DEFAULT;
    
    /** 登录来源 终端;PC端 */
    private String source = LOGIN_SOURCE_PC;
    
    /** 用于存储数据 */
    private Object data;
    
    /**
     * 构造函数(默认开启验证码)
     */
    public RestUsernamePasswordToken() {
        super();
    }
    
    /**
     * 构造函数
     * 
     * @param username username
     * @param password password
     * @param rememberMe rememberMe
     * @param host host
     * @param captcha captcha
     * @param isCaptchaEnabled 独立开关,是否开启验证码验证
     */
    public RestUsernamePasswordToken(String username, String password, boolean rememberMe, String host, String captcha, boolean isCaptchaEnabled) {
        super(username, password, rememberMe, host, captcha);
        this.captchaEnabled = isCaptchaEnabled;
    }

    
    /**
     * 构造函数(关闭验证码)
     * 
     * @param username username
     * @param password password
     * @param rememberMe rememberMe
     * @param host host
     * @param captcha 验证码
     */
    public RestUsernamePasswordToken(String username, String password, boolean rememberMe, String host, String captcha) {
        this(username, password, rememberMe, host, captcha, false);
        if (StringUtils.isNotBlank(captcha)) {
            this.captchaEnabled = true;
        }
    }

    /**
     * @return loginType
     */
    public String getLoginType() {
        return loginType;
    }
    
    /**
     * @param loginType 要设置的 loginType
     */
    public void setLoginType(String loginType) {
        this.loginType = loginType;
    }
    
    /**
     * @return data
     */
    public Object getData() {
        return data;
    }
    
    /**
     * @param data 要设置的 data
     */
    public void setData(Object data) {
        this.data = data;
    }

	public String getSource() {
		return source;
	}

	public void setSource(String source) {
		this.source = source;
	}
}

package com.comtop.map.pub.cache.redis;

import com.comtop.map.pub.utils.SerializeUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.Pool;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * JedisTemplate 提供了一个template方法,负责对Jedis连接的获取与归还。 JedisAction 和 JedisActionNoResult两种回调接口,适用于有无返回值两种情况。 同时提供一些最常用函数的封装, 如get/set/zadd等。
 */
public class JedisTemplate {

    /**
     * FIXME
     */
    private static Logger logger = LoggerFactory.getLogger(JedisTemplate.class);

    /**
     * Jedis连接资源池
     */
    private Pool jedisPool;

    /**
     * sharded模式下的资源池
     */
    private ShardedJedisPool shardedPool;

    /**
     * 是否为sharded模式
     */
    private boolean isSharded;

    /**
     * 构造函数
     *
     * @param jedisPool 普通连接池
     */
    public JedisTemplate(Pool jedisPool) {
        this.jedisPool = jedisPool;
    }

    /**
     * 构造函数
     *
     * @param isSharded   是否为sharded模式
     * @param jedisPool   普通连接池
     * @param shardedPool sharded连接池
     */
    public JedisTemplate(boolean isSharded, Pool jedisPool, ShardedJedisPool shardedPool) {
        this.isSharded = isSharded;
        this.jedisPool = jedisPool;
        this.shardedPool = shardedPool;
    }

    /**
     * 执行有返回结果的action。
     *
     * @param jedisAction xx
     * @return xx
     * @throws JedisException xx
     */
    public  T execute(JedisAction jedisAction) throws JedisException {
        Jedis jedis = null;
        boolean broken = false;
        try {
            jedis = jedisPool.getResource();
            return jedisAction.action(jedis);
        } catch (JedisConnectionException e) {
            logger.error("Redis connection lost.", e);
            broken = true;
            throw e;
        } finally {
            closeResource(jedis, broken);
        }
    }

    /**
     * 执行无返回结果的action。
     *
     * @param jedisAction xx
     * @throws JedisException xx
     */
    public void execute(JedisActionNoResult jedisAction) throws JedisException {
        Jedis jedis = null;
        boolean broken = false;
        try {
            jedis = jedisPool.getResource();
            jedisAction.action(jedis);
        } catch (JedisConnectionException e) {
            logger.error("Redis connection lost.", e);
            broken = true;
            throw e;
        } finally {
            closeResource(jedis, broken);
        }
    }

    /**
     * 根据连接是否已中断的标志,分别调用returnBrokenResource或returnResource。
     *
     * @param jedis            xx
     * @param connectionBroken xx
     */
    protected void closeResource(Jedis jedis, boolean connectionBroken) {
        if (jedis != null) {
            try {
                jedis.close();
            } catch (Exception e) {
                logger.error("Error happen when return jedis to pool, try to close it directly.", e);
                if (jedis.isConnected()) {
                    try {
                        try {
                            jedis.quit();
                        } catch (Exception ex) {
                        }
                        jedis.disconnect();
                    } catch (Exception ex) {

                    }
                }
            }
        }
    }

    // //////////////////////////////////////////////////////////////////////
    // //Sharded interface

    /**
     * 执行有返回结果的action。
     *
     * @param shardedJedisAction xx
     * @return xx
     * @throws JedisException xx
     */
    public  T execute(ShardedJedisAction shardedJedisAction) throws JedisException {
        ShardedJedis shardedJedis = null;
        boolean broken = false;
        try {
            shardedJedis = shardedPool.getResource();
            return shardedJedisAction.action(shardedJedis);
        } catch (JedisConnectionException e) {
            logger.error("Redis connection lost.", e);
            broken = true;
            throw e;
        } finally {
            closeShardedResource(shardedJedis, broken);
        }
    }

    /**
     * 执行无返回结果的action。
     *
     * @param jedisAction xx
     * @throws JedisException xx
     */
    public void execute(ShardedJedisActionNoResult jedisAction) throws JedisException {
        ShardedJedis shardedJedis = null;
        boolean broken = false;
        try {
            shardedJedis = shardedPool.getResource();
            jedisAction.action(shardedJedis);
        } catch (JedisConnectionException e) {
            logger.error("Redis connection lost.", e);
            broken = true;
            throw e;
        } finally {
            closeShardedResource(shardedJedis, broken);
        }
    }

    /**
     * 根据连接是否已中断的标志,分别调用returnBrokenResource或returnResource。
     *
     * @param shardedJedis     xx
     * @param connectionBroken xx
     */
    protected void closeShardedResource(ShardedJedis shardedJedis, boolean connectionBroken) {
        if (shardedJedis != null) {
            try {
                shardedJedis.close();
            } catch (Exception e) {
                logger.error("Error happen when return jedis to pool, try to close it directly.", e);
                for (Jedis jedis : shardedJedis.getAllShards()) {
                    if (jedis.isConnected()) {
                        try {
                            try {
                                jedis.quit();
                            } catch (Exception ex) {
                            }
                            shardedJedis.disconnect();
                        } catch (Exception ex) {

                        }
                    }
                }
            }
        }
    }

    // //////////////////////////////////////////////////////////////////////

    /**
     * 获取内部的pool做进一步的动作。
     *
     * @return xx
     */
    public Pool getJedisPool() {
        return jedisPool;
    }

    /**
     * 获取内部的pool做进一步的动作。
     *
     * @return xx
     */
    public ShardedJedisPool getShardedPool() {
        return shardedPool;
    }

    /**
     * 有返回结果的回调接口定义。
     *
     * @param  xx
     */
    public interface JedisAction {

        /**
         * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
         *
         * @param jedis xx
         * @return xx
         */
        T action(Jedis jedis);
    }

    /**
     * 无返回结果的回调接口定义。
     */
    public interface JedisActionNoResult {


        /**
         * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
         *
         * @param jedis xx
         */
        void action(Jedis jedis);
    }

    /**
     * 用于Sharded集群的回调接口定义
     *
     * @param  xx
     */
    public interface ShardedJedisAction {


        /**
         * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
         *
         * @param jedis Shared 集群 Jedis 对象
         * @return xx
         */
        S action(ShardedJedis jedis);
    }

    /**
     * 无返回结果的回调接口定义。
     */
    public interface ShardedJedisActionNoResult {


        /**
         * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
         *
         * @param jedis xx
         */
        void action(ShardedJedis jedis);
    }

    // ////////////// 常用方法的封装 ///////////////////////// //

    // ////////////// 公共 ///////////////////////////

    /**
     * 删除key, 如果key存在返回true, 否则返回false。
     *
     * @param key xx
     * @return xx
     */
    public boolean del(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.del(key) == 1 ? true : false;
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.del(key) == 1 ? true : false;
                }
            });
        }
    }

    /**
     * 如果key存在返回true, 否则返回false。
     *
     * @param key xx
     * @return xx
     */
    public Boolean exists(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.exists(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.exists(key);
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     */
    public void flushDB() {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {


                @Override
                public void action(ShardedJedis shardedJedis) {
                    for (Jedis jedis : shardedJedis.getAllShards()) {
                        jedis.flushDB();
                    }
                }
            });
        } else {
            execute(new JedisActionNoResult() {


                @Override
                public void action(Jedis jedis) {
                    jedis.flushDB();
                }
            });
        }
    }

    // ////////////// 关于String ///////////////////////////

    /**
     * 如果key不存在, 返回null.
     *
     * @param key xx
     * @return xx
     */
    public String get(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public String action(ShardedJedis jedis) {
                    return jedis.get(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public String action(Jedis jedis) {
                    return jedis.get(key);
                }
            });
        }
    }

    /**
     * @param key
     * @return
     */
    public byte[] get(final byte[] key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public byte[] action(ShardedJedis jedis) {
                    return jedis.get(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public byte[] action(Jedis jedis) {
                    return jedis.get(key);
                }
            });
        }
    }

    /**
     * 如果key不存在, 返回0.
     *
     * @param key xx
     * @return xx
     */
    public Long getAsLong(final String key) {
        String result = get(key);
        return result != null ? Long.parseLong(result) : 0;
    }

    /**
     * 如果key不存在, 返回0.
     *
     * @param key xx
     * @return xx
     */
    public Integer getAsInt(final String key) {
        String result = get(key);
        return result != null ? Integer.parseInt(result) : 0;
    }

    /**
     * 通过正则表达式获取匹配的所有keys的方法
     *
     * @param keyPattern 获取key的正则表达
     * @return 发挥key的集合
     */
    public Set keys(final String keyPattern) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public Set action(ShardedJedis shardedJedis) {
                    Object[] ary = shardedJedis.getAllShards().toArray();
                    if (ary.length > 0) {
                        return ((Jedis) ary[0]).keys(keyPattern);
                    } else {
                        return null;
                    }
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public Set action(Jedis jedis) {
                    return jedis.keys(keyPattern);
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key   xx
     * @param value xx
     */
    public void set(final String key, final String value) {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {


                @Override
                public void action(ShardedJedis jedis) {
                    jedis.set(key, value);
                }
            });
        } else {
            execute(new JedisActionNoResult() {


                @Override
                public void action(Jedis jedis) {
                    jedis.set(key, value);
                }
            });
        }
    }

    /**
     * @param key
     * @param value
     */
    public void set(final byte[] key, final byte[] value) {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {
                @Override
                public void action(ShardedJedis jedis) {
                    jedis.set(key, value);
                }
            });
        } else {
            execute(new JedisActionNoResult() {
                @Override
                public void action(Jedis jedis) {
                    jedis.set(key, value);
                }
            });
        }
    }

    /**
     * @param key
     * @param value
     */
    public void setex(final byte[] key, final int timeout, final byte[] value) {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {
                @Override
                public void action(ShardedJedis jedis) {
                    jedis.setex(key, timeout, value);
                }
            });
        } else {
            execute(new JedisActionNoResult() {
                @Override
                public void action(Jedis jedis) {
                    jedis.setex(key, timeout, value);
                }
            });
        }
    }

    public void setexObject(final String key, final int timeout, final Object value) {
        setex(key.getBytes(), timeout, SerializeUtils.serialize(value));
    }

    public void setObject(final String key, final Object value) {
        set(key.getBytes(), SerializeUtils.serialize(value));
    }

    public Object getObject(final String key) {
        byte[] bytes = get(key.getBytes());
        if (null == bytes) {
            return null;
        } else {
            return SerializeUtils.deserialize(bytes);
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key   xx
     * @param value xx
     * @param nxxx  xx
     * @param expx  xx
     * @param time  xx
     * @return xx
     */
    public String set(final String key, final String value, final String nxxx, final String expx, final int time) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public String action(ShardedJedis jedis) {
                    return jedis.set(key, value);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public String action(Jedis jedis) {
                    return jedis.set(key, value, nxxx, expx, time);
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key     xx
     * @param value   xx
     * @param seconds xx
     */
    public void setex(final String key, final String value, final int seconds) {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {


                @Override
                public void action(ShardedJedis jedis) {
                    jedis.setex(key, seconds, value);
                }
            });
        } else {
            execute(new JedisActionNoResult() {


                @Override
                public void action(Jedis jedis) {
                    jedis.setex(key, seconds, value);
                }
            });
        }
    }

    /**
     * 如果key还不存在则进行设置,返回true,否则返回false.
     *
     * @param key   xx
     * @param value xx
     * @return xx
     */
    public boolean setnx(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.setnx(key, value) == 1 ? true : false;
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.setnx(key, value) == 1 ? true : false;
                }
            });
        }
    }

    /**
     * 如果key还不存在则进行设置,并且设置超时时间,返回true,否则返回false.
     *
     * @param key
     * @param value
     * @param seconds 秒
     * @return
     */
    public boolean setnx(final String key, final String value, final int seconds) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public Boolean action(ShardedJedis jedis) {
                    Long r = jedis.setnx(key, value);
                    if (r == 1) {
                        jedis.expire(key, seconds);
                        return true;
                    } else {
                        return false;
                    }
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public Boolean action(Jedis jedis) {
                    Long r = jedis.setnx(key, value);
                    if (r == 1) {
                        jedis.expire(key, seconds);
                        return true;
                    } else {
                        return false;
                    }
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key xx
     * @return xx
     */
    public long incr(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.incr(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.incr(key);
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key xx
     * @return xx
     */
    public long decr(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.decr(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.decr(key);
                }
            });
        }
    }

    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param key   xx
     * @param value xx
     */
    // ////////////// 关于List ///////////////////////////
    public void lpush(final String key, final String value) {
        if (isSharded) {
            execute(new ShardedJedisActionNoResult() {


                @Override
                public void action(ShardedJedis jedis) {
                    jedis.lpush(key, value);
                }
            });
        } else {
            execute(new JedisActionNoResult() {


                @Override
                public void action(Jedis jedis) {
                    jedis.lpush(key, value);
                }
            });
        }
    }

    /**
     * 返回List长度, key不存在时返回0,key类型不是list时抛出异常.
     *
     * @param key xx
     * @return xx
     */
    public long llen(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.llen(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.llen(key);
                }
            });
        }
    }

    /**
     * 删除List中的第一个等于value的元素,value不存在或key不存在时返回0.
     *
     * @param key   xx
     * @param value xx
     * @return xx
     */
    public boolean lremOne(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    Long count = jedis.lrem(key, 1, value);
                    return (count == 1);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    Long count = jedis.lrem(key, 1, value);
                    return (count == 1);
                }
            });
        }
    }

    /**
     * 删除List中的所有等于value的元素,value不存在或key不存在时返回0.
     *
     * @param key   xx
     * @param value xx
     * @return xx
     */
    public boolean lremAll(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    Long count = jedis.lrem(key, 0, value);
                    return (count > 0);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    Long count = jedis.lrem(key, 0, value);
                    return (count > 0);
                }
            });
        }
    }

    // ////////////// 关于Sorted Set ///////////////////////////

    /**
     * 加入Sorted set, 如果member在Set里已存在,只更新score并返回false,否则返回true.
     *
     * @param key    xx
     * @param member xx
     * @param score  xx
     * @return xx
     */
    public boolean zadd(final String key, final String member, final double score) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.zadd(key, score, member) == 1 ? true : false;
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.zadd(key, score, member) == 1 ? true : false;
                }
            });
        }
    }

    /**
     * 获取序列中的元素
     *
     * @param key   xx
     * @param start xx
     * @param end   xx
     * @return xx
     */
    public Set zrange(final String key, final long start, final long end) {
        return execute(new JedisAction>() {

            @Override
            public Set action(Jedis jedis) {
                return jedis.zrange(key, start, end);
            }
        });
    }

    /**
     * 获取序列中的元素
     *
     * @param key   xx
     * @param start xx
     * @param end   xx
     * @return xx
     */
    public Set zrangeByScore(final String key, final long start, final long end, final int count) {
        return execute(new JedisAction>() {

            @Override
            public Set action(Jedis jedis) {
                return jedis.zrangeByScore(key, start, end, 0, count);
            }
        });
    }

    /**
     * 获取序列中的元素
     *
     * @param key   xx
     * @param start xx
     * @param end   xx
     * @return xx
     */
    public Set zrevrangeByScore(final String key, final long start, final long end, final int count) {
        return execute(new JedisAction>() {

            @Override
            public Set action(Jedis jedis) {
                return jedis.zrevrangeByScoreWithScores(key, end, start, 0, count);
            }
        });
    }

    /**
     * 删除sorted set中的元素,成功删除返回true,key或member不存在返回false。
     *
     * @param key    xx
     * @param member xx
     * @return xx
     */
    public boolean zrem(final String key, final String member) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.zrem(key, member) == 1 ? true : false;
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.zrem(key, member) == 1 ? true : false;
                }
            });
        }
    }

    /**
     * 返回List长度, key不存在时返回0,key类型不是sorted set时抛出异常.
     *
     * @param key xx
     * @return xx
     */
    public long zcard(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.zcard(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.zcard(key);
                }
            });
        }
    }

    /**
     * 设置哈希数据
     *
     * @param key   哈希key
     * @param field 哈希字段
     * @param value 哈希值
     * @return 哈希值
     */
    public long hset(final String key, final String field, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.hset(key, field, value);
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public Long action(Jedis jedis) {
                    return jedis.hset(key, field, value);
                }
            });
        }
    }

    /**
     * 设置哈希数据
     *
     * @param key   哈希key
     * @param field 哈希字段
     * @param value 哈希值
     * @return 哈希值
     */
    public long hset(final String key, final String field, final Object value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.hset(getKeyBytes(key), getKeyBytes(field), SerializeUtils.serialize(value));
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public Long action(Jedis jedis) {
                    return jedis.hset(getKeyBytes(key), getKeyBytes(field), SerializeUtils.serialize(value));
                }
            });
        }
    }

    /**
     * 设置哈希数据
     *
     * @param key  哈希key
     * @param hash 哈希值
     * @return 哈希值
     */
    public String hmset(final String key, final Map hash) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public String action(ShardedJedis jedis) {
                    return jedis.hmset(key, hash);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public String action(Jedis jedis) {
                    return jedis.hmset(key, hash);
                }
            });
        }
    }

    /**
     * 设置哈希数据
     *
     * @param key   哈希key
     * @param field 哈希字段
     * @param value 哈希值
     * @return 哈希值
     */
    public long hsetnx(final String key, final String field, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.hsetnx(key, field, value);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.hsetnx(key, field, value);
                }
            });
        }
    }

    /**
     * 获取哈希数据
     *
     * @param key   哈希key
     * @param field 哈希字段
     * @return 哈希值
     */
    public String hget(final String key, final String field) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public String action(ShardedJedis jedis) {
                    return jedis.hget(key, field);
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public String action(Jedis jedis) {
                    return jedis.hget(key, field);
                }
            });
        }
    }

    /**
     * @param key
     * @param field
     * @return
     */
    public byte[] hgetByte(final String key, final String field) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public byte[] action(ShardedJedis jedis) {
                    return jedis.hget(getKeyBytes(key), getKeyBytes(field));
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public byte[] action(Jedis jedis) {
                    return jedis.hget(getKeyBytes(key), getKeyBytes(field));
                }
            });
        }
    }

    public List hmgetByte(final String key, final String... field) {
        if (isSharded) {
            return execute(new JedisAction>() {
                @Override
                public List action(Jedis jedis) {
                    return jedis.hmget(getKeyBytes(key), getKeyBytes(field));
                }
            });
        } else {
            return execute(new JedisAction>() {
                @Override
                public List action(Jedis jedis) {
                    return jedis.hmget(getKeyBytes(key), getKeyBytes(field));
                }
            });
        }
    }

    /**
     * 批量获取Map中的值
     *
     * @param key
     * @param fields
     * @return
     */
    public List hmget(final String key, final String... fields) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {
                @Override
                public List action(ShardedJedis jedis) {
                    return jedis.hmget(key, fields);
                }
            });
        } else {
            return execute(new JedisAction>() {
                @Override
                public List action(Jedis jedis) {
                    return jedis.hmget(key, fields);
                }
            });
        }
    }

    /**
     * 获取该键对应的哈希表
     *
     * @param key 哈希key
     * @return 哈希值
     */
    public Map hgetAll(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public Map action(ShardedJedis jedis) {
                    return jedis.hgetAll(key);
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public Map action(Jedis jedis) {
                    return jedis.hgetAll(key);
                }
            });
        }
    }

    /**
     * 检查指定的哈希的键是否存在
     *
     * @param key   哈希key
     * @param field 键名
     * @return 哈希值
     */
    public Boolean hexists(final String key, final String field) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.hexists(key, field);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.hexists(key, field);
                }
            });
        }
    }

    /**
     * 删除哈希数据
     *
     * @param key   哈希key
     * @param field 哈希字段
     * @return 哈希值
     */
    public Long hdel(final String key, final String field) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.hdel(key, field);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.hdel(key, field);
                }
            });
        }
    }

    /**
     * 获取哈希数据key值集合
     *
     * @param key 哈希key
     * @return 哈希fields集合
     */
    public Set hkeys(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public Set action(ShardedJedis jedis) {
                    return jedis.hkeys(key);
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public Set action(Jedis jedis) {
                    return jedis.hkeys(key);
                }
            });
        }
    }

    /**
     * 获取哈希数据valus值集合
     *
     * @param key 哈希key
     * @return 哈希values集合
     */
    public List hvals(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public List action(ShardedJedis jedis) {
                    return jedis.hvals(key);
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public List action(Jedis jedis) {
                    return jedis.hvals(key);
                }
            });
        }
    }

    /**
     * 获取哈希数据是否存在某个键值
     *
     * @param key 哈希key
     * @return 是否存在某个键值
     */
    public boolean hasKey(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.exists(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.exists(key);
                }
            });
        }
    }

    /**
     * 哈希的所有字段值得集合
     *
     * @param key 哈希数据键
     * @return 所有字段值的集合
     */
    public List hvalue(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public List action(ShardedJedis jedis) {
                    return jedis.hvals(key);
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public List action(Jedis jedis) {
                    return jedis.hvals(key);
                }
            });
        }

    }

    /**
     * 将hash中的某个字段自增指定数量
     *
     * @param key   哈希数据键
     * @param field 字段
     * @param count 自增数量
     * @return 所有字段值的集合
     */
    public long hincrBy(final String key, final String field, final long count) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.hincrBy(key, field, count);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.hincrBy(key, field, count);
                }
            });
        }

    }

    /**
     * 将value添加到set中
     *
     * @param key   key
     * @param value value
     * @return Long
     */
    public Long sadd(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.sadd(key, value);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.sadd(key, value);
                }
            });
        }
    }

    /**
     * 返回集合 key 的基数(集合中元素的数量)。
     *
     * @param key key
     * @return Long
     */
    public Long scard(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.scard(key);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.scard(key);
                }
            });
        }
    }

    /**
     * 从取出value的set
     *
     * @param key key
     * @return Set
     */
    public Set smembers(final String key) {
        if (isSharded) {
            return execute(new ShardedJedisAction>() {


                @Override
                public Set action(ShardedJedis jedis) {
                    return jedis.smembers(key);
                }
            });
        } else {
            return execute(new JedisAction>() {


                @Override
                public Set action(Jedis jedis) {
                    return jedis.smembers(key);
                }
            });
        }

    }

    /**
     * 删除集合中某个值
     *
     * @param key   key
     * @param value value
     * @return long
     */
    public Long srem(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.srem(key, value);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.srem(key, value);
                }
            });
        }
    }

    /**
     * 删除集合中一系列值
     *
     * @param key    key
     * @param values value
     * @return long
     */
    public Long srem(final String key, final List values) {
        if (CollectionUtils.isEmpty(values)) {
            return 0L;
        }
        if (isSharded) {
            return execute((ShardedJedis jedis) -> {
                ShardedJedisPipeline pipeline = jedis.pipelined();
                for (String value : values) {
                    pipeline.srem(key, value);
                }
                pipeline.sync();
                return new Long(values.size());
            });
        } else {
            return execute((Jedis jedis) -> {
                Pipeline pipeline = jedis.pipelined();
                for (String value : values) {
                    pipeline.srem(key, value);
                }
                pipeline.sync();
                return new Long(values.size());
            });
        }
    }

    /**
     * 检查某个值是否在这个集合中
     *
     * @param key   key
     * @param value value
     * @return Boolean
     */
    public Boolean sismember(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {
                @Override
                public Boolean action(ShardedJedis jedis) {
                    return jedis.sismember(key, value);
                }
            });
        } else {
            return execute(new JedisAction() {
                @Override
                public Boolean action(Jedis jedis) {
                    return jedis.sismember(key, value);
                }
            });
        }
    }

    public Long publish(final String channel, final String data) {
        if (isSharded) {
            logger.error("Redis model unsupport subscribe");
            throw new JedisConnectionException("Redis model unsupport subscribe");
        } else {
            return execute(new JedisAction() {
                @Override
                public Long action(Jedis jedis) {
                    return jedis.publish(channel, data);
                }
            });
        }
    }

    public void subscribe(final JedisPubSub jedisPubSub, final String... channel) {
        if (isSharded) {
            logger.error("Redis model unsupport subscribe");
            throw new JedisConnectionException("Redis model unsupport subscribe");
        } else {
            execute(new JedisActionNoResult() {
                @Override
                public void action(Jedis jedis) {
                    jedis.subscribe(jedisPubSub, channel);
                }
            });
        }
    }

    /**
     * sunionstore
     *
     * @param dstkey
     * @param keys
     * @return
     */
    public Long sunionstore(final String dstkey, final String... keys) {
        if (isSharded) {
            return Long.valueOf(0);
        } else {
            return execute(new JedisAction() {

                @Override
                public Long action(Jedis jedis) {
                    return jedis.sunionstore(dstkey, keys);
                }
            });
        }
    }

    /**
     * 从尾部插入队列
     *
     * @param key   x
     * @param value x
     * @return x
     */
    public Long rpush(final String key, final String value) {
        if (isSharded) {
            return execute(new ShardedJedisAction() {


                @Override
                public Long action(ShardedJedis jedis) {
                    return jedis.rpush(key, value);
                }
            });
        } else {
            return execute(new JedisAction() {


                @Override
                public Long action(Jedis jedis) {
                    return jedis.rpush(key, value);
                }
            });
        }
    }

    /**
     * 获取byte
     *
     * @param key
     * @return
     */
    private static byte[] getKeyBytes(final String key) {
        return key.getBytes(Charset.forName("UTF-8"));
        // return SerializeUtils.serialize(key);
    }

    /**
     * 获取byte
     *
     * @param fields
     * @return
     */
    private byte[][] getKeyBytes(String... fields) {
        byte[][] bytes = new byte[fields.length][];
        for (int i = 0; i < fields.length; i++) {
            bytes[i] = null;
            String field = fields[i];
            if (null != field) {
                bytes[i] = getKeyBytes(field);
            }
        }
        return bytes;
    }
}