首页 > 其他分享 >记录一次全局异常告警@ExceptionHandler和HandlerExceptionResolver的问题

记录一次全局异常告警@ExceptionHandler和HandlerExceptionResolver的问题

时间:2023-05-17 15:34:41浏览次数:39  
标签:void ExceptionHandler HandlerExceptionResolver ex Override import 告警 public Resu

          最近有同事说之前写的全局异常告警,如果有@Valid的注解,在接入新写的插件告警后,返回信息不打印了。全局异常是基于@ExceptionHandler的全局异常类,主要是Servlet MVC的ModelAndView返回的错误信息的捕获。代码如下:

    

 

/**
 * @author xxx
 */
@RestControllerAdvice
public class DefaultGlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(DefaultGlobalExceptionHandler.class);
    /**
     * @param ex
     * @return 响应对象
     * @description 基础异常
     */
    @ExceptionHandler(value = {BaseException.class})
    public Result baseException(BaseException ex) {
        log.error("baseException:{}", ex);
        return Result.fail(ex.getErrorCode(), ex.getErrorMsg());
    }

    @ExceptionHandler(value = {Exception.class})
    public Result exception(Exception ex) {
        log.error("Exception:{}", ex);
        return Result.fail();
    }

    @ExceptionHandler(value = {MaxUploadSizeExceededException.class})
    public Result exception(MaxUploadSizeExceededException ex) {
        log.error("RuntimeException:{}", ex);
        return Result.error(CommonResultStatus.COMMON_ERROR_UPLOAD_SIZE_EXCEED.getCode(),"上传文件大小超出限制!");
    }

    @ExceptionHandler(value = {RuntimeException.class})
    public Result exception(RuntimeException ex) {
        log.error("RuntimeException:{}", ex);
        return Result.fail();
    }

   /**
    * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
    *
    * @param ex
    * @return com.gwm.marketing.common.result.Result
    * @author xxx
    * @date 15:01 2021/6/11
    */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result validExceptionHandler(BindException ex) {
        String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        return Result.error(CommonResultStatus.COMMON_INVALID_PARAM.getCode(),CommonResultStatus.COMMON_INVALID_PARAM.getMessage()+":["+message+"]");
    }

    /**
     * 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常
     *
     * @param ex
     * @return  
     * @author  
     * @date 15:15 2021/6/11
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
        String message = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","));
        return Result.error(CommonResultStatus.COMMON_INVALID_PARAM.getCode(),CommonResultStatus.COMMON_INVALID_PARAM.getMessage()+":["+message+"]");
    }

    /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常
     *
     * @param ex
     * @return com.gwm.marketing.common.result.Result
     * @author xxx
     * @date 15:16 2021/6/11
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        return Result.error(CommonResultStatus.COMMON_INVALID_PARAM.getCode(),CommonResultStatus.COMMON_INVALID_PARAM.getMessage()+":["+message+"]");
    }


    @ExceptionHandler(value = {Throwable.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result throable() {
        return Result.fail();
    }
}

       加入的插件告警是基于@WebMvcConfigurer,里面重写了对于异常的处理,重写了HandlerExceptionResolver,如果有异常信息,通过钉钉告警的方式实时通知。加了这么一个功能。同事给我说了之后,我本地使用postman发现本地是能复现的,于是开始一点点的调试追踪。

   首先是重写WebMvcConfigurer

    

package com.gwm.marketing.filter;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gwm.marketing.filter.exception.DingdingHandleException;
import com.gwm.marketing.filter.intercepter.*;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
 * @Author fanht
 * @Description 拦截器参数校验
 * @Date 2021/11/12 2:05 下午
 * @Version 1.0
 */
@Configuration
public class OraDingdingConfigurer implements WebMvcConfigurer, Interceptor {

