content: package com.cn.xmf.service.redis;
  
  import com.alibaba.fastjson.JSON;
  import com.alibaba.fastjson.JSONObject;
  import com.cn.xmf.util.StringUtil;
  import org.apache.commons.httpclient.util.DateUtil;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.data.redis.connection.RedisConnection;
  import org.springframework.data.redis.connection.RedisStringCommands;
  import org.springframework.data.redis.connection.ReturnType;
  import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  import org.springframework.data.redis.core.RedisTemplate;
  import org.springframework.data.redis.core.types.Expiration;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RestController;
  
  import java.nio.charset.Charset;
  import java.util.Date;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.Set;
  import java.util.concurrent.locks.ReentrantLock;
  
  @SuppressWarnings("all")
  @RestController
  @RequestMapping("/server/redis/")
  public class RedisService {
  
      private static Logger logger = LoggerFactory.getLogger(RedisService.class);
      private static final String UNLOCK_LUA;//释放锁的命令
      private final ReentrantLock lock = new ReentrantLock();
      static {
          StringBuilder sb = new StringBuilder();
          sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
          sb.append("then ");
          sb.append("    return redis.call(\"del\",KEYS[1]) ");
          sb.append("else ");
          sb.append("    return 0 ");
          sb.append("end ");
          UNLOCK_LUA = sb.toString();
      }
  
      @Autowired
      private RedisTemplate redisTemplate;
  
      /**
       * 获取链接信息
       *
       * @return
       */
      public RedisConnection getRedisConnection() {
          RedisConnection connection = null;
          try {
              connection = redisTemplate.getConnectionFactory().getConnection();
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          return connection;
      }
  
      /**
       * getRedisInfo（redis 运行健康信息)
       *
       * @param key
       * @return
       */
      @RequestMapping("getRedisInfo")
      public JSONObject getRedisInfo() {
          logger.info("getRedisInfo（redis 运行健康信息) 开始 ");
          JSONObject result = new JSONObject();
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          boolean broken = false;
          try {
              Hashtable info = conn.info();
              if (info == null) {
                  return result;
              }
              String jsonString = JSON.toJSONString(info);
              if (StringUtil.isBlank(jsonString)) {
                  return result;
              }
              result.put("info", jsonString);
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          logger.info("getRedisInfo（redis 运行健康信息)redis 结束 " + result);
          return result;
      }
  
      /**
       * getQueueLength（获取队列长度)key 是消息频道
       *
       * @param key
       * @return
       */
      @RequestMapping("getQueueLength")
      public Long getQueueLength(String key) {
          logger.info("getQueueLength（获取队列长度) 开始 " + key);
          Long result = (long) -1;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          boolean broken = false;
          try {
              result = conn.lLen(key.getBytes());
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          logger.info("getQueueLength（获取队列长度)redis 结束 " + result);
          return result;
      }
  
      /**
       * putToQueue（写入消息队列）入队key 是消息频道 ，value 消息内容
       *
       * @param key
       * @param value
       * @return
       */
      @RequestMapping("putToQueue")
      public Long putToQueue(final String key, final String value) {
          logger.info("putToQueue（写入消息队列）redis 开始 " + key + " value:" + value);
          Long result = (long) -1;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          if (StringUtil.isBlank(value)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          boolean broken = false;
          try {
              result = conn.lPush(key.getBytes(), value.getBytes());
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
              broken = true;
          }
          logger.info("putToQueue（写入消息队列）redis 结束 " + result);
          return result;
      }
  
      /**
       * getFromQueue（读取队列消息） （读过队列中消息就没有了）key 是消息频道
       *
       * @param key
       * @return
       */
      @RequestMapping("getFromQueue")
      public String getFromQueue(final String key) {
          logger.info("getFromQueue（读取队列消息）redis 开始 " + key);
          String result = null;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              byte[] bytes = conn.rPop(key.getBytes());
              if (bytes != null) {
                  result = new String(bytes, "utf-8");
              }
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          logger.info("getFromQueue（读取队列消息）redis 结束 " + result);
          return result;
      }
  
  
      /**
       * getCache（获取缓存数据）
       *
       * @param key
       * @return
       */
      @RequestMapping("getCache")
      public String getCache(String key) {
          logger.info("getCache（获取缓存数据）redis 开始 " + key);
          String result = null;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              byte[] bytes = conn.get(key.getBytes());
              if (bytes != null) {
                  result = new String(bytes, "utf-8");
              }
          } catch (Exception e) {
              logger.error("getCache:" + StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * 判断key是否存在
       *
       * @param key
       * @return
       */
      @RequestMapping("exists")
      public Boolean exists(String key) {
          Boolean result = false;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              result = conn.exists(key.getBytes());
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * 在某段时间后失效
       *
       * @param key
       * @param unixTime
       * @return
       */
      @RequestMapping("expire")
      public Long expire(String key, long seconds) {
          Long result = (long) -1;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              boolean ret = conn.expire(key.getBytes(), seconds);
              if (ret) {
                  result = (long) 1;
              }
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * saveCache:(设置缓存-带有效期)
       *
       * @param key
       * @param value
       * @param seconds 有效时间 单位（秒）
       * @return
       * @author rufei.cn
       */
      @RequestMapping("save")
      public long saveCache(String key, String value, long seconds) {
          logger.info("save:(设置缓存-带有效期) 开始 key={},seconds={}", key, seconds);
          long result = -1;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              Boolean ret = conn.set(key.getBytes(), value.getBytes(), Expiration.seconds(seconds), RedisStringCommands.SetOption.UPSERT);
              if (ret) {
                  result = 1L;
              }
          } catch (Exception e) {
              logger.error("saveCache:" + StringUtil.getExceptionMsg(e));
          }
          logger.info("saveCache:(设置缓存-带有效期) 结束 key={},result={}", key, result);
          return result;
      }
  
      /**
       * delete（将 key 缓存数据删除）
       *
       * @param key
       * @return
       */
      @RequestMapping("delete")
      public Long delete(String key) {
          logger.info("delete（将 key 缓存数据删除） 开始 key={}", key);
          Long result = null;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              result = conn.del(key.getBytes());
          } catch (Exception e) {
              logger.error("delete_error:" + StringUtil.getExceptionMsg(e));
          }
          logger.info("delete（将 key 缓存数据删除）结束 key={},result={}", key, result);
          return result;
      }
  
      /**
       * 将 key 中储存的数字值减一
       *
       * @param key
       * @return
       */
      @RequestMapping("decr")
      public Long decr(String key) {
          Long result = null;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              result = conn.decr(key.getBytes());
          } catch (Exception e) {
              logger.error("decr_error:" + StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * 将 key 中储存的数字值加N
       *
       * @param key
       * @param integer
       * @return
       */
      @RequestMapping("incrBy")
      public Long incrBy(String key, long integer) {
          Long result = null;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              result = conn.incrBy(key.getBytes(), integer);
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
  
      /**
       * 根据通配符删除所有key
       *
       * @param key
       * @param integer
       * @return
       */
      @RequestMapping("delCaches")
      public long delCaches(String pattern) {
          long result = -1;
          if (StringUtil.isBlank(pattern)) {
              return result;
          }
          if ("*".equals(pattern)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              Set<byte[]> list = getKeyList(pattern);
              if (list == null || list.size() < 1) {
                  return result;
              }
              Iterator<byte[]> iterator = list.iterator();
              while (iterator.hasNext()) {
                  if (iterator.next() == null) {
                      continue;
                  }
                  String next = new String(iterator.next(), "utf-8");
                  if (StringUtil.isBlank(next)) {
                      continue;
                  }
                  delete(next);
              }
              result = 1;
          } catch (Exception e) {
              logger.error("delCaches:" + StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * 根据通配符获取key集合
       *
       * @param key
       * @param integer
       * @return
       */
      @RequestMapping("getKeyList")
      public Set<byte[]> getKeyList(String pattern) {
          Set<byte[]> result = null;
          if (StringUtil.isBlank(pattern)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              Set<byte[]> keys = conn.keys(pattern.getBytes());
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * getLock（分布式锁-正确方式）
       *
       * @param key        锁标识
       * @param requestId  请求唯一标识，解锁需要带入
       * @param expireTime 自动释放锁的时间
       */
      @RequestMapping("getLock")
      public Long getLock(String key, String requestId, long expireTime) {
          Long result = -1L;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          if (StringUtil.isBlank(requestId)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          try {
              boolean ret = conn.set(key.getBytes(Charset.forName("UTF-8")), requestId.getBytes(Charset.forName("UTF-8")), Expiration.milliseconds(expireTime), RedisStringCommands.SetOption.SET_IF_ABSENT);
              if (ret) {
                  result = 1L;
              }
          } catch (Exception e) {
              logger.error("getRedisLock（取分布式锁-正确方式）异常={}", StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * unRedisLock（释放分布式锁）
       *
       * @param key       锁
       * @param requestId 请求唯一标识，解锁需要带入
       * @return 是否释放成功
       */
      @RequestMapping("unRedisLock")
      public int unRedisLock(String key, String requestId) {
          int result = -1;
          if (StringUtil.isBlank(key)) {
              return result;
          }
          if (StringUtil.isBlank(requestId)) {
              return result;
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return result;
          }
          // 释放锁的时候，有可能因为持锁之后方法执行时间大于锁的有效期，此时有可能已经被另外一个线程持有锁，所以不能直接删除
          try {
              boolean ret = conn.eval(UNLOCK_LUA.getBytes(), ReturnType.BOOLEAN, 1, key.getBytes(Charset.forName("UTF-8")), requestId.getBytes(Charset.forName("UTF-8")));
              if (ret) {
                  result = 1;
              }
          } catch (Exception e) {
              logger.error("unRedisLock（释放分布式锁）异常={}", StringUtil.getExceptionMsg(e));
          }
          return result;
      }
  
      /**
       * getOnlyNo(获取唯一编号)
       *
       * @param type
       * @return
       */
      @RequestMapping("getOnlyNo")
      public String getOnlyNo(String prefix) {
          logger.info("getOnlyNo(获取唯一编号) 开始：" + prefix);
          String onlyNo = null;
          if (StringUtil.isBlank(prefix)) {
              return onlyNo;
          }
          String key = DateUtil.formatDate(new Date(), "yyyyMMdd");
          if (!exists(key)) {
              saveCache(key, "100000", 60 * 60 * 24);
          }
          RedisConnection conn = getRedisConnection();
          if (conn == null) {
              return onlyNo;
          }
          long number = -1;
          try {
              number = conn.incr(key.getBytes());
          } catch (Exception e) {
              logger.error(StringUtil.getExceptionMsg(e));
          }
          onlyNo = prefix + DateUtil.formatDate(new Date(), "yyyyMMddHHmmss") + number;
          logger.info("getOnlyNo(获取唯一编号) 结束  ：" + onlyNo);
          return onlyNo;
      }
  
  }
  