redis 消息订阅 java_基于Redis 实现的消息发布与订阅

该博客介绍了如何基于Redis实现消息中间件,通过枚举定义消息通道,配置Redis监听器,创建消息的生产者和消费者。在Spring Boot 2.1.x项目中,利用StringRedisTemplate发送和接收消息,结合ThreadPoolExecutor处理并发。当接收到消息时,通过反射调用处理方法,并使用DingDingMsgSendUtils发送钉钉群消息。
摘要由CSDN通过智能技术生成

基于redis 的实现的 消息中间件代码:

小弟最近在维护一个 代码内异常发送dingding消息的功能。觉得redis消息中间件还是挺好用的。于是赶紧记下来;

redis发布消息时基于通道的概念。所以 先定义好一个通道,比如有个枚举

public enum RedisMsgEnum {

SEND_MSG_CHNNEL("CHANNEL_CASE_MSG", "REDIS CHANNEL专用");

private String channel;

private String name;

RedisMsgEnum(String channel, String name) {

this.channel = channel;

this.name = name;

}

public String getChannel() {

return channel;

}

public void setChannel(String channel) {

this.channel = channel;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

由于是基于boot 2.1.X 项目,所以要先初始化 redis消息监听器

@Configuration

public class RedisSubListenerConfig {

//初始化监听器

@Bean

RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,

MessageListenerAdapter listenerAdapter) {

RedisMessageListenerContainer container = new RedisMessageListenerContainer();

container.setConnectionFactory(connectionFactory);

container.addMessageListener(listenerAdapter, new PatternTopic(RedisMsgEnum.SEND_MSG_CHNNEL.getChannel()));

return container;

}

//利用反射来创建监听到消息之后的执行方法

@Bean

MessageListenerAdapter listenerAdapter(RedisConsumer redisReceiver) {

return new MessageListenerAdapter(redisReceiver, "receiveMessage");

}

//使用默认的工厂初始化redis操作模板

@Bean

StringRedisTemplate template(RedisConnectionFactory connectionFactory) {

return new StringRedisTemplate(connectionFactory);

}

}

这样redis 就完成了基本配置,现在写类似MQ 的 生产者和消费者:

生产者:

@Service

public class RedisSender {

private static final Logger logger = LoggerFactory.getLogger(RedisSender.class);

@Autowired

private StringRedisTemplate stringRedisTemplate;

//向通道发送消息的方法

public void sendChannelMess(String channel, String message) {

stringRedisTemplate.convertAndSend(channel, message);

}

}

消费者:

@Service

public class RedisConsumer {

private static final Logger logger = LoggerFactory.getLogger(RedisConsumer.class);

private static final String PROD_ENVIRONMENT = "prod";

private static final String HUIDU_ENVIRONMENT = "huidu";

public void receiveMessage(String message) {

//收到通道的消息之后执行业务

DingDingMsgSendUtils.sendDingDingGroupMsg(

DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(),

"【kashtrees-app-进件超时-"+ SpringContextUtil.getActiveProfile()+"-环境】异常,用户id:"+message,

DingMsgPhoneEnum.DEVELOPER_PHONE_yansf.getPhone());

}

}

发送入口:

private static int corePoolSize = Runtime.getRuntime().availableProcessors();

//调整队列数 拒绝服务

private static ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,

new LinkedBlockingQueue(10000));

private void sendChannelMess(RiskUserInfoParamVo riskUserInfoParamVo) {

Runnable task = new Runnable() {

@Override

public void run() {

//思考如何返回给用户信息ws

redisSender.sendChannelMess(RedisMsgEnum.SEND_MSG_CHNNEL.getChannel(),// 通道

riskUserInfoParamVo.getUserId()+"");

}

};

executor.execute(task);

}

钉钉发送工具类:

public class DingDingMsgSendUtils {

private static final Logger logger = LoggerFactory.getLogger(DingDingMsgSendUtils.class);

/**

* 处理发送的钉钉消息

*

* @param accessToken

* @param textMsg

*/

private static void dealDingDingMsgSendTest(String accessToken, String textMsg) {

HttpClient httpclient = HttpClients.createDefault();

String WEBHOOK_TOKEN = "https://oapi.dingtalk.com/robot/send?access_token=" + accessToken;

HttpPost httppost = new HttpPost(WEBHOOK_TOKEN);

httppost.addHeader("Content-Type", "application/json; charset=utf-8");

StringEntity se = new StringEntity(textMsg, "utf-8");

httppost.setEntity(se);

try {

org.apache.http.HttpResponse response = httpclient.execute(httppost);

if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

String result = EntityUtils.toString(

response.getEntity(), "utf-8");

System.out.println("【发送钉钉群消息】消息响应结果:"

+ JSON.toJSONString(result));

}

} catch (Exception e) {

System.out.println("【发送钉钉群消息】error:" + e.getMessage()+e);

}

}

