Spring boot+redis實現消息發佈與訂閱

一.創建spring boot項目

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>

二.編輯yml配置文件

server:
  port: 7888
# 日誌配置
logging:
  config: classpath:log/logback.xml
  level:
    cn.com.dhcc: info
    org.springframework: info
    org.springframework.web: info
    com.alibaba.nacos.client.naming: error
spring:
  redis:
     host: localhost
     port: 6379
     password: *********
     database: 1
     jedis:
      pool:
        max-idle: 8
        max-active: 8
        max-wait: -1
        min-idle: 0
     timeout: 5000

三.配置Redis

@Configuration
public class RedisConfiguration {

    /**
     * 實例化 RedisTemplate 對象
     *
     * @return
     */
    @Bean("RedisTemplateS")
    public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 設置數據存入 redis 的序列化方式,並開啓事務
     * 
     * @param redisTemplate
     * @param factory
     */
    private void initDomainRedisTemplate(@Qualifier("RedisTemplateS") RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
        // 如果不配置Serializer,那麼存儲的時候缺省使用String,如果用User類型存儲,那麼會提示錯誤User can't cast to
        // String!
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<Object>(Object.class);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        //redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        //redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        // 開啓事務
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.setConnectionFactory(factory);
    }

    /**
     * 注入封裝RedisTemplate @Title: redisUtil @return RedisUtil @date
     * 
     */
    @Bean(name = "redisUtils")
    public RedisUtils redisUtil(@Qualifier("RedisTemplateS") RedisTemplate<String, Object> redisTemplate) {
        RedisUtils redisUtil = new RedisUtils();
        redisUtil.setRedisTemplate(redisTemplate);
        return redisUtil;
    }

四.編寫RedisUtil消息發佈方法

public class RedisUtils {
    private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);

    private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void publish(String channal ,Object obj) {
        redisTemplate.convertAndSend(channal,obj );
    }
}

五.配置消息監聽

@Configuration
public class RedisMessageListener {

    /**
     * 創建連接工廠
     * @param connectionFactory
     * @param listenerAdapter
     * @return
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter,MessageListenerAdapter listenerAdapter2){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //接受消息的key
        container.addMessageListener(listenerAdapter,new PatternTopic("phone"));
        return container;
    }

    /**
     * 綁定消息監聽者和接收監聽的方法
     * @param receiver
     * @return
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(ReceiverRedisMessage  receiver){
        return new MessageListenerAdapter(receiver,"receiveMessage");
    }

    /**
     * 註冊訂閱者
     * @param latch
     * @return
     */
    @Bean
    ReceiverRedisMessage receiver(CountDownLatch latch) {
        return new ReceiverRedisMessage(latch);
    }

    /**
     * 計數器,用來控制線程
     * @return
     */
    @Bean
    public CountDownLatch latch(){
        return new CountDownLatch(1);//指定了計數的次數 1
    }
}

六.消息訂閱方法

public class ReceiverRedisMessage {

    private static final Logger log = LoggerFactory.getLogger(ReceiverRedisMessage.class);
    private CountDownLatch latch;

    @Autowired
    public ReceiverRedisMessage(CountDownLatch latch) {
        this.latch = latch;
    }

    /**
     * 隊列消息接收方法
     *
     * @param jsonMsg
     */
    public void receiveMessage(String jsonMsg) {
        log.info("[開始消費REDIS消息隊列phone數據...]");
        try {
            log.info("監聽者收到消息:{}", jsonMsg);
            JSONObject exJson = JSONObject.parseObject(jsonMsg);
            User user = JSON.toJavaObject(exJson, User.class);
            System.out.println("轉化爲對象 :"+user);
            log.info("[消費REDIS消息隊列phone數據成功.]");
        } catch (Exception e) {
            log.error("[消費REDIS消息隊列phone數據失敗,失敗信息:{}]", e.getMessage());
        }
        latch.countDown();
    }
}

七.定時消息發佈測試

@EnableScheduling
@Component
public class PublisherController {

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

    @Autowired
    private RedisUtils redisUtils;

    @Scheduled(fixedRate = 5000)
    public String pubMsg() {
        User user=new User(1, "尚***", 26,"男","陝西省xxxx市xxxxxx縣");
        redisUtils.publish("phone", user);
        log.info("Publisher sendes Topic... ");
        return "success";
    }
}

八.測試結果
Spring boot+redis實現消息發佈與訂閱

九.發佈對象User實體

public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;
    private String sex;
    private String address;
     .....................
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章