文章目录
一、配置钉钉机器人
打开钉钉群聊天窗口,点击右上角三个点。
在群资料页面,点击【智能群助手】。
点击【添加机器人】。
选择自定义。
1、输入机器人名字,选择要发送消息的群 。
2、完成必要的安全设置,至少选择一种。
3、当选择了自定义关键词的时候,在发送报警信息时一定要带上关键词。
4、完成设置后,复制机器人的 Webhook 地址,后面用于向这个群发送消息。
https://oapi.dingtalk.com/robot/send?access_token=XXX
二、全局异常处理
1、自定义业务异常类
某些业务需要进行业务回滚,但 spring 的事务只针对 RuntimeException 进行回滚操作,所以需要回滚就要继承 RuntimeException。
public class CommonException extends RuntimeException{
private Integer errCode;
private String errMsg;
public Integer getErrCode() {
return errCode;
}
public void setErrCode(Integer errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public CommonException(Integer errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
public CommonException(String errMsg, Throwable e) {
super(errMsg);
this.errMsg = errMsg;
}
}
2、全局异常处理类
@ControllerAdvice
@Component
@Slf4j
public class CommonExceptionHandler {
@Autowired
private GlobalUtils globalUtils;
@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public Result handle(Exception exception) throws ApiException {
if (exception instanceof CommonException) {
log.error(exception.getMessage(), exception);
CommonException e = (CommonException) exception;
log.error("捕获到异常,异常代码为{},异常信息为{}", e.getErrCode(), e.getErrMsg());
//发送异常信息到钉钉机器人
globalUtils.globalMsg(exception);
return Result.error(new CodeMsg(e.getErrCode(), e.getErrMsg()));
} else if (exception instanceof HttpMessageNotReadableException) {
log.error("前台传入JSON格式错误");
//发送异常信息到钉钉机器人
globalUtils.globalMsg(exception);
return Result.error(CodeMsg.JSON_ERR);
} else {
//发送异常信息到钉钉机器人
globalUtils.globalMsg(exception);
log.error("捕获到异常错误");
return Result.error(CodeMsg.FILES);
}
}
}
三、工具类
1、CodeMsg 类
public class CodeMsg {
private int code;
private String msg;
public CodeMsg(int code, String msg) {
this.code = code;
this.msg = msg;
}
public CodeMsg() {
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public static CodeMsg SUCCESS = new CodeMsg(200, "success");
public static CodeMsg FILES = new CodeMsg(300, "未知错误");
public static CodeMsg JSON_ERR = new CodeMsg(300, "JSON格式错误");
}
2、Result 类
@ApiModel(value = "响应结果")
public class Result<T> {
@ApiModelProperty(position = 0, value = "状态码", required = true, example = "200200")
private int code;
@ApiModelProperty(position = 1, value = "响应信息", required = true, example = "success")
private String msg;
@ApiModelProperty(position = 2, value = "响应数据", required = true)
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* 成功时候的调用
*/
public static <T> Result<T> success(T data) {
return new Result<T>(data);
}
/**
* 失败时候的调用
*/
public static <T> Result<T> error(CodeMsg codeMsg) {
return new Result<T>(codeMsg);
}
/**
* 成功的构造函数
* @param data
*/
private Result(T data) {
this.code = 000000;//默认000000是成功
this.msg = "SUCCESS";
this.data = data;
}
public Result(int code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Result(CodeMsg codeMsg, T data) {
this.code = codeMsg.getCode();
this.msg = codeMsg.getMsg();
this.data = data;
}
/**
* 失败的构造函数
* @param code
* @param msg
*/
public Result(CodeMsg codeMsg) {
if (codeMsg != null) {
this.code = codeMsg.getCode();
this.msg = codeMsg.getMsg();
}
}
}
3、GlobalUtils 类
@Component
public class GlobalUtils {
@Autowired
private DingDing dingDing;
public void globalMsg(Exception exception) throws ApiException {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
exception.printStackTrace(pw);
String stackTraceString = sw.getBuffer().toString();
dingDing.sendMsg(stackTraceString);
}
}
四、整合钉钉机器人
1、Pom 导入依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>1.0.1</version>
</dependency>
2、发送信息的工具类
自定义机器人支持文本、链接、markdown、FeedCard 消息类型等。
@Component
public class DingDing {
public OapiRobotSendResponse sendMsg(String stackTraceString) throws ApiException {
String qm = qm();
// 前面复制的机器人 Webhook 地址,放进来,后面加上签名
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?access_token=XXX" + qm + "");
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("警报:" + stackTraceString + "");
request.setText(text);
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(Collections.singletonList("132xxxxxxxx"));
// isAtAll类型如果不为Boolean,请升级至最新SDK
// at.setIsAtAll(true);
// at.setAtUserIds(Arrays.asList("109929","32099"));
// request.setAt(at);
// request.setMsgtype("link");
// OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
// link.setMessageUrl("https://www.dingtalk.com/");
// link.setPicUrl("");
// link.setTitle("时代的火车向前开");
// link.setText("警报: 这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林");
// request.setLink(link);
// request.setMsgtype("markdown");
// OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
// markdown.setTitle("杭州天气");
// markdown.setText("警报: #### 杭州天气 @156xxxx8827\n" +
// "> 9度,西北风1级,空气良89,相对温度73%\n\n" +
// "> \n" +
// "> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) \n");
// request.setMarkdown(markdown);
return client.execute(request);
}
@SneakyThrows
public static String qm() {
Long timestamp = System.currentTimeMillis();
String secret = "this is secret";
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
System.out.println(sign);
return "×tamp=" + timestamp + "&sign=" + sign + "";
}
}
3、测试启动
控制类
@RestController
@RequestMapping("/permit-through/")
public class DingDingController {
@Resource
private TestService testService;
@GetMapping("/testw")
public Result test() {
testService.test();
return new Result(CodeMsg.FILES);
}
}
接口类
public interface TestService {
public void test();
}
实现类
@Service
public class TestServiceImpl implements TestService {
@Override
public void test() {
int i = 1 / 0;
}
}
群里显示结果