1. 消息对象定义

1.1 通用消息对象定义

package com.yj.notice.message;

import com.yj.commons.tools.utils.DateUtils;

import com.yj.commons.tools.utils.StringUtil;

import com.yj.notice.costant.NoticeMethodEnum;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

import java.util.Date;/**

* @author : dyg

* @className : SmsMessageDTO

* @description : SMS短信平台 实体类

* @date : 2023/8/30 10:35

*/

@AllArgsConstructor

@NoArgsConstructor

@Builder

@Data

public class NoticeMessage implements Serializable {

private static final long serialVersionUID = 5081758462088563857L; /** * 消息类型 **/ private String messageType;

/**

* 通知消息类型

*/

protected NoticeMethodEnum noticeMethod;

/**

* 接收者-手机号码

*/

protected String receiverPhone;

protected String receiverId;

/**

* 接收者-用户名

*/

protected String receiverUserName;

/**

* 消息内容

*/

protected String content;

/**

* 消息内容

*/

protected String title;

/**

* 消息时间

*/

protected String time;

/**

* 发送结果

*/

protected String result;

/**

* 错误信息

*/

protected String error;

public String wrapperMessage() {

StringBuilder sub = new StringBuilder();

String time = StringUtil.isEmpty(this.getTime()) ? format(new Date(),"yyyy-MM-dd HH:mm:ss") : this.getTime();

sub.append("消息标题: ").append(this.getTitle()).append("\n" )

.append("消息内容: ").append(this.getContent()).append("\n")

.append("消息时间: ").append(time).append("\n" );

return sub.toString();

}

public static String format(Date date, String pattern) { if (date != null) { SimpleDateFormat df = new SimpleDateFormat(pattern); return df.format(date); } return null; }

}

1.2 告警消息对象定义

package com.yj.notice.message;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

/**

* @author : dyg

* @className : AlarmMessage

* @description : 告警信息

* @date : 2023/9/5 11:19

*/

@Data

@AllArgsConstructor

@NoArgsConstructor

public class AlarmMessage extends NoticeMessage implements Serializable {

private static final long serialVersionUID = -8390792683552907827L;

/**

* 告警级别

*/

protected String level;

/**

* 告警类型

*/

protected String type;

/**

* 告警备注

*/

protected String remark;

public String wrapperMessage() {

if(StringUtil.isEmpty(this.getTime()) && StringUtil.isEmpty(this.getLevel()) && StringUtil.isEmpty(this.getType())&& StringUtil.isEmpty(this.getRemark())) {

return this.getContent();

}

StringBuilder sub = new StringBuilder();

sub.append("告警时间: ").append(this.getTime()).append("\n")

.append("告警级别: ").append(this.getLevel()).append("\n")

.append("告警类别: ").append(this.getType()).append("\n")

.append("告警消息: ").append(this.getContent()).append("\n")

.append("备注信息: ").append(this.getRemark());

return sub.toString();

}

}

1.3 邮件消息对象定义

package com.yj.notice.message;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.File;

import java.io.Serializable;

/**

* @author : dyg

* @className : MailMessage

* @description : 描述说明该类的功能

* @date : 2023/9/5 14:33

*/

@Data

@AllArgsConstructor

@NoArgsConstructor

public class MailMessage extends AlarmMessage implements Serializable {

private static final long serialVersionUID = 4370431527898082801L;

/**

* 附件

*/

private File attachFile;

/**

* html内容

*/

private String html;

}

1.4 消息发送类型枚举定义

package com.yj.notice.costant;

import lombok.AllArgsConstructor;

import lombok.Getter;

/**

* 通知方式

*

* @author changXT

* @date 2022-8-10

**/

@AllArgsConstructor

@Getter

public enum NoticeMethodEnum {

WECHAT("微信", "WECHAT"),

EMAIL("邮件", "EMAIL"),

TENCENT_SMS("腾讯短信", "TENCENT_SMS"),

IN_MSG("站内消息", "IN_MSG"),

DINGTALK("钉钉", "DINGTALK");

private String cnName;

private String name;

public static NoticeMethodEnum getEnum(String name) {

for (NoticeMethodEnum noticeMethodEnum : NoticeMethodEnum.values()) {

if (name.equals(noticeMethodEnum.name())) {

return noticeMethodEnum;

}

}

return null;

}

}

2. 消息发送接口定义

2.1 消息发送接口定义

package com.yj.notice.service;

import com.yj.notice.MessageSenderManager;

import com.yj.notice.message.NoticeMessage;

import org.springframework.beans.factory.InitializingBean;

/**

* @author : dyg

* @className : MessageService

* @description : 消息发送

* @date : 2023/8/30 10:34

*/

public interface MessageService extends InitializingBean {

/**

* 发送消息

* @param message

* @return

*/

String send(NoticeMessage message);

/**

* 获取发送方法

*

* @return 发送方法

*/

String getNoticeMethod();

@Override

default void afterPropertiesSet() {

MessageSenderManager.registrySender(getNoticeMethod(), this);

}

}

2.2 消息发送收集器定义

package com.yj.notice;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.service.MessageService;

import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

/**

* 消息发送者管理器

*

* @author donglanlan

* @date 2021/7/22 2:33 下午

**/

@Component

public class MessageSenderManager {

private static final ConcurrentHashMap> SENDER_MAP =

new ConcurrentHashMap<>();

public static void registrySender(String sendMethod, MessageService messageSender) {

SENDER_MAP.put(sendMethod, messageSender);

}

public MessageService getMessageSender(NoticeMessage messsage) {

if (messsage.getNoticeMethod() == null) {

throw new RuntimeException("没有指定消息的发送方式!");

}

return getMessageSender(messsage.getNoticeMethod());

}

public MessageService getMessageSender(NoticeMethodEnum methodEnum) {

return SENDER_MAP.get(methodEnum.getName());

}

}

