【SpringBoot】Java SpringBoot 企业微信机器人发送文本消息、图片消息

前言

最近需要定时提示同事分享文章等,因此做了一个企业微信机器人定时发送消息。

官网指导文档:
群机器人配置说明
发送应用消息

实战

1.根据文档里的JSON格式,我们先定义要用到的消息实体对象和枚举类。
(1) Message

/**
 * @description: 企业微信机器人消息实体类
 * @author: DreamflyChen
 * @create: 2020-08-30 13:03
 */
@Data
public class Message {
    /**
     * 消息类型
     */
    private MessageTypeEnum msgtype;
    /**
     * 文本消息
     */
    private JSONObject text;

    /**
     * 图片消息
     */
    private JSONObject image;

    /**
     * 表示是否是保密消息,0表示否,1表示是,默认0
     */
    private Integer safe;
}

(2) ImageMessage

/**
 * @description: 图片类型消息
 * @author: DreamflyChen
 * @create: 2020-08-30 13:16
 */
@Data
public class ImageMessage {
    /**
     * 图片内容的base64编码
     * 注:图片(base64编码前)最大不能超过2M,支持JPG,PNG格式
     */
    private String base64;

    /**
     * 图片内容(base64编码前)的md5值
     */
    private String md5;
}

(3) TextMessage

/**
 * @description: 文本消息实体类
 * @author: DreamflyChen
 * @create: 2020-08-30 13:11
 */
@Data
public class TextMessage {
    /**
     * 文本内容,最长不超过2048个字节,必须是utf8编码(必填)
     */
    private String content;

    /**
     * userid的列表,提醒群中的指定成员(@某个成员),@all表示提醒所有人,如果开发者获取不到userid,可以使用mentioned_mobile_list
     * (非必填)
     */
    private List<String> mentioned_list;

    /**
     * 手机号列表,提醒手机号对应的群成员(@某个成员),@all表示提醒所有人
     */
    private List<String> mentioned_mobile_list;
}

(4)MessageTypeEnum 消息类型枚举

/**
 * 消息类型枚举
 *
 * @author DreamflyChen
 * @create 2020-8-30 14:25:06
 */
@Getter
@Slf4j
public enum MessageTypeEnum {

    unknown_type(-1, "未知类型"),
    text(1, "文本类型"),
    image(2, "图片类型");

    private final int value;
    private final String desc;


    MessageTypeEnum(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    /**
     * 根据值返回枚举
     *
     * @param value
     * @return
     */
    public static MessageTypeEnum getEnumByValue(int value) {
        for (MessageTypeEnum v : MessageTypeEnum.values()) {
            if (v.getValue() == value) {
                return v;
            }
        }
        return unknown_type;
    }

    /**
     * 根据编码获取描述信息
     *
     * @param value
     * @return
     */
    public static String getDescByValue(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        try {
            int discount = Integer.parseInt(value.trim());
            for (MessageTypeEnum v : MessageTypeEnum.values()) {
                if (v.getValue() == discount) {
                    return v.getDesc();
                }
            }
            return "未知类型: " + value;
        } catch (Exception e) {
            log.info("字符串格式转数字异常,str: {}", value);
            return null;
        }
    }
}

2.封装处理器,主要是发送消息的方法,图片转Base64字符串(注意要去掉换行符,这一点官网文档没有说明),文件md5加密。
(1) ImageManager

/**
 * @description: 图片处理
 * @author: DreamflyChen
 * @create: 2020-08-29 23:05
 */
@Slf4j
public class ImageManager {
    /**
     * @Description 图片转base64字符串
     * @param imgUrl 图片路径(Resources目录下, 如/img/pic1.png)
     * @return
     */
    public static String imageToBase64Str(String imgUrl) {
        InputStream inputStream;
        byte[] data;
        try {
            inputStream = ImageManager.class.getResourceAsStream(imgUrl);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            log.error("图片转base64字符串异常, 异常信息如下:{}", e.getMessage());
            return null;
        }
        // 加密
        BASE64Encoder encoder = new BASE64Encoder();
        //去掉换行符
        String result = encoder.encode(data).replaceAll("\r|\n", "");
        return result;
    }

