上一次的介绍,主要围绕如何统一去捕获异常,以及为每一种异常添加自己的Mapper实现,并且我们知道,当在ExceptionMapper中返回非200的Response,不支持application/json的响应类型,而是写死的text/plain类型。
Filter为二方包异常手动捕获
参考:https://blog.csdn.net/2401_84048290/article/details/138105184
我们来看看dubbo的源码进行分析,如果Dubbo的provider端 抛出异常(Throwable),则会被 provider端 的ExceptionFilter拦截到,执行以下invoke方法,里面有个实现Listener类,重写了onResponse,我们可以自定义filter来覆盖原来的ExceptionFilter,把自定义的异常通过RuntimeException进行包裹,然后在Mapper中进行统一的捕获。
- 添加CustomExceptionFilter类型,实现Filter和BaseFilter.Listener,重写onResponse方法,添加自定义代码,如下:
public class CustomExceptionFilter implements Filter, BaseFilter.Listener {public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {exception = appResponse.getException();String className = exception.getClass().getName();// 本项目的异常也直接抛出if (className.startsWith("com.myself.")) {appResponse.setException(new RuntimeException(exception));return;}// 其它原来ExceptionFilter中的代码}}public class CustomExceptionFilter implements Filter, BaseFilter.Listener { public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) { exception = appResponse.getException(); String className = exception.getClass().getName(); // 本项目的异常也直接抛出 if (className.startsWith("com.myself.")) { appResponse.setException(new RuntimeException(exception)); return; } // 其它原来ExceptionFilter中的代码 } }public class CustomExceptionFilter implements Filter, BaseFilter.Listener { public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) { exception = appResponse.getException(); String className = exception.getClass().getName(); // 本项目的异常也直接抛出 if (className.startsWith("com.myself.")) { appResponse.setException(new RuntimeException(exception)); return; } // 其它原来ExceptionFilter中的代码 } }
- META-INF中注册这个过滤器resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter
customExceptionFilter=com.xxx.register.exception.filter.CustomExceptionFiltercustomExceptionFilter=com.xxx.register.exception.filter.CustomExceptionFiltercustomExceptionFilter=com.xxx.register.exception.filter.CustomExceptionFilter
- 配置中文中注册,并移除默认的resources/application.properties
# 自定义过滤器,上面-exception就是dubbo默认的处理异常的filter,前面-号就代表去除,注意:不需要加双引号dubbo.provider.filter=customExceptionFilter,-exception# 自定义过滤器,上面-exception就是dubbo默认的处理异常的filter,前面-号就代表去除,注意:不需要加双引号 dubbo.provider.filter=customExceptionFilter,-exception# 自定义过滤器,上面-exception就是dubbo默认的处理异常的filter,前面-号就代表去除,注意:不需要加双引号 dubbo.provider.filter=customExceptionFilter,-exception
一个Mapper处理所有自定义异常
- 配置文件中指定mapper,resources/application.properties
dubbo.protocols.http.extension=com.xxx.register.exception.mapper.CustomExceptionMapperdubbo.protocols.http.extension=com.xxx.register.exception.mapper.CustomExceptionMapperdubbo.protocols.http.extension=com.xxx.register.exception.mapper.CustomExceptionMapper
- mapper源码如下
@Providerpublic class DbViolationExceptionMapper implements ExceptionMapper<RuntimeException> {@Overridepublic Response toResponse(RuntimeException exception) {Map<String, String> map = MapUtil.<String, String>builder().put("error", exception.getMessage()).build();if (exception.getCause() instanceof ForbiddenException) {return Response.status(Response.Status.FORBIDDEN).entity(map).type(MediaType.APPLICATION_JSON).build();}if (exception.getCause() instanceof CustomException) {return Response.status(Response.Status.BAD_REQUEST).entity(map).type(MediaType.APPLICATION_JSON).build();}if (exception.getCause() instanceof IdentityBrokerException) {return Response.status(Response.Status.UNAUTHORIZED).entity(map).type(MediaType.APPLICATION_JSON).build();}if (exception.getCause() instanceof UniqueException) {return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(map).type(MediaType.APPLICATION_JSON).build();}return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(MapUtil.builder().put("error", exception.getMessage()).build()).type(MediaType.APPLICATION_JSON).encoding("utf-8").build();// 非200的请求,这个type无效,一直是text/plain}}@Provider public class DbViolationExceptionMapper implements ExceptionMapper<RuntimeException> { @Override public Response toResponse(RuntimeException exception) { Map<String, String> map = MapUtil.<String, String>builder().put("error", exception.getMessage()).build(); if (exception.getCause() instanceof ForbiddenException) { return Response.status(Response.Status.FORBIDDEN).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof CustomException) { return Response.status(Response.Status.BAD_REQUEST).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof IdentityBrokerException) { return Response.status(Response.Status.UNAUTHORIZED).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof UniqueException) { return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(map).type(MediaType.APPLICATION_JSON) .build(); } return Response.status(Response.Status.SERVICE_UNAVAILABLE) .entity(MapUtil.builder().put("error", exception.getMessage()).build()).type(MediaType.APPLICATION_JSON) .encoding("utf-8").build();// 非200的请求,这个type无效,一直是text/plain } }@Provider public class DbViolationExceptionMapper implements ExceptionMapper<RuntimeException> { @Override public Response toResponse(RuntimeException exception) { Map<String, String> map = MapUtil.<String, String>builder().put("error", exception.getMessage()).build(); if (exception.getCause() instanceof ForbiddenException) { return Response.status(Response.Status.FORBIDDEN).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof CustomException) { return Response.status(Response.Status.BAD_REQUEST).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof IdentityBrokerException) { return Response.status(Response.Status.UNAUTHORIZED).entity(map).type(MediaType.APPLICATION_JSON).build(); } if (exception.getCause() instanceof UniqueException) { return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(map).type(MediaType.APPLICATION_JSON) .build(); } return Response.status(Response.Status.SERVICE_UNAVAILABLE) .entity(MapUtil.builder().put("error", exception.getMessage()).build()).type(MediaType.APPLICATION_JSON) .encoding("utf-8").build();// 非200的请求,这个type无效,一直是text/plain } }
未解决的问题
- 目前非200的请求,toResponse时,响应类型还是text/plain
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容