3. 微信公众号消息发送实现类

3.1 实现类定义

package com.yj.notice.service.impl;

import cn.hutool.http.HttpUtil;

import com.alibaba.fastjson.JSONObject;

import com.yj.commons.tools.utils.DateUtils;

import com.yj.commons.tools.utils.JsonUtil;

import com.yj.commons.tools.utils.StringUtil;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.message.AlarmMessage;

import com.yj.notice.service.MessageService;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.entity.StringEntity;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.http.ResponseEntity;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import java.io.IOException;

import java.util.*;

import static com.yj.commons.tools.utils.DateUtils.DATE_TIME_PATTERN;

/**

* @author : dyg

* @className : WxMessageServiceImpl

* @description : 描述说明该类的功能

* @date : 2023/9/5 9:35

*/

@Service("WechatMessageService")

@Slf4j

@Data

public class WechatMessageServiceImpl implements MessageService {

/**

* 账号app_id

*/

@Value(value = "${notice.wechat.bk_app_id}")

private String bkAppKey;

/**

* 账户密钥

*/

@Value(value = "${notice.wechat.bk_app_secret}")

private String bkAppSecret;

/**

* 告警消息模板id

*/

@Value(value = "${notice.wechat.alarm_template_id}")

private String alarmTemplateId;

/**

* 普通消息模板id

*/

@Value(value = "${notice.wechat.common_template_id}")

private String commonTemplateId;

/**

* 获取token

* "+ appId +"&secret=" + appIdSecret

*/

@Value(value = "${notice.wechat.token_uri}")

private String tokenUri;

/**

* + accessToken;

*/

@Value(value = "${notice.wechat.user_list_uri}")

private String userListUri;

/**

* + accessToken;

*/

@Value(value = "${notice.wechat.send_message_uri}")

private String sendMessageUri;

@Autowired

RestTemplate restTemplate;

/**

* 用户token

*/

private String enterpriseToken = null;

private Long tokenFreshTimeSt = 0L;

@Override

public String send(NoticeMessage message) {

String result = null;

try {

result = this.sendMessage(message);

}catch (Exception e){

log.error(e.getMessage());

result = e.getMessage()+ " " + e;

}

if (com.yj.cmp.commons.util.StringUtil.isNotEmpty(result)) {

log.error(result);

} else {

result = "发送成功";

}

return result;

}

@Override

public String getNoticeMethod() {

return NoticeMethodEnum.WECHAT.getName();

}

/**

* 获取或者刷新token

*/

private void getOrRefreshToken() {

try {

String requestUrl = this.tokenUri + this.bkAppKey +"&secret=" + this.bkAppSecret;

String res = HttpUtil.get(requestUrl);

JSONObject jsonObject = JSONObject.parseObject(res);

String accessToken = jsonObject.getString("access_token");

this.enterpriseToken = accessToken;

this.tokenFreshTimeSt = System.currentTimeMillis()/1000;

} catch (Exception e) {

log.error("---获取token出现异常{} {} ",e.getMessage(),e);

}

}

/**

* 获取用户列表openid

*/

public void getUserList(){

RestTemplate restTemplate = new RestTemplate();

String requestUrl = this.userListUri+ this.enterpriseToken;

ResponseEntity response = restTemplate.postForEntity(requestUrl, null, String.class);

log.info("结果是: {}",response.getBody());

com.alibaba.fastjson.JSONObject result = com.alibaba.fastjson.JSONObject.parseObject(response.getBody());

com.alibaba.fastjson.JSONArray openIdJsonArray = result.getJSONObject("data").getJSONArray("openid");

Iterator iterator = openIdJsonArray.iterator();

if (iterator.hasNext()){

log.debug("用户openid:"+iterator.next());

}

}

@Data

public class WeChatTemplateMsg {

/**

* 消息

*/

private String value;

/**

* 消息颜色

*/

private String color;

public WeChatTemplateMsg(String value) {

this.value = value;

this.color = "#173177";

}

public WeChatTemplateMsg(String value, String color) {

this.value = value;

this.color = color;

}

}

/**

* 获取用户id

* @param alarmMessage

* @return

*/

private JSONObject getWechatUserId(NoticeMessage alarmMessage){

JSONObject result = new JSONObject();

String openId = alarmMessage.getReceiverId();

if(StringUtil.isEmpty(openId)){

// todo 根据手机号码获取微信id --对应数据估计得手动维护

String receiverPhone = alarmMessage.getReceiverPhone();

if(StringUtil.isEmpty(receiverPhone)){

result.put("message","消息接收者手机号码+微信id都为空,消息无法发送");

}

openId = getWechatUserId(receiverPhone);

}

result.put("userId",openId);

return result;

}

/**

* 发送消息

* @param noticeMessage

* @return

*/

public String sendMessage(NoticeMessage noticeMessage){

String result = null;

// 模板参数

Map sendMag = new HashMap();

// openId代表一个唯一微信用户,即微信消息的接收人

JSONObject wechatUserId = getWechatUserId(noticeMessage);

String openId = null;

if(wechatUserId.containsKey("message")){

String message = wechatUserId.getString("message");

log.error(message);

return message;

}else{

Object userId = wechatUserId.get("userId");

if(Objects.isNull(userId)){

String message = "未能根据手机号码"+noticeMessage.getReceiverPhone()+"成功获取用户的微信id";

return message;

}

openId = wechatUserId.getString("userId");

}

// 公众号的模板id(也有相应的接口可以查询到)

validateToken();

String requestUrl = this.sendMessageUri + this.enterpriseToken;

//拼接base参数

Map sendBody = new HashMap<>();

sendBody.put("touser", openId);

sendBody.put("data", sendMag);

if(noticeMessage instanceof AlarmMessage){

AlarmMessage alarmMessage = (AlarmMessage)noticeMessage;

sendMag.put("message", new WeChatTemplateMsg(alarmMessage.getContent()));

sendMag.put("time",new WeChatTemplateMsg(alarmMessage.getTime()));

sendMag.put("level",new WeChatTemplateMsg(alarmMessage.getLevel(),"#FF69B4" ));

sendMag.put("type",new WeChatTemplateMsg(alarmMessage.getType() ,"#173177"));

sendMag.put("remark",new WeChatTemplateMsg(alarmMessage.getRemark(),"#173177"));

sendBody.put("template_id", this.alarmTemplateId);

}else{

sendMag.put("content", new WeChatTemplateMsg(noticeMessage.getContent()));

sendMag.put("title",new WeChatTemplateMsg(noticeMessage.getTitle()));

String time = StringUtil.isEmpty(noticeMessage.getTime()) ? DateUtils.format(new Date(),DATE_TIME_PATTERN) : noticeMessage.getTime();

sendMag.put("time",new WeChatTemplateMsg(time,"#FF69B4"));

sendBody.put("template_id", this.commonTemplateId);

}

try {

// 1.创建httpclient对象

CloseableHttpClient client = HttpClients.createDefault();

// 2.创建post对象

HttpPost post = new HttpPost(requestUrl);

StringEntity postingString = new StringEntity(JsonUtil.entityToString(sendBody), "utf-8");

post.setEntity(postingString);

// 3.执行post方法:得到结果

CloseableHttpResponse response = client.execute(post);

// 4.处理结果

// 1.得到状态码

int statusCode = response.getStatusLine().getStatusCode();

log.info("----http code : {}", statusCode);

if (statusCode == 200) {

// 2.得到实体内容

org.apache.http.HttpEntity entity = response.getEntity();

String content = EntityUtils.toString(entity, "utf-8");

JSONObject jsonObject = JsonUtil.StringToEntity(content, JSONObject.class);

String messageCode = jsonObject.getString("errcode");

String msgId = jsonObject.getString("msgid");

result = "messageCode : " + messageCode + ", msgId: " +msgId;

}

// 5.关闭连接

client.close();

} catch (IOException e) {

log.error("------exception : {} {} ",e.getMessage(),e);

}

return result;

}

/**

* 根据手机号码获取用户id

* @param receiverPhone

* @return

*/

private String getWechatUserId(String receiverPhone) {

String userId = null;

return userId;

}

/**

* 验证并刷新token

*/

private void validateToken() {

if (com.yj.cmp.commons.util.StringUtil.isEmpty(this.enterpriseToken)) {

this.getOrRefreshToken();

}

Long now = System.currentTimeMillis()/1000;

if(this.tokenFreshTimeSt == 0L){

this.getOrRefreshToken();

}else{

Long diff = (now - tokenFreshTimeSt)/60;

if(diff > 600){

// 超过十分钟重新获取一下

this.getOrRefreshToken();

}

}

}

}

