springboot项目exception异常信息推送至企业微信

1.问题起因

       有时候新项目上线,系统在实际生产环境下难免会产生那么些大大小小的问题,因为这些问题时常遭受到客户的消息轰炸。

       开发人员角度:看到客户的消息轰炸又不得不与之battle几句,完事了还得去翻日志定位问题所在,一顿操作下来问题定位到了,但是时间也已过半了。

       项目经理角度:可能项目经理也头疼这个问题,又要与客户battle还要与开发battle,时间成本高暂且不说,主要是烦啊。

2.解决方案

        为了解决这一问题,一开始考虑到实时的去监控每一个接口的数据,但是后面想到没有实际的意义,起不到快速反应快速定位的效果;后面想到去监控系统后台所有的异常信息,将系统捕捉到的异常信息推送到企业微信中,这样只要系统后台代码出现异常报错,都能通过企业微信将产生的异常信息推送到开发的群聊中,开发人员能在第一时间获取到报错的异常信息并处理。

3.具体实现

 3.1企业微信群添加群机器人获取webhook地址

       1.首先进入群聊点击群机器人,点击添加机器人,这样就能获取到机器人的webhook地址了。

        2.向企业微信机器人发送消息

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

@Component
@Slf4j
public class ExceptionMsgBot {
    
    /**
     * 企微机器人webhook地址
     */
    private String url = "这里放你的企微机器人webhook地址";

    /**
     * 是否启用
     */
    private Boolean isEnable = true;
    

    public void send(Exception e, HttpServletRequest request) {
        if (!isEnable) {
            return;
        }

        String title = "业务报警";

        //请求url
        String api = request.getRequestURL().toString();
        //请求参数
        String params = JSONUtil.toJsonStr(request.getAttribute("params"));
        if (!StringUtils.isEmpty(params)) {
            //将json转成普通string
            params = params.replace("\"","\\\"");
        }
        String textMsg = "{\n" +
                "    \"msgtype\": \"markdown\",\n" +
                "    \"markdown\": {\n" +
                "        \"content\": \"" + title + "\\n\n" +
                "         【接口路径url】: " + api + " \n" +
                "         【接口参数】: " + params + " \n" +
                "         【报错信息】: " + e.getMessage() + " \n" +
                "         【根本异常】: " + e.getCause() + " \n" +
                "         【异常信息】: " + e + "  \"\n" +

                "    }\n" +
                "}\n";

        //发送消息
        HttpResponse response = HttpRequest
                .post(url)
                .header(Header.CONTENT_TYPE, "application/json; charset=UTF-8")
                .body(textMsg)
                .execute();

        log.info("【异常消息发送结果】 {}", response.body());
    }
}

        3.设置全局异常处理类(处理所有由@RequestMapping注解修饰的类和方法中的异常,相当于监控了我们controller层中的所有接口),在全局异常处理类该类中调用ExceptionMsgBot类中的send()方法,将捕捉到的异常信息发送至企微机器人

package com.ruoyi.framework.web.exception;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;


/**
 * 全局异常处理器
 * 
 * @author ruoyi
 */
@RestControllerAdvice
public class GlobalExceptionHandler
{

    @Autowired
    private ExceptionMsgBot bot;

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 权限校验异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        bot.send(e,request);
        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
            HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        bot.send(e,request);
        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(ServiceException.class)
    public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
    {
        log.error(e.getMessage(), e);
        bot.send(e,request);
        Integer code = e.getCode();
        return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        bot.send(e,request);
        log.error("请求地址'{}',发生未知异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        bot.send(e,request);
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public AjaxResult handleBindException(BindException e,HttpServletRequest request)
    {
        log.error(e.getMessage(), e);
        bot.send(e,request);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
    {
        log.error(e.getMessage(), e);

        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(message);
    }

    /**
     * 演示模式异常
     */
    @ExceptionHandler(DemoModeException.class)
    public AjaxResult handleDemoModeException(DemoModeException e)
    {
        return AjaxResult.error("演示模式,不允许操作");
    }
}

    注:该全局异常处理类我使用的是若依框架的,使用时注意,你可以按它这个结构自己定义属于你的全局异常处理类(@RestControllerAdvice或@ControllerAdvice+@ExceptionHandler)

4.效果展示

       当有异常被全局异常处理类捕捉到时会调用ExceptionMsgBot类中的send()方法,将捕捉到的异常信息发送至企微机器人,效果如下:

要集成微信公众号的消息推送功能,可以使用Spring Boot和WeChat SDK。以下是一些步骤: 1. 在微信公众平台上创建一个公众号,并获得AppID和AppSecret。 2. 在Spring Boot项目中添加WeChat SDK依赖项。 3. 创建一个Controller类来处理微信服务器发送过来的请求,比如验证URL有效性和处理用户消息。 4. 配置服务器URL和Token,并在微信公众平台上进行验证。 5. 使用SDK提供的方法实现消息的回复和推送。 以下是一个简单的代码示例: ```java @RestController @RequestMapping("/wechat") public class WeChatController { @Autowired private WxMpService wxMpService; @GetMapping(produces = "text/plain;charset=utf-8") public String validate(@RequestParam(name = "signature") String signature, @RequestParam(name = "timestamp") String timestamp, @RequestParam(name = "nonce") String nonce, @RequestParam(name = "echostr") String echostr) { if (wxMpService.checkSignature(timestamp, nonce, signature)) { return echostr; } return "error"; } @PostMapping(produces = "application/xml; charset=UTF-8") public String handleMessage(@RequestBody String requestBody, @RequestParam(name = "signature") String signature, @RequestParam(name = "timestamp") String timestamp, @RequestParam(name = "nonce") String nonce, @RequestParam(name = "openid") String openid) { // 处理用户发送的消息 WxMpXmlMessage wxMessage; try { wxMessage = WxMpXmlMessage.fromXml(requestBody); } catch (Exception e) { return "error"; } // 构造回复消息 WxMpXmlOutMessage outMessage = WxMpXmlOutMessage.TEXT() .content("你好,欢迎关注我的公众号!") .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); return outMessage.toXml(); } } ``` 在上面的代码中,我们首先验证了微信服务器发送过来的请求是否有效。如果有效,我们返回echostr作为响应。接下来,我们处理用户发送的消息,并构造一个回复消息。最后,我们将回复消息作为响应返回给微信服务器。 请注意,我们使用了WxMpService类提供的方法来验证签名、解析消息和构造回复消息。要使用这个类,我们需要在Spring Boot项目的配置文件中添加以下内容: ``` # WeChat SDK wx.mp.appId=<your app ID> wx.mp.secret=<your app secret> wx.mp.token=<your token> wx.mp.aesKey=<your AES key> ``` 在上面的代码中,我们使用了WxMpXmlOutMessage.TEXT()方法来构造文本消息的回复。如果你需要回复其他类型的消息,比如图文消息或音频消息,请查看WeChat SDK的文档。 最后,我们需要在微信公众平台上配置服务器URL和Token。可以在公众号的基本配置页面中找到这些设置。在配置完成后,我们可以向公众号发送消息,然后观察是否收到了回复。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值