• 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设计的不太好。

  • 相关阅读:
    Vue2组件间通讯
    html 常见兼容性问题
    从头开发一个RISC-V的操作系统(四)嵌入式开发介绍
    文件批量从gbk转成utf8的工具
    如何设计一套单点登录系统 ?
    表单引擎的自定义控件的概念与设计
    (完整版)英语常用词组大全(2000词以上)
    弘玑Cyclone上榜36氪中国超自动化先锋企业
    ElasticSearch - 基于 JavaRestClient 操作索引库和文档
    算法:二元选择排序
  • 原文地址:https://www.cnblogs.com/lori/p/18236716