3.2 配置参数

# 消息推送相关

notice:

# 微信消息相关

wechat:

bk_app_id: xxx

bk_app_secret: xxx

alarm_template_id: xxx

common_template_id: xxxxxh

token_uri: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=

user_list_uri: https://api.weixin.qq.com/cgi-bin/user/get?access_token=

send_message_uri: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=

3.3 消息模板

4. 钉钉群消息发送实现类

4.1 引入依赖

com.aliyun

dingtalk

1.5.24

com.aliyun

alibaba-dingtalk-service-sdk

2.0.0

4.2 实现类定义

package com.yj.notice.service.impl;

import com.dingtalk.api.DefaultDingTalkClient;

import com.dingtalk.api.DingTalkClient;

import com.dingtalk.api.request.OapiGettokenRequest;

import com.dingtalk.api.response.OapiGettokenResponse;

import com.yj.cmp.commons.util.StringUtil;

import com.yj.commons.tools.utils.JsonUtil;

import com.yj.notice.message.AlarmMessage;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.service.MessageService;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import com.aliyun.dingtalkrobot_1_0.Client;

import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;

import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;

import com.aliyun.tea.TeaException;

import com.aliyun.teaopenapi.models.Config;

import com.aliyun.teautil.Common;

import com.aliyun.teautil.models.RuntimeOptions;

import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;

import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;

import java.util.Arrays;

import java.util.Map;

/**

* @author : dyg

* @className : DingMessageServiceImpl

* @description : 钉钉消息发送

* @date : 2023/9/4 17:14

*/

@Service("DingTalkMessageService")

@Slf4j

@Data

