用于排队叫号系统的redis工具类

  1. 分析

排队叫号系统的队列数据变化很频繁,因此可以考虑使用redis的list结构存储某一队列的数据,与前端采用websocekt连接,后端主动推送数据给前端,避免频繁轮询造成资源浪费。
为了满足排队系统的需求,需要设计以下几个api:

  • 入队
  • 出队
  • 获取队列数据和队长
  • 允许某人中途离队(已知其信息,从队列中剔除)
  • 允许某人插队(在目标anchor前插队还是后插队)
  • 得到某人在队列中的位置

2 redis配置和Vo类代码

yml配置

  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 3000
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0

redis配置类

@EnableCaching
@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.database}")
    private Integer database;
    @Value("${spring.redis.port}")
    private Integer port;
//  @Value("${spring.redis.password}")
//  private String pwd;

    @Primary
    @Bean(name = "jedisPoolConfig")
    @ConfigurationProperties(prefix = "spring.redis.pool")
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxWaitMillis(100000);
        return jedisPoolConfig;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setDatabase(database);
        // redisStandaloneConfiguration.setPassword(pwd);
        redisStandaloneConfiguration.setPort(port);
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        jpcb.poolConfig(jedisPoolConfig);
        JedisClientConfiguration jedisClientConfiguration = jpcb.build();
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    /**
     * 配置redisTemplate针对不同key和value场景下不同序列化的方式
     *
     * @param factory Redis连接工厂
     * @return
     */
    @Primary
    @Bean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer(PatientVo.class);
        template.setValueSerializer(redisSerializer);
        template.setHashValueSerializer(redisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

vo类代码:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PatientVo {
    private Long patientId;
    private Integer queueNum;
    private String patientName;
    private String patientGender;
}
  1. redis排队工具类

这里写的不好的地方在于没有判断捕获异常。

@Component
public class QueueUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 入队
     * @param roomCode 诊室编码
     * @param vo 病人vo对象
     */
    public  void addPatient2Queue(String roomCode, PatientVo vo) {
        redisTemplate.opsForList().rightPush(roomCode, vo);
    }

    /**
     * 队长
     * @param roomCode 诊室编码
     * @return Long长度
     */
    public  Long getQueueLength(String roomCode) {
        return redisTemplate.opsForList().size(roomCode);
    }

    // 获取队列数据
    public List getQueueData(String roomCode) {
        return redisTemplate.opsForList().range(roomCode, 0, -1);
    }

    // 某人中途离开队伍
    public  void leaveQueue(String roomCode, PatientVo patientVo) {
        redisTemplate.opsForList().remove(roomCode, 0, patientVo);
    }

    // 队首离队
    public  PatientVo headLeaveQueue(String roomCode) {
        PatientVo leftPop = redisTemplate.opsForList().leftPop(roomCode);
        return leftPop;
    }

    // 得到某人队列中的位置
    public  List getOnesPosition(String roomCode, PatientVo patientVo) {
        List queueData = getQueueData(roomCode);
        int myPositionBeforeNum = queueData.indexOf(patientVo);
        int myPosition = myPositionBeforeNum + 1;
        int size = queueData.size();
        // 当前排队res[0]人,您排在第res[1]位,前面还有res[2]位。
        List result = new ArrayList<>();
        result.add(size);
        result.add(myPosition);
        result.add(myPositionBeforeNum);
        return result;
    }

    // 插队操作
    public  void jumpAQueue(String roomCode, PatientVo jumpChecker, PatientVo targetChecker, Integer jumpType) {
        // 在target前面插队
        if (jumpType.equals(1)) {
            redisTemplate.opsForList().leftPush(roomCode, targetChecker, jumpChecker);
        }
        if (jumpType.equals(2)) {
            redisTemplate.opsForList().rightPush(roomCode, targetChecker, jumpChecker);
        }
    }
}
  1. 简单测试

测试代码

@Autowired
    private QueueUtil queueUtil;

    @GetMapping("/test/qu")
    private Result testQueueUtil() {
        long start = System.currentTimeMillis();
        List list = patientInfoService.list();
        for (int i = 0; i < 10; i++) {
            PatientInfo info = list.get(i);
            PatientVo vo = new PatientVo(info.getPatientId(),
                    info.getQueueNum(),
                    info.getPatientName(),
                    info.getPatientSex());
            queueUtil.addPatient2Queue("test", vo);
        }
        List queueData = queueUtil.getQueueData("test");
//      PatientVo jumpVo = new PatientVo(1999L, 2999, "test", "test");
//      PatientVo targetVo = new PatientVo(1058L, 2005, "冯秀娟", "女");
//      queueUtil.jumpAQueue("test", jumpVo, targetVo, 2);
//      List queueData = queueUtil.getQueueData("test");
        long end = System.currentTimeMillis();
        log.info("waste time: {}s", (float)(end - start) / 1000);
        return Result.success(queueData);
    }

测试结果图1:

用于排队叫号系统的redis工具类
测试结果图2:
用于排队叫号系统的redis工具类
然后测试一下插队功能,在冯秀娟后面插入test
查看RedisManager里的结果:
用于排队叫号系统的redis工具类
test成功插队。

Original: https://www.cnblogs.com/ceeSomething8/p/15935420.html
Author: cee_nil
Title: 用于排队叫号系统的redis工具类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/710798/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球