• dubbo~全局异常拦截器的使用与设计缺陷


    异常拦截器ExceptionMapper

    在JAX-RS(Java API for RESTful Web Services)中,ExceptionMapper接口用于将Java异常映射到HTTP响应。通过实现ExceptionMapper接口,你可以自定义如何处理特定类型的异常,并生成相应的HTTP响应。

    优先级和选择

    当有多个ExceptionMapper可用于处理同一类型的异常时,JAX-RS会选择最具体的那个。例如,如果你有一个处理RuntimeException的ExceptionMapper和一个处理NullPointerException的ExceptionMapper,那么当抛出NullPointerException时,会选择处理NullPointerException的ExceptionMapper。

    定义自定义异常

     public class UniqueException extends RuntimeException {
    
    	public UniqueException(Throwable cause) {
    		super(cause);
    	}
    
    	public UniqueException(String message) {
    		super(message);
    	}
    
    	public UniqueException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    }
    

    实现ExceptionMapper

    /**
     * 数据表约束异常处理器.
     *
     * @author lind
     * @date 2024/6/4 10:45
     * @since 1.0.0
     */
    @Provider
    public class DbViolationExceptionMapper implements ExceptionMapper<UniqueException> {
    
    	@Override
    	public Response toResponse(UniqueException exception) {
    
    		return Response.status(Response.Status.BAD_REQUEST)
    				.entity(MapUtil.builder().put("error", exception.getMessage()).build()).type(MediaType.APPLICATION_JSON)
    				.encoding("utf-8").build();// 非200的请求,这个type无效,一直是text/plain
    
    		/*
    		 * return Response.status(Response.Status.OK)
    		 * .entity(MapUtil.builder().put("error", exception.getMessage()).build())
    		 * .type("application/json; charset=UTF-8").build();//
    		 * 200的请求,是可以使用application/json的
    		 *
    		 */
    	}
    
    }
    

    注册ExceptionMapper

    在文件resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports添加内容

    com.xx.exception.handler.DbViolationExceptionMapper
    

    业务代码直接抛出异常

    if (getCurrentUserId() == null || !getCurrentUserId().equals(userId)) {
    	throw new UniqueException("权限不足");
     }
    

    相关问题

    • 当在ExceptionMapper中返回的Response对象,状态码为200时,可以响应为application/json
    • 当Response对象状态码非200时,响应一直是text/plain

    经过调试与排查,发现当非200时,在这个过滤器org.apache.dubbo.rpc.protocol.rest.filter.ServiceInvokeRestFilter里,它出现了两个content-type,text/plain不知道是什么时间被加进去的,如图

    方法执行到这里时,为响应头添加了text/plain,事实上,在操作org.apache.dubbo.rpc.protocol.rest.netty.NettyHttpResponse对象的setStatus()方法时,它完成了默认content-type的强编码

    NettyHttpResponse的setStatus()方法如下,完成了强编码

    public void setStatus(int status) {
      if (status > 200) {
            this.addOutputHeaders(RestHeaderEnum.CONTENT_TYPE.getHeader(), MediaType.TEXT_PLAIN.value);
        }
    
        this.status = status;
    }
    

    这也是业务代码中,直接报出自定义异常,在ExceptionMapper捕获返回json没有生效的原因,这块感觉dubbo设计的不太好。

  • 相关阅读:
    什么是 Cooke、Session 和 Token?
    440-C++基础语法(91-100)
    Java与Redis的集成
    postCss基本介绍
    pgsql优势,pgsql安装(centOs),pgagent安装
    这有几个常见的电脑故障解决方法,需要的朋友快来
    接口测试--Postman变量
    Apache Airflow (二) : Airflow单机搭建
    Android之Gradle和Gradle插件区别及联系
    推荐一款可以下载B站视频和音频的工具
  • 原文地址:https://www.cnblogs.com/lori/p/18236716