public class DingTalkMessageServiceImpl implements MessageService {

@Value(value = "${notice.dingtalk.token_url}")

private String tokenUrl;

@Value(value = "${notice.dingtalk.get_user_by_phone_url}")

private String getUserByPhoneUrl;

@Value(value = "${notice.dingtalk.bk_app_key}")

private String bkAppKey;

@Value(value = "${notice.dingtalk.bk_app_secret}")

private String bkAppSecret;

/**

* token 数据

*/

private String enterpriseToken = "";

/**

* 获取/刷新token时间戳

*/

private Long tokenFreshTimeSt = 0L;

@Override

public String send(NoticeMessage message) {

String result = null;

try {

String receiverId = message.getReceiverId();

if (StringUtil.isNotEmpty(receiverId)) {

// 用户id不为空根据id发送

result = this.sendDingTalkNotify(receiverId, message);

} else {

// 否则根据手机号码查询用户

String receiverPhone = message.getReceiverPhone();

if (StringUtil.isNotEmpty(receiverPhone)) {

receiverId = this.getDingdingUserIdByPhone(receiverPhone);

if (StringUtil.isNotEmpty(receiverId)) {

result = this.sendDingTalkNotify(receiverId, message);

} else {

result = "根据接收者用户手机号码获取的用户id都为空,无法完成消息发送需求";

}

} else {

result = "接收者用户id和手机号码都为空,无法完成消息发送需求";

}

}

}catch (Exception e){

log.error(e.getMessage());

result = e.getMessage()+ " " + e;

}

if (StringUtil.isNotEmpty(result)) {

log.error(result);

} else {

result = "发送成功";

}

return result;

}

@Override

public String getNoticeMethod() {

return NoticeMethodEnum.DINGTALK.getName();

}

/**

* 使用 Token 初始化账号Client

*

* @return Client

* @throws Exception

*/

private Client createClient() throws Exception {

Config config = new Config();

config.protocol = "https";

config.regionId = "central";

return new Client(config);

}

/**

* 获取token,每两小时失效

*/

private void getOrRefreshToken() {

try {

DingTalkClient client = new DefaultDingTalkClient(this.tokenUrl);

OapiGettokenRequest req = new OapiGettokenRequest();

req.setAppkey(this.bkAppKey);

req.setAppsecret(this.bkAppSecret);

req.setHttpMethod("GET");

OapiGettokenResponse rsp = client.execute(req);

log.info("token:" + rsp.getBody());

Map json = JsonUtil.StringToEntity(rsp.getBody(), Map.class);

this.enterpriseToken = json.get("access_token").toString();

this.tokenFreshTimeSt = System.currentTimeMillis()/1000;

} catch (Exception e) {

log.error("---获取token出现异常{} {} ",e.getMessage(),e);

}

}

/**

* 根据手机号码获取钉钉用户id

* -- 备注: 必须将用户拉入组织/群中之后才可以根据手机号码获取用户

* @param phone 用户手机号

* @return void

*/

private String getDingdingUserIdByPhone(String phone) {

try {

if (StringUtil.isEmpty(this.enterpriseToken)) {

this.getOrRefreshToken();

}

DingTalkClient client = new DefaultDingTalkClient(getUserByPhoneUrl);

OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();

req.setMobile(phone);

OapiV2UserGetbymobileResponse rsp = client.execute(req, this.enterpriseToken);

if (rsp != null) {

OapiV2UserGetbymobileResponse.UserGetByMobileResponse result = rsp.getResult();

return result == null ? null : result.getUserid();

}

} catch (Exception e) {

log.error(e.getMessage(), e);

}

return null;

}

/**

* 发送钉钉消息

* @param dingUserId 钉钉用户id

* @param message 发送消息

* @return void

*/

public String sendDingTalkNotify(String dingUserId, NoticeMessage message) throws Exception {

String result = null;

validateToken();

Client client = createClient();

BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders();

batchSendOTOHeaders.xAcsDingtalkAccessToken = this.enterpriseToken;

String content = null;

if(message instanceof AlarmMessage){

AlarmMessage alarmMessage = (AlarmMessage)message;

content = alarmMessage.wrapperMessage();

}else{

content = message.wrapperMessage();

}

String finalContent = "{\"content\": \"" + content + "\"}";

BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest()

.setRobotCode(this.bkAppKey)//机器人appkey

.setUserIds(Arrays.asList(dingUserId))

.setMsgKey("officialTextMsg")

.setMsgParam(finalContent);

try {

client.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions());

} catch (TeaException err) {

if (!Common.empty(err.code) && !Common.empty(err.message))

// err 中含有 code 和 message 属性,可帮助开发定位问题

log.error(err.code + ":" + err.message);

} catch (Exception e) {

TeaException err = new TeaException(e.getMessage(), e);

if (!Common.empty(err.code) && !Common.empty(err.message))

// err中含有code和message 属性,可帮助开发定位问题

log.error(err.code + ":" + err.message);

result = err.code + ":" + err.message;

}

return result;

}

/**

* 验证并刷新token

*/

private void validateToken() {

if (StringUtil.isEmpty(this.enterpriseToken)) {

this.getOrRefreshToken();

}

Long now = System.currentTimeMillis()/1000;

if(this.tokenFreshTimeSt == 0L){

this.getOrRefreshToken();

}else{

Long diff = (now - tokenFreshTimeSt)/60;

if(diff > 600){

// 超过十分钟重新获取一下

this.getOrRefreshToken();

}

}

}

}

4.3 配置参数

# 消息推送相关

notice:

# 钉钉消息相关

dingtalk:

bk_app_key: xxx

bk_app_secret: xxxx

token_url: https://oapi.dingtalk.com/gettoken

get_user_by_phone_url: https://oapi.dingtalk.com/topapi/v2/user/getbymobile

4.4 创建应用获取appKey+appSecret

1. 使用钉钉账户作为管理员创建一个组织/群

2. 登录钉钉后台管理页面,工作台--->应用管理--->创建应用(委托服务商开发), 创建一个H5微应用

3. 登录钉钉后台管理页面,工作台--->应用管理--->点击应用, 查看 凭证与基础信息 获取配置文件中所需要的appKey/appSecret

4. 为当前应用创建机器人,工作台--->应用管理--->点击应用-->添加应用能力--->机器人添加

5. 为应用申请相应的权限,例如根据手机号码获取用户,企业内机器人发送消息权限

6. 将当前应用发布 ,当添加完毕机器人+权限之后,当前应用显示 开发中,如下图所示,需要在版本与管理中创建一个发布版本(只有发布成功之后才可以使用)

7. 将需要接收消息的钉钉用户拉入群组

5. 邮件发送实现类

5.1 引入依赖

org.springframework.boot

spring-boot-starter-mail

5.2 定义实现类import com.yj.commons.tools.utils.JsonUtil;

import com.yj.commons.tools.utils.StringUtil;

