需要用到的枚举类
import enums.ICommonEnum;
import external.robot.common.enums.TransformEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumAnnotation {
/**
* <p>枚举类</p>
* */
Class< ? extends ICommonEnum> clz();
/**
* <p>转换方式(code转换value或者type转value)</p>
* <p>默认code到value的转换</p>
* */
TransformEnum transform() default TransformEnum.CODE_TO_VALUE;
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>自定义注解,用于参数校验</p>
* @author
* 李萌*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Required {
/**
* <p>消息</p>
* */
String errorMsg() default "不能为空";
/**
* <p>备注</p>
* */
String remark() default "";
/**
* <p>是否需要对这个类进行解释</p>
* */
boolean classParse() default false;
}
异常类
package external.robot.common.dto;
import external.robot.common.enums.ExceptionCode;
import lombok.Getter;
/**
* 基类异常
*/
@Getter
public class BaseException extends RuntimeException{
private int code= ExceptionCode.FAIL.getKey();
private ExceptionCode errorCode;
private String message;
private Object entity;
public BaseException() {
errorCode = ExceptionCode.SYSTEM_ERROR;
}
public BaseException(String message) { this.message = message; }
public BaseException(String message, Throwable e) { super(message, e); }
public BaseException(Throwable e) { super(e); }
public BaseException(ExceptionCode exceptionCode){
this.errorCode=exceptionCode;
}
public BaseException(ExceptionCode exceptionCode, Object entity) {
super();
errorCode = exceptionCode;
this.entity=entity;
}
public BaseException(ExceptionCode exceptionCode, Throwable e) {
super(e);
errorCode = exceptionCode;
}
public BaseException(String message, ExceptionCode exceptionCode) {
super(message);
errorCode = exceptionCode;
this.message = message;
}
public BaseException(String message, ExceptionCode exceptionCode, Throwable e) {
super(message, e);
errorCode = exceptionCode;
}
public ExceptionCode getErrorCode() {
return errorCode;
}
public BaseException(int code, String message) {
super(message);
this.code = code;
this.message = message;
}
}
机器人的响应以及请求体
package external.robot.common.dto;
import cn.hutool.core.net.URLEncodeUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class RobotRequest{
private String requestInterface;
private String requestParams;
private String requestBody;
private String responseResult;
private String responseDate;
private String requestIp;
private String requestUserId;
private String userAgent;
private String stackInfo;
public RobotRequest(String requestInterface, String requestParams, String requestBody, String responseResult, String responseDate,String requestIp,String requestUserId,String userAgent,String stackInfo) {
this.requestInterface = requestInterface;
this.requestParams = requestParams;
this.requestBody = requestBody;
this.responseResult = responseResult;
this.responseDate = responseDate;
this.requestIp=requestIp;
this.requestUserId=requestUserId;
this.userAgent=userAgent;
this.stackInfo=stackInfo;
}
public String toJson(){
return JSONObject.toJSONString(this);
}
public String encode(){
return URLEncodeUtil.encode(toJson());
}
}
package external.robot.common.dto;
import external.robot.common.enums.ExceptionCode;
import lombok.Data;
/**
* 机器人的响应体
*/
@Data
public class RobotResponse {
/**
* <p>成功标识</p>
* */
private static final String SUCCESS_CODE = "0";
/**
* <p>响应码</p>
* */
private String errcode= ExceptionCode.FAIL.getCode();
/**
* <p>响应消息</p>
* */
private String errmsg= ExceptionCode.FAIL.getValue();
/**
* <p>消息发送是否成功</p>
* */
private boolean isSuccess(){ return SUCCESS_CODE.equals(errcode); }
public RobotResponse(){super();}
public RobotResponse(String errcode, String errmsg) {
this.errcode = errcode;
this.errmsg = errmsg;
}
public RobotResponse(ExceptionCode exceptionCode){
this(exceptionCode.getCode(),exceptionCode.getValue());
}
}
转换枚举类和异常枚举类
package external.robot.common.enums;
import enums.ICommonEnum;
import lombok.Getter;
@Getter
public enum AlgorithmEnum implements ICommonEnum {
HmacSHA256("HmacSHA256","HmacSHA256"),
MD5("MD5","MD5");
private final String code;
private final String value;
AlgorithmEnum(String code, String value) {
this.code = code;
this.value = value;
}
@Override
public Integer getKey() { return null; }
}
package external.robot.common.enums;
import enums.ICommonEnum;
import lombok.Getter;
/**
* 类型转换
*/
@Getter
public enum TransformEnum implements ICommonEnum {
CODE_TO_VALUE("getValueByCode", "code到value的转换"),
TYPE_TO_VALUE("getValueByType","type到value的转换");
private final String code;
private final String value;
TransformEnum(String code, String value) {
this.code = code;
this.value = value;
}
@Override
public Integer getKey() { return Integer.parseInt(code); }
}
package external.robot.common.enums;
import enums.ICommonEnum;
import lombok.Getter;
/**
* @description: 异常编码枚举
*/
public enum ExceptionCode implements ICommonEnum {
SUCCESS(0,"成功"),
FAIL(201,"操作失败"),
NO_AUTHORIZATION(204,"无权访问"),
ERROR(400,"错误请求"),
MISSING_PARAMETERS(401,"参数缺失"),
MISSING_REQUIRED_PARAMETERS(402,"缺少必要参数"),
VERIFICATION_FAILED(404,"验证不通过"),
SYSTEM_ERROR(500,"服务器繁忙...");
@Getter
private String value;
@Getter
private Integer key;
ExceptionCode(Integer key, String value) {
this.key=key;
this.value = value;
}
@Override
public String getCode() { return key.toString(); }
}
验证工具类
package external.robot.common.util;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import external.robot.common.annotations.Required;
import external.robot.common.dto.BaseException;
import utils.ReflectUtil;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
public class CheckUtil {
public static ExecutorService robotExecutor = ThreadUtil.newExecutor(4);
/**
* <p>验证对象是否通过验证</p>
* @param object 待验证的对象
* @return
* */
public static boolean isRequiredPass(Object object) throws Exception {
Class<?> clz = object.getClass();
Map<String, Field> fieldMap = ReflectUtil.getClassField(clz);
Iterator<Field> iterator = fieldMap.values().iterator();
while(iterator.hasNext()){
Field field = iterator.next();
Required required = field.getAnnotation(Required.class);
if(null==required){ continue; }
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clz);
Method method = propertyDescriptor.getReadMethod();
Object value = method.invoke(object);
if(null==value){
String errorMessage = required.errorMsg();
errorMessage = StrUtil.isBlank(errorMessage)?String.format("%s为必填参数!",field.getName()):errorMessage;
throw new BaseException(errorMessage);
}
boolean parse = required.classParse();
// 如果注解中的 classParse 不为 true,则不进行解释
if(!parse){ continue; }
boolean _primitive = ReflectUtil.isPrimitive(field.getDeclaringClass());
// 如果是基本类型或包装类型则不进行解释
if(_primitive){continue;}
Map<String, Field> _map = ReflectUtil.getClassField(value.getClass());
boolean pass = isRequiredPass(value); // TODO 这里递归有bug ....
if(!pass){ return Boolean.FALSE; }
}
return true;
}
}
钉钉发送消息(文本,图片,链接,是否@所有人)对应的实体
package external.robot.dingding.entity;
import external.robot.common.annotations.Required;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BaseRequest<T> {
/**
* <p>时间戳</p>
* */
@Required(errorMsg = "时间戳不能为空或null",remark="时间戳",classParse = false)
private long timestamp;
/**
* <p>密钥</p>
*/
@Required(errorMsg = "密钥不能为空",remark="加签的密钥",classParse = false)
private String secret;
@Required(errorMsg = "消息类型不能为空",remark="消息类型",classParse = false)
private String msgtype;
@Required(errorMsg = "访问令牌不能为空",remark="访问令牌",classParse = false)
private String accessToken;
}
package external.robot.dingding.entity;
import external.robot.common.annotations.Required;
import external.robot.dingding.enums.DingTalkEnum;
import lombok.Data;
@Data
public class DingActionCardRequest extends BaseRequest {
@Required(errorMsg = "actionCard不能为空",remark="actionCard",classParse = true)
private ActionCard actionCard;
public DingActionCardRequest(ActionCard actionCard) {
super.setMsgtype(DingTalkEnum.MSG_TYPE.ACTION_CARD.getCode());
this.actionCard = actionCard;
super.setTimestamp(System.currentTimeMillis());
}
public DingActionCardRequest(String title, String text, String singleTitle, String singleURL, DingTalkEnum.BTN_ORIENTATION btnOrientation) {
super.setMsgtype(DingTalkEnum.MSG_TYPE.ACTION_CARD.getCode());
this.actionCard = new ActionCard(title,text,singleTitle,singleURL,btnOrientation);
super.setTimestamp(System.currentTimeMillis());
}
public DingActionCardRequest(String title, String text, String singleTitle, String singleURL) {
this(title,text,singleTitle,singleURL, DingTalkEnum.BTN_ORIENTATION.STANDARD);
}
@Data
public static class ActionCard{
@Required(errorMsg = "首屏会话透出的展示内容不能为空",remark="首屏会话透出的展示内容",classParse = false)
private String title;
@Required(errorMsg = "消息内容不能为空",remark="markdown格式的消息",classParse = false)
private String text;
@Required(errorMsg = "按钮的标题不能为空",remark="单个按钮的标题,注意:(设置此项和singleURL后,btns无效)。",classParse = false)
private String singleTitle;
@Required(errorMsg = "跳转的URL不能为空",remark="点击消息跳转的URL,打开方式如下:移动端(在钉钉客户端内打开),PC端(默认侧边栏打开)",classParse = false)
private String singleURL;
// --------------- 非必填 ---------------
/**
* <p>按钮排列方向(0:按钮竖直排列、1:按钮横向排列)</p>
* */
private int btnOrientation;
// --------------- 构建函数 ---------------
public ActionCard(String title, String text, String singleTitle, String singleURL){
this(title,text,singleTitle,singleURL, DingTalkEnum.BTN_ORIENTATION.STANDARD);
}
public ActionCard(String title, String text, String singleTitle, String singleURL, DingTalkEnum.BTN_ORIENTATION btnOrientation) {
this.title = title;
this.text = text;
this.singleTitle = singleTitle;
this.singleURL = singleURL;
this.btnOrientation = btnOrientation.getKey();
}
}
}
package external.robot.dingding.entity;
import external.robot.common.annotations.Required;
import external.robot.dingding.enums.DingTalkEnum;
import lombok.Data;
/**
* @category 带链接的消息
*/
@Data
public class DingLinkRequest extends BaseRequest<DingLinkRequest> {
@Required(errorMsg = "link不能为空",remark="link",classParse = true)
private Link link;
public DingLinkRequest(String title, String text, String messageUrl){
this(new Link(title,text,messageUrl,null));
}
public DingLinkRequest(String title, String text, String messageUrl, String picUrl){
this(new Link(title,text,messageUrl,picUrl));
}
public DingLinkRequest(Link link) {
super.setMsgtype(DingTalkEnum.MSG_TYPE.LINK.getCode());
this.link = link;
super.setTimestamp(System.currentTimeMillis());
}
public DingLinkRequest(){super();}
@Data
public static class Link {
@Required(errorMsg = "消息标题不能为空",remark="消息标题",classParse = false)
private String title;
@Required(errorMsg = "消息内容不能为空",remark="消息内容",classParse = false)
private String text;
@Required(errorMsg = "跳转的URL不能为空",remark="跳转的URL",classParse = false)
private String messageUrl;
// --------------- 非必填 ---------------
private String picUrl;
// --------------- 构建函数 ---------------
public Link(String title, String text, String messageUrl, String picUrl) {
this.title = title;
this.text = text;
this.messageUrl = messageUrl;
this.picUrl = picUrl;
}
public Link(String title, String text, String messageUrl){
this(title,text,messageUrl,null);
}
}
}
package external.robot.dingding.entity;
import external.robot.common.annotations.Required;
import external.robot.dingding.enums.DingTalkEnum;
import lombok.Data;
@Data
public class DingMarkDownRequest extends BaseRequest {
@Required(errorMsg = "markdown不能为空",remark="markdown",classParse = true)
private Markdown markdown;
// --------------- 非必填 ---------------
private At at;
// --------------- 构建函数 ---------------
public DingMarkDownRequest(Markdown markdown, At at) {
super.setMsgtype(DingTalkEnum.MSG_TYPE.MARKDOWN.getCode());
this.markdown = markdown;
this.at = at;
super.setTimestamp(System.currentTimeMillis());
}
public DingMarkDownRequest(Markdown markdown){
this(markdown,null);
}
public DingMarkDownRequest(String title, String text){
this(new Markdown(title,text),null);
}
// -------------------------->> 内部类 <<--------------------------
@Data
public static class Markdown{
@Required(errorMsg = "首屏会话透出的展示内容不能为空!",remark = "首屏会话透出的展示内容",classParse = false)
private String title;
@Required(errorMsg = "消息不能为空!",remark = "markdown格式的消息",classParse = false)
private String text;
public Markdown(String title, String text) {
this.title = title;
this.text = text;
}
}
@Data
public static class At{
/**
* <p>被@人的手机号(注意:在text内容里要有@人的手机号,只有在群内的成员才可被@,非群内成员手机号会被脱敏)</p>
* */
private String[] atMobiles;
/**
* <p>被@人的用户userid(注意 在content里添加@人的userid)</p>
* */
private String[] atUserIds;
/**
* <p>是否@所有人</p>
* */
private boolean isAtAll;
public At(String[] atMobiles, String[] atUserIds, boolean isAtAll) {
this.atMobiles = atMobiles;
this.atUserIds = atUserIds;
this.isAtAll = isAtAll;
}
}
}
package external.robot.dingding.entity;
import external.robot.common.annotations.Required;
import external.robot.dingding.enums.DingTalkEnum;
import lombok.Data;
import java.util.List;
@Data
public class DingTextRequest extends BaseRequest {
@Required(errorMsg = "text不能为空",remark="text",classParse = true)
private Text text;
private At at;
@Data
public static class At{
/**
* <p>是否@所有人</p>
* */
private boolean isAtAll;
/**
* <p>注意:在content里添加@人的手机号,且只有在群内的成员才可被@,非群内成员手机号会被脱敏。</p>
* */
private List<String> atMobiles;
/**
* <p>被@人的用户userid。注意:在content里添加@人的userid。</p>
* */
private List<String> atUserIds;
}
@Data
public static class Text {
@Required(errorMsg = "消息内容不能为空",remark="消息内容",classParse = false)
private String content;
public Text(String content) { this.content = content; }
}
public DingTextRequest(){super();}
public DingTextRequest(String message, At at) {
super.setMsgtype(DingTalkEnum.MSG_TYPE.TEXT.getCode());
this.text = new Text(message);
this.at = at;
super.setTimestamp(System.currentTimeMillis());
}
public DingTextRequest(String message){ this(message,null); }
}
钉钉需要的枚举类
package external.robot.dingding.enums;
import enums.ICommonEnum;
import external.robot.dingding.entity.*;
import external.robot.dingding.service.*;
import lombok.Getter;
/***
** @category 钉钉Talk枚举
**/
public class DingTalkEnum {
@Getter
/**
* <p>消息类型</p>
* */
public enum MSG_TYPE implements ICommonEnum {
TEXT( "text","文本消息", TextMsgService.class, DingTextRequest.class),
LINK("link","带URL链接的消息", LinkMsgService.class, DingLinkRequest.class),
MARKDOWN("markdown","markdown消息", MarkDownMsgService.class, DingMarkDownRequest.class),
ACTION_CARD("actionCard","ActionCard消息", ActionCardMsgService.class, DingActionCardRequest.class),
FEED_CARD("feedCard","feedCard消息");
private final String code;
private final String value;
private final Class<?extends AbsDingTalkMessage> service;
private final Class<?extends BaseRequest> request;
MSG_TYPE(String code, String value){ this(code,value,null,null); }
MSG_TYPE(String code, String value, Class<?extends AbsDingTalkMessage> service, Class<?extends BaseRequest> request) {
this.code = code;
this.value = value;
this.service=service;
this.request=request;
}
@Override
public Integer getKey() { return null; }
}
/**
* <p>按钮排列方向</p>
* */
@Getter
public enum BTN_ORIENTATION implements ICommonEnum{
VERTICAL("0","按钮竖直排列"),
STANDARD("1","按钮横向排列");
private final String code;
private final String value;
BTN_ORIENTATION(String code, String value) {
this.code = code;
this.value = value;
}
@Override
public Integer getKey() { return Integer.parseInt(code); }
}
}
机器人扩展接口
package external.robot.dingding.service.interfaces;
import enums.ICommonEnum;
/**
* @category 机器人扩展接口
*/
public interface IRobot<T extends Enum> extends ICommonEnum {
/**
* <p>群编码</p>
* */
String getGroupCode();
/**
* <p>群名称</p>
* */
String getGroupName();
/**
* <p>访问令牌</p>
* */
String getAccessToken();
}
package external.robot.dingding.service;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import enums.EncodingEnum;
import external.robot.common.dto.RobotResponse;
import external.robot.common.enums.AlgorithmEnum;
import external.robot.common.enums.ExceptionCode;
import external.robot.common.util.CheckUtil;
import external.robot.dingding.entity.BaseRequest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
public abstract class AbsDingTalkMessage {
/**
* <p>处理请求(子类需要根据不同场景实现)</p>
* @param request
* @return
* */
public abstract <T> String handle(BaseRequest<T> request);
/**
* <p>处理请求</p>
* @param request
* @return
* */
public <T> RobotResponse doHandle(BaseRequest<T> request) throws Exception {
boolean pass = CheckUtil.isRequiredPass(request);
if(!pass){return new RobotResponse(ExceptionCode.VERIFICATION_FAILED);}
String result = handle(request);
return JSONUtil.toBean(new JSONObject(result), RobotResponse.class);
}
/**
* <p>加签(把timestamp+"\n"+secret当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集))</p>
* @param timestamp
* @param secret
* @return
* */
protected static String getSign(long timestamp,String secret) throws Exception {
String stringToSign = String.format("%s\n%s",timestamp,secret);
Mac mac = Mac.getInstance(AlgorithmEnum.HmacSHA256.getCode());
mac.init(new SecretKeySpec(secret.getBytes(EncodingEnum.UTF_8.getCode()), AlgorithmEnum.HmacSHA256.getCode()));
byte[] signData = mac.doFinal(stringToSign.getBytes(EncodingEnum.UTF_8.getCode()));
return URLEncoder.encode(Base64.encode(signData),EncodingEnum.UTF_8.getCode());
}
/**
* <p>发送消息</p>
* @param request 待发送的消息
* @return
* */
protected static <T> String send(BaseRequest<T> request){
try {
long timestamp = System.currentTimeMillis();
String sign = getSign(timestamp,request.getSecret());
//钉钉机器人地址(配置机器人的webhook)
String params = String.format("?access_token=%s×tamp=%s&sign=%s",new Object[]{request.getAccessToken(),timestamp,sign});
String dingUrl = String.format("https://oapi.dingtalk.com/robot/send%s",params);
//推送消息(http请求)
return HttpUtil.post(dingUrl, JSONUtil.toJsonStr(request));
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
package external.robot.dingding.service;
import external.robot.dingding.entity.BaseRequest;
public class ActionCardMsgService extends AbsDingTalkMessage {
@Override
public String handle(BaseRequest request) {
return send(request);
}
}
package external.robot.dingding.service;
import external.robot.dingding.entity.BaseRequest;
public class LinkMsgService extends AbsDingTalkMessage {
@Override
public String handle(BaseRequest request) {
return send(request);
}
}
package external.robot.dingding.service;
import external.robot.dingding.entity.BaseRequest;
public class MarkDownMsgService extends AbsDingTalkMessage {
@Override
public String handle(BaseRequest request) {
return send(request);
}
}
package external.robot.dingding.service;
import external.robot.dingding.entity.BaseRequest;
public class TextMsgService extends AbsDingTalkMessage {
@Override
public String handle(BaseRequest request) {
return send(request);
}
}
钉钉发送消息工具类
package external.robot.dingding.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import external.config.RobotDingConf;
import external.robot.common.util.CheckUtil;
import external.robot.dingding.entity.*;
import external.robot.dingding.enums.DingTalkEnum;
import utils.EnumUtil;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class DingTalkUtil {
/**
* <p>发送钉钉消息</p>
*
* @param jsonParams 待发送的消息
* @return
*/
public static void sendMessage(String jsonParams) {
BaseRequest request = JSONUtil.toBean(jsonParams, BaseRequest.class);
if (null == request) {
return;
}
DingTalkEnum.MSG_TYPE msgTypeEnum = EnumUtil.getEnumByCode(DingTalkEnum.MSG_TYPE.class, request.getMsgtype());
if (null == msgTypeEnum) {
return;
}
sendMessage(JSONUtil.toBean(jsonParams, msgTypeEnum.getRequest()));
}
/**
* <p>发送钉钉消息</p>
*
* @param paramsMap 待发送的消息
* @return
*/
public static void sendMessage(Map<String, Object> paramsMap) {
sendMessage(JSONUtil.toJsonStr(paramsMap));
}
public static void sendMessage(String title, String text, String url) {
BaseRequest request = new DingTextRequest(text);
if (StrUtil.isNotBlank(url)) {
int result = new Random().nextInt(3);
request = result == 0 ? new DingMarkDownRequest(title, String.format("> %s 
 %s", title, text)) : result == 1 ? new DingLinkRequest(title, text, url) : new DingActionCardRequest(title, text, title, url);
}
sendMessage(request);
}
/**
* <p>发送钉钉消息</p>
*
* @param request 待发送的请求消息
* @return
*/
public static <T extends BaseRequest> void sendMessage(T request) {
if (null == request) {
return;
}
DingTalkEnum.MSG_TYPE MSG_TYPE_ENUM = EnumUtil.getEnumByCode(DingTalkEnum.MSG_TYPE.class, request.getMsgtype());
RobotDingConf.DingDto robot = selectRobot();
if (null == MSG_TYPE_ENUM || null == robot) {
return;
}
CheckUtil.robotExecutor.execute(() -> {
request.setSecret(robot.getSecretKey());
request.setAccessToken(robot.getAccessToken());
try {
MSG_TYPE_ENUM.getService().newInstance().doHandle(request);
} catch (Exception e) {
e.printStackTrace();
}
});
}
/**
* <p>采用轮询算法,获取某一个机器人</p>
* <p>因为钉钉每个机器人每分钟发送的消息频率为30条,超过则会屏蔽掉</p>
*/
private static Integer index = 0;
private static RobotDingConf.DingDto selectRobot() {
RobotDingConf.DingDto robot = null;
List<RobotDingConf.DingDto> robotList = RobotDingConf.getInstance().getList();
if (CollUtil.isEmpty(robotList)) {
return null;
}
synchronized (index) {
// 下标复位
if (index >= robotList.size()) {
index = 0;
}
robot = robotList.get(index);
index++;
}
return robot;
}
}
UTF-8枚举类和通用枚举类接口
package enums;
import lombok.Getter;
@Getter
public enum EncodingEnum implements ICommonEnum {
UTF_8("UTF-8","utf-8编码"),
GBK("GBK","GBK编码");
private final String code;
private final String value;
EncodingEnum(String code, String value) {
this.code = code;
this.value = value;
}
@Override
public Integer getKey() { return null; }
}
package enums;
/**
* <p>通用枚举接口</p>
*/
public interface ICommonEnum {
/**code(key) */
default String getCode() {return null;}
/**value */
String getValue();
/**当code值为数字类型时,在调用getKey时会将字符类型转换成Integer类型方便调用*/
Integer getKey();
}
钉钉机器人配置
package external.config;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
/**
* <p>钉钉机器人配置</p>
*/
@Data
@Component
@ConfigurationProperties(prefix = "robot.ding")
public class RobotDingConf {
private List<DingDto> list;
private static volatile RobotDingConf instance;
private RobotDingConf(){}
public static synchronized RobotDingConf getInstance(){
if(null==instance){
synchronized (RobotDingConf.class){
if(null==instance){
instance = new RobotDingConf();
}
}
}
return instance;
}
@PostConstruct
public void init (){
RobotDingConf conf = RobotDingConf.getInstance();
conf.setList(list);
}
@Data
@NoArgsConstructor
public static class DingDto{
private String accessToken;
private String secretKey;
public DingDto(String accessToken, String secretKey) {
this.accessToken = accessToken;
this.secretKey = secretKey;
}
}
}
yml配置
spring:
profiles:
active: @profiles.active@
mybatis-plus:
mapper-locations: classpath*:mybatis/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
robot:
wechat:
list:
- ***************
-
ding:
list:
- accessToken: **********
secretKey: *************