    /**
     * 拦截器参数校验
     *
     * @param interceptorRegistry
     */
    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry) {
        //注意拦截器的顺序
        interceptorRegistry.addInterceptor(new CharacterValidInterceptors());
        interceptorRegistry.addInterceptor(new HttpParamVerifyInterceptor());
        interceptorRegistry.addInterceptor(new HttpRequestStatisticsInterceptor());
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) {

    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) {

    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {

    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {

    }

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {

    }


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {

    }

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {

    }

    @Override
    public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {

    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {

    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {

    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {

    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> list) {

    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> list) {
        //新版本中的
        Optional<HttpMessageConverter<?>> optional = list.stream()
                .filter(o -> o instanceof MappingJackson2HttpMessageConverter)
                .findFirst();
        if (optional.isPresent()) {
            MappingJackson2HttpMessageConverter converter =
                    (MappingJackson2HttpMessageConverter) optional.get();
            ObjectMapper mapper = converter.getObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        }
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
    }

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
        //todo 添加全局异常,因为HandlerInterceptor不能显示异常 之前是写到了configureHandlerExceptionResolvers 里面,使用哪个会和全局异常DefaultGlobalExceptionHandler有先后顺序问题
       list.add(0,new DingdingHandleException());
    }

    @Override
    public Validator getValidator() {
        return null;
    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        Request request = chain.request();
        return chain.proceed(request);
    }

    @Bean
    public DispatcherServlet dispatcherServlet(){
        return new OraDispatcherServlet();
    }

}

 

    原来我是直接实现configureHandlerExceptionResolvers,在

@Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
        list.add(new DingdingHandleException());
    }

  

DingdingHandleException()代码如下

    但是每次调试发现,哪个全局异常确实是走到了,但是在走到下一步的ModelAndView的解析器时候,

标签:void,ExceptionHandler,HandlerExceptionResolver,ex,Override,import,告警,public,Resu
From: https://www.cnblogs.com/thinkingandworkinghard/p/17408899.html

相关文章

  • wazuh告警通过webhook推送到飞书
    使用wazuh自带的shuffle脚本实现 步骤:1.进入:/var/ossec/integrations复制shuffle、shuffle.py两个文件,并重命名为:custom-feishu、custom-feishu.py备注:一定要按这个方式命名,自定义告警前,都要加custom2.编辑custom-feishu.py,修改generate_msg函数: 3.如果想看告警......
  • @ExceptionHandler注解
    1,基本使用方法Spring的@ExceptionHandler可以用来统一处理方法抛出的异常,比如这样:@ExceptionHandler()publicStringhandleExeption2(Exceptionex){System.out.println("抛异常了:"+ex);ex.printStackTrace();StringresultStr="异常:默认";returnr......
  • 玩转Zabbix智能告警:降噪、排班、认领、升级、IM协同
    Zabbix作为一款流行的企业级监控工具,可以监控各种网络设备和服务的状态,并提供强大的告警功能,能够在出现异常情况时及时通知管理员。以下是Zabbix的一些特点:支持多种监控方式,包括SNMP、JMX、IPMI等,可以监控各种网络设备、服务器、虚拟化平台等;提供了丰富的监控项和模板,可以轻松......
  • alertmanager实现某个时间段静默某些告警项
    目录【0】解决思路分析【1】APIAPIVersionPOST/api/v2/alertsGET/api/v2/alertsGET/api/v2/alerts/groups【2】API使用实践(2.1)基本案例【3】最佳实践(定时静默)(3.1)立马构造出故障的告警信息(3.2)构建好静默,获取静默语句(3.3)使用生成静默规则(3.4)自动化脚本 ......
  • zabbix告警 Zabbix server: Utilization of housekeeper processes over 75% 解决方法
    原因分析为了防止数据库持续增大,Zabbix有自动删除历史数据的机制,即housekeeper,而在频繁清理历史数据的时候,MySQL数据库可能出现性能降低的情况,此时就会告警。一般来说,Zabbix都会监控ZabbixServer本身。如下所示,我们可以分析“Zabbixserver:Utilizationofhousekeeperinte......
  • SpringBoot中@ControllerAdvice/@RestControlAdvice+@ExceptionHandler实现全局异常捕
    场景在编写Controller接口时,为避免接口因为未知的异常导致返回不友好的结果和提示。如果不进行全局异常捕获则需要对每个接口进行try-catch或其他操作。 可以对Controller进行全局的异常捕获和处理,一旦发生异常,则返回通用的500响应码与通用错误提示。并将异常发生的具体的......
  • Linux部署Prometheus+Alertmanager并配置企业微信告警
    一、Prometheus告警简介告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。在Prometheus中一条告警规则主要由以下几部分组......
  • Linux部署Prometheus+Alertmanager并配置邮件告警
    一、Prometheus告警简介告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。在Prometheus中一条告警规则主要由以下几部分组......
  • Linux部署Prometheus+Alertmanager并配置钉钉告警
    一、Prometheus告警简介告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。在Prometheus中一条告警规则主要由以下几部分组......
  • python dingtalk钉钉群告警消息发布
    目录pythondingtalk钉钉群告警消息发布Dingtalk简介钉钉告警消息通知脚本pythondingtalk钉钉群告警消息发布公司用oprator部署的prometheus,理论上时可以直接通过alertmanager的配置。通过钉钉机器人的webhook向群里发送告警信息。但是想要格式化输出格式,并且规范化就成了问题......