import com.yj.notice.message.MailMessage;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.service.MessageService;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.mail.SimpleMailMessage;

import org.springframework.mail.javamail.JavaMailSender;

import org.springframework.mail.javamail.MimeMessageHelper;

import org.springframework.stereotype.Service;

import javax.mail.internet.MimeMessage;

import java.io.File;

/**

* @author : dyg

* @className : MailMessageServiceImpl

* @description : 邮件发送器

* @date : 2023/9/5 14:31

*/

@Service("MailMessageService")

@Slf4j

@Data

public class MailMessageServiceImpl implements MessageService {

@Value("${spring.mail.username}")

private String from;

@Autowired

private JavaMailSender mailSender;

@Override

public String getNoticeMethod() {

return NoticeMethodEnum.EMAIL.getName();

}

/**

* 发送邮件

* @param message

* @return

*/

@Override

public String send(NoticeMessage message) {

String result = null;

try{

if(message instanceof MailMessage){

MailMessage mailMessage = (MailMessage)message;

File attachFile = mailMessage.getAttachFile();

String html = mailMessage.getHtml();

if(null != attachFile){

// 带附件的邮件

result = sendAttachFileMail(mailMessage,attachFile);

}else{

if(StringUtil.isNotEmpty(html)){

// html内容的邮件

result = sendHtmlMail(mailMessage,html);

}else{

// 普通邮件

result = sendSimpleMail(mailMessage);

}

}

}

if(StringUtil.isNotEmpty(result)){

log.error("发送邮件: {} 发生错误: {}", JsonUtil.entityToString(message),result);

}

}catch (Exception e){

log.error(e.getMessage());

result = e.getMessage();

}

return result;

}

/**

* 带附件的邮件发送

* @param mailMessage

* @param attachFile

* @return

*/

private String sendAttachFileMail(MailMessage mailMessage,File attachFile) {

String result = null;

try {

MimeMessage message = mailSender.createMimeMessage();

MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);

//邮件发送人

messageHelper.setFrom(from);

//邮件接收人

messageHelper.setTo(mailMessage.getReceiverId());

//邮件主题

message.setSubject(mailMessage.getTitle());

//邮件内容

messageHelper.setText(mailMessage.wrapperMessage());

//添加附件

messageHelper.addAttachment(attachFile.getName(), attachFile);

//发送

mailSender.send(message);

}catch(Exception e) {

log.error("发送附件邮件报错: {} {}",e.getMessage(),e);

result = e.getMessage();

}

return result;

}

/**

* html内容的邮件发送

* @param mailMessage

* @param html

* @return

*/

private String sendHtmlMail(MailMessage mailMessage, String html) {

String result = null;

try {

MimeMessage message = mailSender.createMimeMessage();

MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);

//邮件发送人

messageHelper.setFrom(from);

//邮件接收人

messageHelper.setTo(mailMessage.getReceiverId());

//邮件主题

message.setSubject(mailMessage.getTitle());

//邮件内容

messageHelper.setText(html,true);

//发送

mailSender.send(message);

}catch(Exception e) {

log.error("发送html内容邮件报错: {} {}",e.getMessage(),e);

result = e.getMessage();

}

return result;

}

/**

* 普通邮件发送

* @param mailMessage

* @return

*/

private String sendSimpleMail(MailMessage mailMessage) {

String result = null;

try {

SimpleMailMessage message = new SimpleMailMessage();

message.setFrom(from);

message.setTo(mailMessage.getReceiverId());

message.setCc(from);

message.setSubject(mailMessage.getTitle());

message.setText(mailMessage.wrapperMessage());

mailSender.send(message);

}catch(Exception e) {

log.error("发送普通邮件报错: {} {}",e.getMessage(),e);

result = e.getMessage();

}

return result;

}

}

5.3 配置参数

spring:

# 邮件相关

mail:

host: smtp.qq.com

port: 465

username: xxx@qq.com

password: xxx

properties:

mail:

smtp:

auth: true

starttls:

enable: true

required: true

6. 腾讯短信发送实现类

6.1 引入依赖

com.tencentcloudapi tencentcloud-sdk-java 3.1.1000

6.2 定义实现类

package com.yj.notice.service.impl;

import com.tencentcloudapi.common.Credential;

import com.tencentcloudapi.common.exception.TencentCloudSDKException;

import com.tencentcloudapi.common.profile.ClientProfile;

import com.tencentcloudapi.common.profile.HttpProfile;

import com.tencentcloudapi.sms.v20210111.SmsClient;

import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;

import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;

import com.yj.cmp.commons.json.JsonUtil;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.service.MessageService;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

/**

* @author : dyg

* @className : TencentMessageServiceImpl

* @description : 描述说明该类的功能

* @date : 2024/4/16 10:10

*/

@Service("TencentMessageService")

@Slf4j

@Data

