基于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 订阅与发布的 服务简单实现了。