首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AI协作:借助腾讯云 AI 代码助手实现Springboot整合钉钉机器异常日志通知

AI协作:借助腾讯云 AI 代码助手实现Springboot整合钉钉机器异常日志通知

原创
作者头像
小明爱吃火锅
发布2025-09-19 15:07:45
发布2025-09-19 15:07:45
1460
举报
文章被收录于专栏:小明说Java小明说Java

前言

在现代微服务架构中,及时监控和响应系统异常对于保障系统的稳定性和可靠性至关重要。钉钉作为企业级通讯工具,提供了强大的机器人功能,可以方便地将系统异常信息实时推送到指定的群聊中。本文将介绍如何在Spring Boot项目中整合钉钉机器人,实现异常日志的自动通知功能。本文将利用腾讯云 AI 代码助手完成本次教程,腾讯云 AI 代码助手可以帮助开发者快速生成代码、优化现有代码,并提供技术指导。

引入依赖

首先,在项目的 pom.xml 文件中引入钉钉SDK依赖,以便与钉钉API进行交互。

代码语言:xml
复制
<!-- 引入钉钉SDK -->

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>alibaba-dingtalk-service-sdk</artifactId>
    <version>2.0.0</version>
</dependency>

注意:根据实际需要,可能需要调整版本号或使用其他钉钉SDK依赖。

定义全局异常捕获

为了捕获应用中的所有未处理异常,并将其发送到钉钉群聊中,我们需要定义一个全局异常处理器,这里就可以利用腾讯云 AI 代码助手,帮助生成。

代码语言:java
复制
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletRequest;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 全局异常处理
     * @param e 异常对象
     * @param request HTTP请求
     * @return 错误响应
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<?> exceptionHandler(Exception e, ServletRequest request){
        // 获取请求参数
        if (Objects.nonNull(request) && request instanceof ContentCachingRequestWrapper) {
            ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
            try {
                String requestBody = StringUtils.toEncodedString(
                    wrapper.getContentAsByteArray(),
                    Charset.forName(wrapper.getCharacterEncoding())
                );
                log.info("未知异常 request ip: {}, url: {}, body: {}", 
                    wrapper.getRemoteAddr(),
                    wrapper.getRequestURI(),
                    requestBody);
            } catch (Exception ex) {
                log.warn("解析请求体失败", ex);
            }
        }
        
        log.error("未知异常", e);
        
        // 通知钉钉
        DingTalkSendMsgUtil.sendToDingTalk(e);
        
        return Result.fail("系统异常,请联系管理员");
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<?> exceptionHandler(MethodArgumentNotValidException e) {
        log.debug("传入参数异常", e);
        String errorMessage = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        return Result.fail(errorMessage != null ? errorMessage : e.getMessage());
    }
}

/**
 * 请求包装过滤器,用于缓存请求体以便多次读取
 */
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    FilterChain filterChain) throws ServletException, IOException {
        filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse);
    }
}

定义钉钉推送工具类

首先,打开钉钉应用,可以找个测试群聊创建机器人。

配置完成后,系统会生成一个​​Webhook URL​​,这个URL就是后续钉钉群推送消息的接口地址,拷贝webhook。

接下来,需要定义一个工具类,用于将异常信息发送到钉钉群聊中,这里也可以使用腾讯云 AI 代码助手进行生成,最终代码如下:

代码语言:java
复制
import com.aliyun.dingtalk.api.DefaultDingTalkClient;
import com.aliyun.dingtalk.api.DingTalkClient;
import com.aliyun.dingtalk.api.request.OapiRobotSendRequest;
import com.aliyun.dingtalk.api.response.OapiRobotSendResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.output.StringWriter;
import org.apache.commons.io.output.PrintWriter;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class DingTalkSendMsgUtil {

    // 配置自己创建的钉钉群webhook - 实际使用时替换为真实token
    private static String WEBHOOK_URL = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_ACCESS_TOKEN";
    
    // 可选:设置签名密钥(如果启用了安全设置)
    // private static final String SECRET = "your_secret";
    
    /**
     * 发送异常信息到钉钉群聊
     * @param exception 异常对象
     */
    public static void sendToDingTalk(Exception exception) {
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            exception.printStackTrace(pw);
            
            DingTalkClient client = new DefaultDingTalkClient(WEBHOOK_URL);
            OapiRobotSendRequest req = new OapiRobotSendRequest();
            
            // 构建消息内容
            OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
            String traceId = MDC.get("traceId") != null ? MDC.get("traceId") : "N/A";
            text.setContent(String.format(
                "[系统异常通知]\n" +
                "TraceID: %s\n" +
                "异常时间: %s\n" +
                "异常信息:\n%s", 
                traceId, 
                java.time.LocalDateTime.now(), 
                sw.toString()
            ));
            
            req.setMsgtype("text");
            req.setText(text);
            
            // 如果启用了签名安全设置,需要添加签名
            // String timestamp = String.valueOf(System.currentTimeMillis());
            // String sign = SignUtil.sign(SECRET, timestamp);
            // req.setTimestamp(timestamp);
            // req.setSign(sign);
            
            OapiRobotSendResponse response = client.execute(req);
            
            if (!response.isSuccess()) {
                log.error("钉钉消息发送失败: {}", response.getErrmsg());
            }
            
        } catch (Exception e) {
            log.error("消息推送钉钉发送异常", e);
        }
    }
    
    /**
     * 发送富文本消息到钉钉群聊
     * @param title 消息标题
     * @param content 消息内容
     */
    public static void sendRichTextToDingTalk(String title, String content) {
        try {
            DingTalkClient client = new DefaultDingTalkClient(WEBHOOK_URL);
            OapiRobotSendRequest req = new OapiRobotSendRequest();
            req.setMsgtype("markdown");
            
            OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
            markdown.setTitle(title);
            markdown.setText(String.format(
                "### %s\n\n%s\n\n> **TraceID**: %s\n> **时间**: %s",
                title,
                content,
                MDC.get("traceId") != null ? MDC.get("traceId") : "N/A",
                java.time.LocalDateTime.now()
            ));
            
            req.setMarkdown(markdown);
            
            OapiRobotSendResponse response = client.execute(req);
            if (!response.isSuccess()) {
                log.error("钉钉富文本消息发送失败: {}", response.getErrmsg());
            }
            
        } catch (Exception e) {
            log.error("钉钉富文本消息发送异常", e);
        }
    }
}