public class TencentMessageServiceImpl implements MessageService {

/**

* 短信发送API

*/

private final String SMS_API = "sms.tencentcloudapi.com";

private final String SMS_ACTION = "SendSms";

private final String SMS_VERSION = "2021-01-11";

private final String SMS_REGION= "ap-beijing";

/**

* 短信客户端

*/

private SmsClient smsClient;

/**

* 短信发送AppId

*/

@Value(value = "${notice.tencent.appId}")

private String smsSdkAppId;

/**

* 短信发送模板Id

*/

@Value(value = "${notice.tencent.templateId}")

private String smsTemplateId ;

/**

* 腾讯云认证信息

*/

@Value(value = "${notice.tencent.secretId}")

private String secretId ;

@Value(value = "${notice.tencent.secretKey}")

private String secretKey ;

/**

* 获取客户端

* @return

*/

public SmsClient getSmsClient() {

synchronized (this){

if(null == smsClient){

Credential credential = new Credential(secretId,secretKey);

// 实例化一个http选项,可选的,没有特殊需求可以跳过

HttpProfile httpProfile = new HttpProfile();

// 推荐使用北极星,相关指引可访问如下链接

// https://git.woa.com/tencentcloud-internal/tencentcloud-sdk-java#%E5%8C%97%E6%9E%81%E6%98%9F

httpProfile.setEndpoint(SMS_API);

// 实例化一个client选项,可选的,没有特殊需求可以跳过

ClientProfile clientProfile = new ClientProfile();

clientProfile.setHttpProfile(httpProfile);

// 实例化要请求产品的client对象,clientProfile是可选的

smsClient = new SmsClient(credential,SMS_REGION,clientProfile);

}

}

return smsClient;

}

@Override

public String send(NoticeMessage message) {

String result = null;

SendSmsRequest sendSmsRequest = new SendSmsRequest();

sendSmsRequest.setSmsSdkAppId(smsSdkAppId);

sendSmsRequest.setPhoneNumberSet(new String[]{message.getReceiverPhone()});

sendSmsRequest.setSignName("腾讯云");

sendSmsRequest.setTemplateId(smsTemplateId);

sendSmsRequest.setTemplateParamSet(new String[]{message.getTitle(),message.getContent(),message.getTime()});

try {

SendSmsResponse sendSmsResponse = smsClient.SendSms(sendSmsRequest);

result = "发送腾讯短信平台结果: "+ JsonUtil.objectToJson(sendSmsResponse);

} catch (TencentCloudSDKException e) {

log.error(e.getMessage(),e);

result ="发送腾讯短信平台失败: "+ e.getMessage()+ " " + e;

}

return result;

}

@Override

public String getNoticeMethod() {

return NoticeMethodEnum.TENCENT_SMS.getName();

}

}

6.3 配置参数

# 消息推送相关

notice:

# 腾讯短信配置

tencent:

appId: xx

templateId: xx

secretId: xx

secretKey: xx

7. 系统内部消息发送实现类

7.1 系统内部消息表定义

-- 系统用户-站内消息表

DROP TABLE IF EXISTS `system_user_message`;

