Dubbo封装rest服务返回结果

由于Dubbo服务考虑到一个是给其他系统通过RPC调用,另外一个是提供HTTP协议本身系统的后台管理页面,因此Dubbo返回参数在rest返回的时候配置拦截器进行处理。 在拦截器中,对返回参数封装成如下对象,并统一输出到前端。 View Code 需要继承的服务处理类有(按照实际调用顺序)ExceptionMapper, ContainerResponseFilter, WriterInterceptor 。 1. ExceptionMapper 用于后台返回异常结果的封装处理,需要对异常类进行区别对待,并返回错误提示信息。 复制代码 /** * 异常拦截 */ @Override public Response toResponse(Exception e) { // System.err.println("进入结果处理——toResponse"); String errMsg = e.getMessage(); JsonResult result = new JsonResult<>(false, StringUtils.isEmpty(errMsg)? "系统异常" : errMsg); if(javax.ws.rs.ClientErrorException.class.isAssignableFrom(e.getClass())){ ClientErrorException ex = (ClientErrorException) e; LOGGER.error("请求错误:" + e.getMessage()); return ex.getResponse(); }     if(e instanceof BaseException){ // 后台自定义异常,用于传递异常参数 BaseException ex = (BaseException) e; result.setData(ex.getErrorParams()); } LOGGER.error(errMsg, e); return Response.status(200).entity(result).build(); } 复制代码 2.ContainerResponseFilter 可用于服务端返回状态码进行处理,由于方法返回类型是 void,或者某个资源类型返回是 null 的情况,JAX-RS 框架一般会返回状态204,表示请求处理成功但没有响应内容。因此在此处我们对返回值封装成200-处理成功,数据为空的情况。 复制代码 @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { // System.err.println("进入结果处理——filter"); // 它的目的是专门处理方法返回类型是 void,或者某个资源类型返回是 null 的情况, // 这种情况下JAX-RS 框架一般会返回状态204,表示请求处理成功但没有响应内容。 我们对这种情况也重新处理改为操作成功 String wrapTag = requestContext.getProperty("Not-Wrap-Result") == null ? "" : requestContext.getProperty("Not-Wrap-Result").toString(); // 客户端显示提醒不要对返回值进行封装 if (StringUtils.isBlank(wrapTag) &&responseContext.getStatus() == 204 && !responseContext.hasEntity()){ responseContext.setStatus(200); responseContext.setEntity(new JsonResult<>(true, "执行成功")); responseContext.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); } } 复制代码 3.WriterInterceptor 用于服务端返回值的写入处理,进入到此处的一般都是执行成功的返回值。 复制代码 @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { // System.err.println("进入结果处理——aroundWriteTo"); // 针对需要封装的请求对结构进行封装处理。这里需要注意的是对返回类型已经是封装类(比如:异常处理器的响应或者204处理可能已经是封装类型)时要忽略掉。 Object originalObj = context.getEntity(); String wrapTag = context.getProperty("Not-Wrap-Result") == null ? "" : context.getProperty("Not-Wrap-Result").toString(); // 客户端通过head参数显示提醒不要对返回值进行封装 Boolean wraped = originalObj instanceof JsonResult; // 已经被封装过了的,不用再次封装 if (StringUtils.isBlank(wrapTag) && !wraped){ JsonResult result = new JsonResult<>(true, "执行成功"); result.setData(context.getEntity()); context.setEntity(result); // 以下两处set避免出现Json序列化的时候,对象类型不符的错误 context.setType(result.getClass()); context.setGenericType(result.getClass().getGenericSuperclass()); } context.proceed(); } 复制代码 以上代码即完成了返回值的封装,如果有其他异常类型还需要特殊处理,在ExceptionMapper增加异常判断。 完成代码如下: View Code 异常处理的时候,比较容易出现异常 org.jboss.resteasy.spi.UnhandledException: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.wjs.common.web.JsonResult of media type: text/html;charset=UTF-8 org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209) org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:230) org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:139) 这种情况一般是有什么特殊异常,在toResponse中没有进行特殊处理,Response中.entity(result)放入了返回对象无法解析造成。处理方式参考(e instanceof javax.ws.rs.NotFoundException)增加异常的特殊处理即可。https://www.cnblogs.com/loveyou/p/9550321.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信