注意事项:

  • 将 YOUR_ACCESS_TOKEN 替换为你在钉钉群中创建机器人时获取到的实际 access_token。
  • 确保项目中已经引入了钉钉SDK相关的依赖。

测试

为了验证异常通知功能是否正常工作,可以创建一个测试控制器,故意抛出一个异常。

代码语言:java
复制

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class DingdingExceptionController {

    @RequestMapping(value = "/dingding/excep", method = RequestMethod.POST)
    public void triggerException() {
        // 故意引发 ArithmeticException
        int i = 1 / 0; 
    }
    
    @RequestMapping(value = "/dingding/test", method = RequestMethod.GET)
    public void testDingTalk() {
        try {
            // 模拟业务异常
            throw new RuntimeException("测试异常 - 这是业务逻辑错误");
        } catch (Exception e) {
            DingTalkSendMsgUtil.sendToDingTalk(e);
        }
    }
}

测试步骤

  1. 启动Spring Boot应用
  2. 使用Postman或其他工具向http://localhost:8080/dingding/excep发送POST请求\ • 或者直接访问http://localhost:8080/dingding/test触发测试异常
  3. 观察钉钉群聊中是否收到包含异常信息的消息
  4. 检查日志中是否有发送失败的记录
  5. 高级配置

6.1 自定义消息格式

可以根据需要自定义消息格式,例如添加更多上下文信息:

代码语言:java
复制

public static void sendDetailedErrorToDingTalk(Exception exception, String contextInfo) {
    try {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        exception.printStackTrace(pw);
        
        DingTalkClient client = new DefaultDingTalkClient(WEBHOOK_URL);
        OapiRobotSendRequest req = new OapiRobotSendRequest();
        req.setMsgtype("markdown");
        
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("[严重错误] 系统异常通知");
        markdown.setText(String.format(
            "### [严重错误] 系统异常通知\n\n" +
            "**TraceID**: %s\n\n" +
            "#### 异常时间\n%s\n\n" +
            "#### 异常信息\n```java\n%s\n```\n\n" +
            "#### 上下文信息\n> %s\n\n" +
            "#### 请求信息\n> 请检查相关日志获取详细请求信息",
            MDC.get("traceId") != null ? MDC.get("traceId") : "N/A",
            java.time.LocalDateTime.now(),
            sw.toString(),
            contextInfo != null ? contextInfo : "无"
        ));
        
        req.setMarkdown(markdown);
        client.execute(req);
    } catch (Exception e) {
        log.error("发送详细错误消息到钉钉失败", e);
    }
}

6.2 异常分类处理

根据不同的异常类型发送不同级别的通知:

代码语言:java
复制

public static void handleException(Exception e) {
    if (e instanceof BusinessException) {
        // 业务异常,发送普通通知
        sendToDingTalk(e);
    } else if (e instanceof DatabaseException) {
        // 数据库异常,发送警告通知
        sendRichTextToDingTalk("数据库异常警告", e.getMessage());
    } else {
        // 其他严重异常,发送紧急通知
        sendRichTextToDingTalk("⚠️ 系统紧急异常 ⚠️", 
            "系统发生严重错误,请立即处理!\n\n" + e.getMessage());
    }
}

总结

通过上述步骤,我们成功地在Spring Boot项目中整合了钉钉机器人,实现了系统异常日志的自动通知功能。这不仅提高了开发团队对系统异常的响应速度,还增强了系统的可维护性和稳定性。在实际应用中,可以根据需求进一步优化异常处理逻辑,例如根据不同的异常类型发送不同的通知,或者集成更多的消息推送渠道。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 引入依赖
  • 定义全局异常捕获
  • 定义钉钉推送工具类
  • 测试
  • 测试步骤
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档