ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Cloud 统一异常处理和统一返回

2019-07-09 16:03:24  阅读:256  来源: 互联网

标签:body code return String Spring data public Cloud 统一


1、前言

    在业务系统中,我们一般希望所有请求放回的类型都是固定的,如:{"code":0,"message":"",data:{"id":1,"name":"zhangsan"}}, 用code表示成功还是失败,message记录失败信息,如果成功,用data返回具体的数据。为了满足这样的需求,我们必须在每个Controller都包装try catch,返回异常信息,同时所有的请求的返回对于都是该对象。有没有更好的办法解决上述问题。

 

2、Spring cloud 项目一般架构

    

         从图可以发现所有的外部请求都是通过gateway进行的,因此具体业务根本不需要进行任何修改,只需在gateway中进行修改返回值。

 

3、实现

     返回类:

     

/**
 * 响应对象
 *
 * @param <T>
 */
public class ResponseVo<T> {

    /**
     * 状态码.
     */
    private Integer code;

    /**
     * 提示信息.
     */
    private String msg;

    /**
     * 具体的数据.
     */
    private T data;

    public ResponseVo() {
    }


    public ResponseVo(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public ResponseVo(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }


    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResponseVo{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

 

   修复返回对象工具

   

public class BodyUtils {

    private static final Log log = LogFactory.getLog(BodyUtils.class);

    private final static int OK = 0;


    public final static String transforBody(String body) {
        ResponseVo responseVo = new ResponseVo();
        responseVo.setCode(OK);
        if (StringUtils.isEmpty(body)) {
            responseVo.setData(body);
            return JSON.toJSONString(responseVo);
        }
        if (!(body.startsWith("{") && body.endsWith("}")) && !(body.startsWith("[") && body.endsWith("]"))) {
            responseVo.setData(body);
            return JSON.toJSONString(responseVo);
        }
        Object jsonObject = JSON.parse(body);
        if (jsonObject instanceof JSONObject) {
            Object code = ((JSONObject) jsonObject).get("code");
            if (code != null) {
                if (((JSONObject) jsonObject).get("data") != null) {
                    if (((JSONObject) jsonObject).get("data") instanceof JSONObject) {
                        JSONObject data = (JSONObject) ((JSONObject) jsonObject).get("data");
                        Object total = data.get("total");
                        Object result = data.get("result");
                        if (total != null && result != null) {
                            Map response = new HashMap<>();
                            for (Map.Entry<String, Object> entry : data.entrySet()) {
                                if (entry.getKey().equals("countColumn")
                                        || entry.getKey().equals("startRow")
                                        || entry.getKey().equals("reasonable")
                                        || entry.getKey().equals("count")
                                        || entry.getKey().equals("endRow")
                                        || entry.getKey().equals("orderBy")
                                        || entry.getKey().equals("pageSize")
                                        || entry.getKey().equals("pageNum")
                                        || entry.getKey().equals("empty")
                                        || entry.getKey().equals("pages")
                                        || entry.getKey().equals("orderByOnly")
                                        || entry.getKey().equals("pageSizeZero")
                                ) {
                                    continue;
                                } else {
                                    response.put(entry.getKey(), entry.getValue());
                                }
                            }
                            responseVo.setData(response);
                            return JSON.toJSONString(responseVo);
                        } else {
                            return body;
                        }
                    } else {
                        return body;
                    }
                } else {
                    return body;
                }
            } else {
                responseVo.setData(jsonObject);
                return JSON.toJSONString(responseVo);
            }
        } else {
            responseVo.setData(jsonObject);
            return JSON.toJSONString(responseVo);
        }
    }

}

      修改gateway 中 ModifyResponseBodyGatewayFilterFactory 并覆盖原包中的类

      

public class ModifyResponseBodyGatewayFilterFactory
        extends AbstractGatewayFilterFactory<ModifyResponseBodyGatewayFilterFactory.Config> {

    private final ServerCodecConfigurer codecConfigurer;

    public ModifyResponseBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) {
        super(Config.class);
        this.codecConfigurer = codecConfigurer;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return new ModifyResponseGatewayFilter(config);
    }

    public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
        private final Config config;

        public ModifyResponseGatewayFilter(Config config) {
            this.config = config;
        }

        @Override
        @SuppressWarnings("unchecked")
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

            ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {

                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

                    Class inClass = config.getInClass();
                    Class outClass = config.getOutClass();

                    String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
                    HttpHeaders httpHeaders = new HttpHeaders();
                    //explicitly add it in this way instead of 'httpHeaders.setContentType(originalResponseContentType)'
                    //this will prevent exception in case of using non-standard media types like "Content-Type: image"
                    httpHeaders.add(HttpHeaders.CONTENT_TYPE, originalResponseContentType);
                    ResponseAdapter responseAdapter = new ResponseAdapter(body, httpHeaders);
                    DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults());

                    //TODO: flux or mono

                    Mono modifiedBody = clientResponse.bodyToMono(inClass)
                            .flatMap(originalBody -> config.rewriteFunction.apply(exchange, originalBody))
                            .switchIfEmpty(Mono.just(JSON.toJSONString(new ResponseVo(0, null))));

                    BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass);
                    CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders());
                    return bodyInserter.insert(outputMessage, new BodyInserterContext())
                            .then(Mono.defer(() -> {
                                Flux<DataBuffer> messageBody = outputMessage.getBody();
                                HttpHeaders headers = getDelegate().getHeaders();
                                if (!headers.containsKey(HttpHeaders.TRANSFER_ENCODING)) {
                                    messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount()));
                                }
                                //TODO: use isStreamingMediaType?
                                return getDelegate().writeWith(messageBody);
                            }));

                }

                @Override
                public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
                    return writeWith(Flux.from(body)
                            .flatMapSequential(p -> p));
                }
            };

            return chain.filter(exchange.mutate().response(responseDecorator).build());
        }

        @Override
        public int getOrder() {
            return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
        }

    }

    public class ResponseAdapter implements ClientHttpResponse {

        private final Flux<DataBuffer> flux;
        private final HttpHeaders headers;

        public ResponseAdapter(Publisher<? extends DataBuffer> body, HttpHeaders headers) {
            this.headers = headers;
            if (body instanceof Flux) {
                flux = (Flux) body;
            } else {
                flux = ((Mono) body).flux();
            }
        }

        @Override
        public Flux<DataBuffer> getBody() {
            return flux;
        }

        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }

        @Override
        public HttpStatus getStatusCode() {
            return null;
        }

        @Override
        public int getRawStatusCode() {
            return 0;
        }

        @Override
        public MultiValueMap<String, ResponseCookie> getCookies() {
            return null;
        }
    }

    public static class Config {
        private Class inClass = String.class;
        private Class outClass = String.class;
        private Map<String, Object> inHints;
        private Map<String, Object> outHints;
        private String newContentType;

        private RewriteFunction rewriteFunction = (exchange, body) -> {
            ServerHttpResponse response = ((ServerWebExchange) exchange).getResponse();
            if (response.getHeaders().get("Content-Type")!=null) {
                for (String s : response.getHeaders().get("Content-Type")) {
                    if(s.equals("application/vnd.ms-excel;charset=utf-8")){
                        return Mono.just(body);
                    }
                }
            }
            if (body instanceof String) {
                return Mono.just(BodyUtils.transforBody((String) body));
            } else {
                return Mono.just(body);
            }
        };

        public Class getInClass() {
            return inClass;
        }

        public Config setInClass(Class inClass) {
            this.inClass = inClass;
            return this;
        }

        public Class getOutClass() {
            return outClass;
        }

        public Config setOutClass(Class outClass) {
            this.outClass = outClass;
            return this;
        }

        public Map<String, Object> getInHints() {
            return inHints;
        }

        public Config setInHints(Map<String, Object> inHints) {
            this.inHints = inHints;
            return this;
        }

        public Map<String, Object> getOutHints() {
            return outHints;
        }

        public Config setOutHints(Map<String, Object> outHints) {
            this.outHints = outHints;
            return this;
        }

        public String getNewContentType() {
            return newContentType;
        }

        public Config setNewContentType(String newContentType) {
            this.newContentType = newContentType;
            return this;
        }

        public RewriteFunction getRewriteFunction() {
            return rewriteFunction;
        }

        public <T, R> Config setRewriteFunction(Class<T> inClass, Class<R> outClass,
                                                RewriteFunction<T, R> rewriteFunction) {
            setInClass(inClass);
            setOutClass(outClass);
            setRewriteFunction(rewriteFunction);
            return this;
        }

        public Config setRewriteFunction(RewriteFunction rewriteFunction) {
            this.rewriteFunction = rewriteFunction;
            return this;
        }
    }
}

          修改地方
         

  private RewriteFunction rewriteFunction = (exchange, body) -> {
            ServerHttpResponse response = ((ServerWebExchange) exchange).getResponse();
            if (response.getHeaders().get("Content-Type")!=null) {
                for (String s : response.getHeaders().get("Content-Type")) {
                    if(s.equals("application/vnd.ms-excel;charset=utf-8")){
                        return Mono.just(body);
                    }
                }
            }
            if (body instanceof String) {
                return Mono.just(BodyUtils.transforBody((String) body));
            } else {
                return Mono.just(body);
            }
        };

       

       为了满足返回对象是void 的也能返回ResponseVo 还得修改

        

          Mono modifiedBody = clientResponse.bodyToMono(inClass)
                            .flatMap(originalBody -> config.rewriteFunction.apply(exchange, originalBody))
                            .switchIfEmpty(Mono.just(JSON.toJSONString(new ResponseVo(0, null))));

       这地方需要加switchIfEmpty ,因为void没有返回值,所有必须加次判断。

 

        gateway 配置

        

spring:
  cloud:
    gateway:
      routes:
        - id: base
          uri: lb://base
          predicates:
            - Path=/basal/*
          filters:
            - StripPrefix=1

        - id: job
          uri: lb://job
          predicates:
            - Path=/job/**
          filters:
            - ModifyResponseBody
            - StripPrefix=1

   其中配置 - ModifyResponseBody的请求都会改写返回值。

  

 

标签:body,code,return,String,Spring,data,public,Cloud,统一
来源: https://www.cnblogs.com/smileIce/p/11157974.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有