create table `system_user_message` (

`id` int(16) NOT NULL AUTO_INCREMENT,

`message_type` varchar(200) COMMENT '消息类型 public-公告 private-个人消息 ticket-工单消息',

`source_msg_id` int(16) COMMENT '消息id' ,

`title` varchar(200) COMMENT '标题',

`content` text COMMENT '内容',

`receiver_id` varchar(200) COMMENT '接收者id 用户id',

`send_time` datetime NOT NULL default NOW() COMMENT '发送时间',

`bus_type` varchar(200) COMMENT '业务类型',

`is_read` int(1) default 0 COMMENT '是否已读 0-no 1-yes',

`read_time` datetime COMMENT '读取时间',

`properties` varchar(1000) comment '其他数据',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '系统用户-站内消息表';

6.2 系统内部消息实体定义

package com.yj.notice.entity;

import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.annotation.TableField;

import com.baomidou.mybatisplus.annotation.TableId;

import com.baomidou.mybatisplus.annotation.TableName;

import com.yj.notice.costant.MessageSource;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

import java.util.Date;

/**

* @author : dyg

* @className : SystemMessage

* @description : 内部通知消息

* @date : 2023/9/7 10:04

*/

@AllArgsConstructor

@NoArgsConstructor

@Builder

@Data

@TableName("system_user_message")

public class SystemUserMessage implements Serializable {

private static final long serialVersionUID = 228169618996650529L;

@TableId(type = IdType.AUTO)

private Integer id;

/**

* 消息类型

* {@link MessageSource}

*/

@TableField("message_type")

private String messageType;

/**

* 源头消息id

* public-公告 yg_alarm-云管告警 cloud_alarm-插件告警 使用到

* {@link MessageSource}

*/

@TableField("source_msg_id")

private Integer sourceMsgId;

/**

* 消息标题

*/

@TableField("title")

private String title;

/**

*消息内容

*/

@TableField("content")

private String content;

/**

* 接收者id

*/

@TableField("receiver_id")

private String receiverId;

/**

* 发送时间

*/

@TableField("send_time")

private Date sendTime;

/**

* 消息业务类型

*/

@TableField("bus_type")

private String busType;

/**

* 是否已读

* 0-no 1-yes

*/

@TableField("is_read")

private Integer isRead;

/**

* 读取时间

*/

@TableField("read_time")

private Date readTime;

@TableField("properties")

private String properties;

}

7.3 实现类定义

package com.yj.notice.service.impl;

import cn.hutool.core.collection.CollectionUtil;

import com.alibaba.fastjson.JSONObject;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.yj.cmp.bss.constant.RoleGroup;

import com.yj.cmp.bss.entity.APIPermission;

import com.yj.cmp.bss.entity.Audit;

import com.yj.cmp.bss.entity.Request;

import com.yj.cmp.bss.entity.User;

import com.yj.cmp.bss.service.RequestService;

import com.yj.cmp.bss.service.UserService;

import com.yj.cmp.commons.constant.BssConstant;

import com.yj.commons.security.user.SecurityUser;

import com.yj.commons.security.user.UserDetail;

import com.yj.commons.tools.page.PageData;

import com.yj.commons.tools.utils.Result;

import com.yj.commons.tools.utils.StringUtil;

import com.yj.helper.user.UserHelper;

import com.yj.notice.costant.MessageSource;

import com.yj.notice.costant.NoticeMethodEnum;

import com.yj.notice.dao.SystemUserMessageDao;

import com.yj.notice.entity.SystemUserMessage;

import com.yj.notice.entity.PublicSystemNotice;

import com.yj.notice.message.NoticeMessage;

import com.yj.notice.service.MessageService;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.servlet.http.HttpServletRequest;

import java.util.*;

import java.util.stream.Collectors;

/**

* @author : dyg

* @className : NoticeInnerMessageServiceImpl

* @description : 描述说明该类的功能

* @date : 2023/9/7 10:42

*/

@Service

@Slf4j

public class SystemUserMessageServiceImpl extends ServiceImpl implements MessageService {

@Override

public String send(NoticeMessage message) {

SystemUserMessage build = SystemUserMessage.builder().messageType(message.getMessageType())

.title(message.getTitle())

.content(message.getContent())

.receiverId(message.getReceiverId())

.sendTime(new Date())

.busType(message.getMessageType())

.isRead(0)

.build();

this.save(build);

return "success";

}

@Override

public String getNoticeMethod() {

return NoticeMethodEnum.IN_MSG.getName();

}

}

8. 消息推送测试

8.1 钉钉推送测试

package com.yj.notice.demo;

import com.aliyun.dingtalkrobot_1_0.Client;

import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;

import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;

import com.aliyun.tea.TeaException;

import com.aliyun.teaopenapi.models.Config;

import com.aliyun.teautil.Common;

import com.aliyun.teautil.models.RuntimeOptions;

import com.dingtalk.api.DefaultDingTalkClient;

import com.dingtalk.api.DingTalkClient;

import com.dingtalk.api.request.*;

import com.dingtalk.api.response.*;

import com.taobao.api.ApiException;

import com.yj.commons.tools.utils.JsonUtil;

import com.yj.commons.tools.utils.StringUtil;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

import java.util.List;

import java.util.Map;

@Slf4j

public class DingTalkMessageSend {

// 企业凭证,两小时一更新

private static String enterpriseToken = "";

// 应用凭证

private static String appkey = "xxxx";

private static String appsecret = "xxxx";

// 获取token,每两小时失效

public static void getToken() {

try {

DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");

OapiGettokenRequest req = new OapiGettokenRequest();

req.setAppkey(appkey);

req.setAppsecret(appsecret);

req.setHttpMethod("GET");

OapiGettokenResponse rsp = client.execute(req);

log.info("token:" + rsp.getBody());

Map json = JsonUtil.StringToEntity(rsp.getBody(), Map.class);

enterpriseToken = json.get("access_token").toString();

} catch (ApiException e) {

e.printStackTrace();

}

}

/**

* 使用 Token 初始化账号Client

*

* @return Client

* @throws Exception

*/

private static Client createClient() throws Exception {

Config config = new Config();

config.protocol = "https";

config.regionId = "central";

return new Client(config);

}

/**

* 发送钉钉消息

*

* @param dingUserId 钉钉用户id

* @param content 发送消息内容

* @return void

*/

public static void createDingNotify(String dingUserId, String content) throws Exception {

if (StringUtil.isEmpty(enterpriseToken)) {

getToken();

}

Client client = createClient();

BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders();

batchSendOTOHeaders.xAcsDingtalkAccessToken = enterpriseToken;

content = "{\"content\": \"" + content + "\"}";

BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest()

.setRobotCode(appkey)//机器人appkey

.setUserIds(Arrays.asList(dingUserId))

.setMsgKey("officialTextMsg")

.setMsgParam(content);

try {

client.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions());

} catch (TeaException err) {

if (!Common.empty(err.code) && !Common.empty(err.message))

// err 中含有 code 和 message 属性,可帮助开发定位问题

log.error(err.code + ":" + err.message);

// 企业凭证enterpriseToken不合法导致出错时获取新企业凭证并重试

if (err.code.equals("InvalidAuthentication")) {

getToken();

}

} catch (Exception e) {

TeaException err = new TeaException(e.getMessage(), e);

if (!Common.empty(err.code) && !Common.empty(err.message))

// err中含有code和message 属性,可帮助开发定位问题

log.error(err.code + ":" + err.message);

}

}

/**

* 发送钉钉消息

*

* @param phone 用户手机号

* @return void

*/

public static String getDingdingUserIdByPhone(String phone) {

try {

if (StringUtil.isEmpty(enterpriseToken)) {

getToken();

}

DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");

OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();

req.setMobile(phone);

OapiV2UserGetbymobileResponse rsp = client.execute(req, enterpriseToken);

if (rsp != null) {

OapiV2UserGetbymobileResponse.UserGetByMobileResponse result = rsp.getResult();

return result == null ? null : result.getUserid();

}

} catch (ApiException e) {

log.error(e.getErrMsg(), e);

}

return null;

}

/**

* 获取组内用户列表

*

* @return void

*/

public static void getUserList( ) {

try {

if (StringUtil.isEmpty(enterpriseToken)) {

getToken();

}

DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");

OapiUserListRequest req = new OapiUserListRequest();

OapiUserListResponse rsp = client.execute(req, enterpriseToken);

if (rsp != null) {

List userlist = rsp.getUserlist();

userlist.stream().forEach(System.out::println);

}

} catch (ApiException e) {

log.error(e.getErrMsg(), e);

}

}

/**

* 获取组内用户列表

*

* @return void

*/

public static void getDepartmentList( ) {

try {

if (StringUtil.isEmpty(enterpriseToken)) {

getToken();

}

DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");

OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();

OapiV2DepartmentListsubResponse rsp = client.execute(req, enterpriseToken);

if (rsp != null) {

List result = rsp.getResult();

result.stream().forEach(System.out::println);

}

} catch (ApiException e) {

log.error(e.getErrMsg(), e);

}

}

public static void main(String[] args) throws Exception{

String dingdingUserIdByPhone = getDingdingUserIdByPhone("17352253381");

System.out.println(dingdingUserIdByPhone);

createDingNotify(dingdingUserIdByPhone,"告警时间: 2023-09-05 16:33:36\n告警级别: 中级\n告警类别: 虚拟机\n告警消息: 虚拟机告警信息\n备注: 虚拟机告警信息");

getDepartmentList();

getUserList();

}

}