/**

* 发送钉钉群消息

*

* @param accessToken

* @param content

*/

public static void sendDingDingGroupMsgTest(String accessToken, String content) {

String textMsg = "{ \"msgtype\": \"text\", \"text\": {\"content\": \"" + content + "\"}}";

dealDingDingMsgSend(accessToken, textMsg);

}

/**

* 发送钉钉群消息(可以艾特人)

*

* @param accessToken 群机器人accessToken

* @param content 发送内容

* @param atPhone 艾特人电话,如:176********,156********,

*/

public static void sendDingDingGroupMsgTest(String accessToken, String content, String atPhone) {

content = content.replace("\"", "'");

String textMsg = "";

// String textMsg = "{\n" +

// " \"msgtype\": \"text\", \n" +

// " \"text\": {\n" +

// " \"content\": \"" + content + "\"\n" +

// " }, \n" +

// " \"at\": {\n" +

// " \"atMobiles\": [\n" +

// " " + atPhone +

// " ], \n" +

// " \"isAtAll\": false\n" +

// " }\n" +

// "}";

MsgDto msgDto = new MsgDto();

msgDto.setMsgtype("text");

TextDto textDto = new TextDto();

textDto.setContent(content);

msgDto.setText(textDto);

AtDto atDto = new AtDto();

atDto.setIsAtAll(false);

List result = Arrays.asList(atPhone.split(","));

atDto.setAtMobiles(result);

msgDto.setAt(atDto);

textMsg = JSONSerializer.toJSON(msgDto).toString();

System.out.println(textMsg);

dealDingDingMsgSend(accessToken, textMsg);

}

//@Value("${spring.profiles.active}")

//private String profile;

public static void main(String[] args) {

try {

int s = Integer.parseInt("df12");

// System.out.println(1 / 0);

} catch (Exception e) {

e.printStackTrace();

//System.out.println("11"+e.getStackTrace().);

StringBuffer sb=new StringBuffer();

for(StackTraceElement elem : e.getStackTrace()) {

sb.append(elem+">>>>>>>>>>>>>>>>>>>>");

}

System.out.println(sb.toString());

sendDingDingGroupMsg(

DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(),

"【JAVA系统消息】钉钉消息推送测试,by:..."

//+e.printStackTrace();

//+ e.getMessage(),

+"环境,异常:"+sb.toString(),

DingMsgPhoneEnum.DEVELOPER_PHONE_yansf.getPhone());

}

//异常捕获

/*try{

//todo

} catch (Exception ex) {

DingDingMsgSendUtils.sendDingDingGroupMsg(DingTokenEnum

.SEND_SMS_BY_DEVELOPER_TOKEN.getToken()

, "***异常,"

//+ profile

+ "环境,errorMsg=" + ex,

DingMsgPhoneEnum.DEVELOPER_PHONE_yansf.getPhone());

}*/

}

/**

* 发送钉钉群消息(可以艾特人)

*

* @param accessToken 群机器人accessToken

* @param content 发送内容

* @param atPhone 艾特人电话,如:176********,156********,

*/

public static void sendDingDingGroupMsg(String accessToken, String content, String atPhone) {

content = content.replace("\"", "'");

String textMsg = "";

MsgDto msgDto = new MsgDto();

msgDto.setMsgtype("text");

TextDto textDto = new TextDto();

textDto.setContent(content);

msgDto.setText(textDto);

AtDto atDto = new AtDto();

atDto.setIsAtAll(false);

List result = Arrays.asList(atPhone.split(","));

atDto.setAtMobiles(result);

msgDto.setAt(atDto);

textMsg = JSONSerializer.toJSON(msgDto).toString();

logger.error("textMsg:",textMsg);

dealDingDingMsgSend(accessToken, textMsg);

}

/**

* 处理发送的钉钉消息

*

* @param accessToken

* @param textMsg

*/

private static void dealDingDingMsgSend(String accessToken, String textMsg) {

HttpClient httpclient = HttpClients.createDefault();

String WEBHOOK_TOKEN = "https://oapi.dingtalk.com/robot/send?access_token="+accessToken ;

HttpPost httppost = new HttpPost(WEBHOOK_TOKEN);

httppost.addHeader("Content-Type", "application/json; charset=utf-8");

StringEntity se = new StringEntity(textMsg, "utf-8");

httppost.setEntity(se);

try {

org.apache.http.HttpResponse response = httpclient.execute(httppost);

if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

String result = EntityUtils.toString(

response.getEntity(), "utf-8");

logger.error("【发送钉钉群消息】消息响应结果:"

+ JSON.toJSONString(result));

}

} catch (Exception e) {

logger.error("【发送钉钉群消息】error:" + e.getMessage()+e);

}

}

}

当然啦。需要先获取钉钉的token 这个就不提供了。

以上就是完整的  基于redis 订阅与发布的 服务简单实现了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值