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

  • 相关阅读:
    JAVA生成20位LONG型UUID
    R语言读取(加载)txt格式数据为dataframe、为dataframe中的两个离散变量构建列联表
    NX二次开发-VS使用NXOpen向导创建项目失败,再次弹出创建向导对话框,解决办法
    docker基础
    2023/09/14 qt&c++
    聊聊从大模型来看NLP解决方案之UIE
    这个时代,让我们一起格局打开!【2022戴尔科技峰会预告】
    JavaScript---DOM---DOM简介、获取元素、事件基础、操作元素---11.5
    从经典学习 NLP:小白到大白:1. Word Tokenization
    浏览器运行机制
  • 原文地址:https://www.cnblogs.com/lori/p/18236716