8.2 微信推送测试

package com.yj.notice.demo;

import cn.hutool.http.HttpUtil;

import com.alibaba.fastjson.JSONObject;

import com.yj.commons.tools.utils.DateUtils;

import com.yj.commons.tools.utils.JsonUtil;

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.entity.StringEntity;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

import org.springframework.http.ResponseEntity;

import org.springframework.web.client.RestTemplate;

import java.io.IOException;

import java.io.Serializable;

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import static com.yj.commons.tools.utils.DateUtils.DATE_TIME_PATTERN;

/**

* @author : dyg

* @className : WechatMessageSend

* @description : 描述说明该类的功能

* @date : 2023/9/5 10:01

*/

@Slf4j

public class WechatMessageSend {

@Data

public static class WeChatTemplateMsg implements Serializable {

/**

* 消息

*/

private String value;

/**

* 消息颜色

*/

private String color;

public WeChatTemplateMsg(String value) {

this.value = value;

this.color = "#173177";

}

public WeChatTemplateMsg(String value, String color) {

this.value = value;

this.color = color;

}

}

public static String getAccessToken(){

String appId = "xxxx";

String appIdSecret = "xxxx";

String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId +"&secret=" + appIdSecret;

String res = HttpUtil.get(requestUrl);

JSONObject jsonObject = JSONObject.parseObject(res);

String accessToken = jsonObject.getString("access_token");

log.info("accessToken:{}", accessToken);

return accessToken;

}

public static void getUserList(){

RestTemplate restTemplate = new RestTemplate();

String accessToken = getAccessToken();

String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token="+ accessToken;

ResponseEntity response = restTemplate.postForEntity(requestUrl, null, String.class);

log.info("结果是: {}",response.getBody());

JSONObject result = JSONObject.parseObject(response.getBody());

com.alibaba.fastjson.JSONArray openIdJsonArray = result.getJSONObject("data").getJSONArray("openid");

Iterator iterator = openIdJsonArray.iterator();

if (iterator.hasNext()){

String userId = iterator.next().toString();

log.debug("用户openid:"+userId);

String userDetailUri = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+accessToken+"&openid="+userId+"&lang=zh_CN";

ResponseEntity response2 = restTemplate.postForEntity(userDetailUri, null, String.class);

log.info("结果是: {}",response2.getBody());

JSONObject result2 = JSONObject.parseObject(response2.getBody());

log.info("用户详细信息: {}",result2.toJSONString());

}

}

public static void sendMessage(String type){

// 模板参数

Map sendMag = new HashMap();

// openId代表一个唯一微信用户,即微信消息的接收人

String openId = "okUjK6P908Zwjc8BOSdinAO8iG5o";

// 公众号的模板id(也有相应的接口可以查询到)

String alarmTemplateId = "mfriJWNssZYtIbpfzxH-4FlxgK4ZQ0ID_xNvEO0xDOY";

String commonTemplateId = "q7bSOYPPDHn-Lz_vTShzsbU4WzKX3lH9nxuasnngj8A";

// 微信的基础accessToken

String accessToken = getAccessToken();

String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;

//消息主题显示相关map

//根据自己的模板定义内容和颜色

//拼接base参数

Map sendBody = new HashMap<>();

sendBody.put("touser", openId); // openId

// sendBody.put("url", "https://www.baidu.com"); //跳转网页url

sendBody.put("data", sendMag); // 模板参数

if("alarm".equals(type)){

sendMag.put("message", new WeChatTemplateMsg("虚拟机-102.23.26.36 CPU使用占比超过80%"));

sendMag.put("time",new WeChatTemplateMsg(DateUtils.format(new Date(),DATE_TIME_PATTERN),"#173177"));

sendMag.put("level",new WeChatTemplateMsg("中等","#FF69B4" ));

sendMag.put("type",new WeChatTemplateMsg("虚拟机CPU" ,"#173177"));

sendMag.put("remark",new WeChatTemplateMsg("虚拟机CPU使用触发告警","#173177"));

sendBody.put("template_id", alarmTemplateId); // 模板Id

}else{

sendMag.put("content", new WeChatTemplateMsg("根据兰州市气象局发布的最新天气预警信息,未来8-24小时内,城关区、七里河区、西固区、安宁区、榆中县、皋兰县大部将有依次明显的降水活动,并伴有短时5-6级大风,请注意及时关注最新天气情况!"));

sendMag.put("title",new WeChatTemplateMsg("暴雨蓝色预警"));

sendMag.put("time",new WeChatTemplateMsg(DateUtils.format(new Date(),DATE_TIME_PATTERN),"#FF69B4"));

sendBody.put("template_id", commonTemplateId); // 模板Id

}

try {

// 1.创建httpclient对象

CloseableHttpClient client = HttpClients.createDefault();

// 2.创建post对象

HttpPost post = new HttpPost(requestUrl);

StringEntity postingString = new StringEntity(JsonUtil.entityToString(sendBody), "utf-8");

post.setEntity(postingString);

// 3.执行post方法:得到结果

CloseableHttpResponse response = client.execute(post);

// 4.处理结果

// 1.得到状态码

int statusCode = response.getStatusLine().getStatusCode();

log.info("----http code : {}", statusCode);

if (statusCode == 200) {

// 2.得到实体内容

org.apache.http.HttpEntity entity = response.getEntity();

String content = EntityUtils.toString(entity, "utf-8");

System.out.println(content);

}

// 5.关闭连接

client.close();

} catch (IOException e) {

log.error("------exception : {} {} ",e.getMessage(),e);

}

}

public static void main(String[] args) {

// getAccessToken();

// getUserList();

sendMessage("a");

}

}