    /**
     * @Description 生成文件的md5值
     * @param fileUrl 文件路径(Resources目录下, 如/img/pic1.png)
     * @return MD5值
     */
    public static String getStringMd5(String fileUrl) throws Exception {
        String value;
        //toURI() 解决中文路径乱码问题
        String path = ImageManager.class.getResource(fileUrl).toURI().getPath();
        try (FileInputStream in = new FileInputStream(path)) {
            MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, new File(path).length());
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(byteBuffer);
            BigInteger bi = new BigInteger(1, md5.digest());
            value = bi.toString(16);
        }
        return value;
    }
}

(2) MessageManager

/**
 * @description: 消息处理器
 * @author: DreamflyChen
 * @create: 2020-08-30 13:33
 */
@Slf4j
public class MessageManager {

    public static boolean sendMessage(Message message, String webHookAddress) {
        OkHttpClient client = new OkHttpClient.Builder()
                // 设置连接超时时间
                .connectTimeout(10, TimeUnit.SECONDS)
                // 设置读取超时时间
                .readTimeout(20, TimeUnit.SECONDS)
                .build();
        MediaType contentType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSONObject.toJSONString(message), contentType);
        Request request = new Request.Builder().url(webHookAddress).post(body).addHeader("cache-control", "no-cache").build();
        try {
            Response response = client.newCall(request).execute();
            byte[] datas = response.body().bytes();
            String respMsg = new String(datas);
            JSONObject resultJSON = JSONObject.parseObject(respMsg);
            if (resultJSON.getIntValue("errcode") == 0) {
                log.info("消息发送成功!");
                return true;
            }
            log.error("消息发送失败, 错误信息如下: {}", resultJSON.getString("errmsg"));
            return false;
        } catch (IOException e) {
            log.error("消息发送失败, 异常信息如下: {}", e.getMessage());
            return false;
        }
    }
}

3.定时任务例子,使用@Scheduled注解与Cron表达式, 跑main方法可以立刻看到效果哦!
在线Cron表达式生成地址:https://qqe2.com/cron

/**
 * @description: 日报提醒和分享任务
 * @author: DreamflyChen
 * @create: 2020-08-29 21:51
 */
@Component
public class DailyTipAndShareTask {

    @Scheduled(cron = "0 0 10 ? * 1")
    public void ShareTip() throws Exception {
        String webHookAddress = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...";
        //发送文本消息
        Message message = new Message();
        message.setMsgtype(MessageTypeEnum.text);
        TextMessage textMessage = new TextMessage();
        textMessage.setContent("这里写文本消息内容。");
        textMessage.setMentioned_list(Arrays.asList("user id list"));
        JSONObject text = JSONObject.parseObject(JSONObject.toJSONString(textMessage));
        message.setText(text);
        MessageManager.sendMessage(message, webHookAddress);

        //发送图片消息
        message.setText(null);
        message.setMsgtype(MessageTypeEnum.image);
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.setBase64(ImageManager.imageToBase64Str("/img/朱茵.jpg"));
        imageMessage.setMd5(ImageManager.getStringMd5("/img/朱茵.jpg"));
        JSONObject image = JSONObject.parseObject(JSONObject.toJSONString(imageMessage));
        message.setImage(image);
        MessageManager.sendMessage(message, webHookAddress);
    }

    public static void main(String[] args) throws Exception {
        new DailyTipAndShareTask().ShareTip();
    }
}

运行效果

【SpringBoot】Java SpringBoot 企业微信机器人发送文本消息、图片消息_第1张图片

项目下载地址

https://gitee.com/cqh_i/qiyeweixin-robot

你可能感兴趣的:(java,企业微信机器人,图片消息,Base64,md5)