1.redis的發佈訂閱功能,很簡單。
消息發佈者和消息訂閱者互相不認得,也不關心對方有誰。
消息發佈者,將消息發送給頻道(channel)。
而後是由 頻道(channel)將消息發送給對本身感興趣的 消息訂閱者們,進行消費。redis
2.redis的發佈訂閱和專業的MQ相比較spring
1>redis的發佈訂閱只是最基本的功能,不支持持久化,消息發佈者將消息發送給頻道。若是沒有訂閱者消費,消息就丟失了。
2>在消息發佈過程當中,若是客戶端和服務器鏈接超時,MQ會有重試機制,事務回滾等。可是Redis沒有提供消息傳輸保障。
3>簡單的發佈訂閱可使用redis,根據業務需求選擇。apache
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<!-- 使用redis的LUA腳本 須要序列化操做的jar-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
爲redis添加消息適配器,綁定消息處理器服務器
消息適配器 能夠添加多個 app
package com.sxd.swapping.config; import com.sxd.swapping.redisReceiver.RedisReceiver; import com.sxd.swapping.redisReceiver.RedisReceiver2; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @author sxd * @date 2019/5/27 16:13 */ @Configuration @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfig { /** * redis消息監聽器容器 * 能夠添加多個監聽不一樣話題的redis監聽器,只須要把消息監聽器和相應的消息訂閱處理器綁定,該消息監聽器 * 經過反射技術調用消息訂閱處理器的相關方法進行一些業務處理 * @param connectionFactory * @param listenerAdapter * @return
*/ @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter, MessageListenerAdapter listenerAdapter2) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); //能夠添加多個 messageListener //能夠對 messageListener對應的適配器listenerAdapter 指定本適配器 適配的消息類型 是什麼 //在發佈的地方 對應發佈的redisTemplate.convertAndSend("user",msg); 那這邊的就對應的能夠消費到指定類型的 訂閱消息
container.addMessageListener(listenerAdapter, new PatternTopic("user")); container.addMessageListener(listenerAdapter2, new PatternTopic("goods")); return container; } /** * 消息監聽器適配器,綁定消息處理器,利用反射技術調用消息處理器的業務方法 * * receiveMessage 是默認監聽方法 通常不變 * @param redisReceiver redis消息處理器,自定義的 * @return
*/ @Bean MessageListenerAdapter listenerAdapter(RedisReceiver redisReceiver) { System.out.println("消息適配器1進來了"); return new MessageListenerAdapter(redisReceiver, "receiveMessage"); } /** * 消息監聽器適配器,綁定消息處理器,利用反射技術調用消息處理器的業務方法 * * receiveMessage 是默認監聽方法 通常不變 * @param redisReceiver2 redis消息處理器,自定義的 * @return
*/ @Bean MessageListenerAdapter listenerAdapter2(RedisReceiver2 redisReceiver2) { System.out.println("消息適配器2進來了"); return new MessageListenerAdapter(redisReceiver2, "receiveMessage"); } //使用默認的工廠初始化redis操做模板
@Bean StringRedisTemplate template(RedisConnectionFactory connectionFactory) { return new StringRedisTemplate(connectionFactory); } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(factory); RedisSerializer keySerializer = new StringRedisSerializer(); // RedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer(); //key採用字符串反序列化對象
redisTemplate.setKeySerializer(keySerializer); //value也採用字符串反序列化對象 //緣由:管道操做,是對redis命令的批量操做,各個命令返回結果可能類型不一樣 //多是 Boolean類型 多是String類型 多是byte[]類型 所以統一將結果按照String處理
redisTemplate.setValueSerializer(keySerializer); return redisTemplate; } }
package com.sxd.swapping.redisReceiver; import org.springframework.stereotype.Service; /** * * redis 訂閱發佈 消息接收器/處理器 * @author sxd * @date 2019/5/30 17:12 */ @Service public class RedisReceiver { public void receiveMessage(String message) { System.out.println("消息處理器1>我處理用戶信息:"+message); //這裏是收到通道的消息以後執行的方法 //此處執行接收到消息後的 業務邏輯
} }
package com.sxd.swapping.redisReceiver; import org.springframework.stereotype.Service; /** * redis 訂閱發佈 消息接收器/處理器2 * @author sxd * @date 2019/5/30 17:15 */ @Service public class RedisReceiver2 { public void receiveMessage(String message) { System.out.println("消息處理器2>我處理商品信息:"+message); //這裏是收到通道的消息以後執行的方法 //此處執行接收到消息後的 業務邏輯
} }
@Autowired RedisTemplate redisTemplate; /** * redis 發佈訂閱pubsub */ @RequestMapping(value = "/redisPubSub") public void redisPubSub(String msg){ if (msg.contains("用戶")){ redisTemplate.convertAndSend("user",msg); }else { redisTemplate.convertAndSend("goods",msg); } }
測試:ide
發送請求:http://localhost:9666/redistest/redisPubSub?msg=用戶---德瑪西亞的用戶spring-boot
結果:測試
消息處理器1>我處理用戶信息:用戶---德瑪西亞的用戶spa
發送請求:http://localhost:9666/redistest/redisPubSub?msg=goods---德瑪西亞的用商品3d
結果:
消息處理器2>我處理商品信息:goods---德瑪西亞的用商品