毕业论文写作

毕业设计需求

计算机毕业设计中Spring Cloud Gateway过滤器精确控制异常返回(实战,完全定制返回body)

 标题:计算机毕业设计中Spring Cloud Gateway过滤器精确控制异常返回(实战,完全定制返回body)

价格:0元
类型:毕业设计程序教程
 
 
 
 
 
点击上方“蓝字”,关注我们.

 

 

本篇概览

Spring Cloud Gateway应用中,处理请求时若发生异常未被捕获,请求方收到的响应是系统默认的内容,无法满足实际业务需求

因此,从前一篇文章《Spring Cloud Gateway过滤器精确控制异常返回(分析篇)》开始,咱们深入分析了Spring Cloud Gateway的相关源码,了解到全局异常的处理细节,然后,通过前文《Spring Cloud Gateway过滤器精确控制异常返回(实战,控制http返回码和message字段)》的实战,咱们已经能随意设置http返回码,以及body中的message字段,也就是控制下图两个红框中的内容:

  • 正如上图所示,异常发生时系统固定返回8个字段,这就有些不够灵活了,在一些对格式和内容有严格要求的场景下,咱们需要能够完全控制返回码和返回body的内容,如下所示,只返回三个字段,每个字段都是完全为业务服务的:

  • {    # 这是有具体业务含义的返回码    "code": "010020003",    # 这是能精确描述错误原因的文本信息    "message": "请确保请求参数中的user-id字段是有效的",        # 这是常规的业务数据,发生异常时该字段为空    "data": null}

今天咱们的目标就是通过编码定制异常发生时的返回信息,具体内容就是上述JSON数据:只有code、message、data三个字段

源码下载

本篇实战中的完整源码可在GitHub下载到,地址和链接信息如下表所示

 

这个git项目中有多个文件夹,本篇的源码在spring-cloud-tutorials文件夹下,如下图红框所示:

spring-cloud-tutorials文件夹下有多个子工程,本篇的代码是gateway-change-body,如下图红框所示:

为何不用常规手段

提到全局异常处理,经验丰富的您应该想到了常用的ControllerAdvice和ExceptionHandler注解修饰的全局异常处理类,但是Spring Cloud Gateway是基于WebFlux的,咱们之前处理异常时用到的HttpServletRequest在Spring Cloud Gateway中并不适用,因此,不能用ControllerAdvice和ExceptionHandler的手段来处理全局异常

基本思路

在动手前做好充足的理论分析,写出的代码才能正常工作

打开DefaultErrorWebExceptionHandler.java,找到renderErrorResponse方法,来看看Spring Cloud Gateway原本是如何构造异常返回内容的:

 

此刻聪明的您应该想到怎么做了:做个新的类继承DefaultErrorWebExceptionHandler,覆盖其renderErrorResponse方法,新的renderErrorResponse方法中,按照实际业务需要来设置返回内容,没错,这就是咱们的思路,不过还要细化一下,最终具体的步骤如下:

1、新增一个异常类CustomizeInfoException.java,该类有三个字段:http返回码、业务返回码、业务描述信息。

2、在返回异常的代码位置,使用CustomizeInfoException类来抛出异常,按照实际业务场景设置CustomizeInfoException实例的各个字段

3、新增MyErrorWebExceptionHandler.java,继承自DefaultErrorWebExceptionHandler,重写了renderErrorResponse方法,这里面检查异常实例是否是CustomizeInfoException类型,如果是,就从其中取出http返回码、业务返回码、业务描述信息等字段,构造返回body的内容,异常实例若不是CustomizeInfoException类型,就保持之前的处理逻辑不变;

4、新增configuration类,用于将MyErrorWebExceptionHandler实例注册到spring环境

分析完毕,开始编码吧,为了简单起见,本篇不再新增maven子工程,而是基于前文创建的子工程gateway-change-body,在这里面继续写代码;

 

 

编码

新增异常类CustomizeInfoException.java:

 

 

package com.bolingcavalry.changebody.exception;import lombok.Data;import org.springframework.http.HttpStatus;@Datapublic class CustomizeInfoException extends Exception {    /**     * http返回码     */    private HttpStatus httpStatus;    /**     * body中的code字段(业务返回码)     */    private String code;    /**     * body中的message字段(业务返回信息)     */    private String message;}

 

修改RequestBodyRewrite.java的apply方法,这里面是在处理请求body,如果检查到没有user-id字段,就不将请求转发到服务提供方provider-hello,而是返回错误,这里的错误就用CustomizeInfoException类来处理:

@Override    public Publisher<String> apply(ServerWebExchange exchange, String body) {        try {            Map<String, Object> map = objectMapper.readValue(body, Map.class);            // 如果请求参数中不含user-id,就返回异常            if (!map.containsKey("user-id")) {                CustomizeInfoException customizeInfoException = new CustomizeInfoException();                // 这里返回406,您可以按照业务需要自行调整                customizeInfoException.setHttpStatus(HttpStatus.NOT_ACCEPTABLE);                // 这里按照业务需要自行设置code                customizeInfoException.setCode("010020003");                // 这里按照业务需要自行设置返回的message                customizeInfoException.setMessage("请确保请求参数中的user-id字段是有效的");                return Mono.error(customizeInfoException);            }            // 取得id            int userId = (Integer)map.get("user-id");            // 得到nanme后写入map            map.put("user-name", mockUserName(userId));            return Mono.just(objectMapper.writeValueAsString(map));        } catch (Exception ex) {            log.error("1. json process fail", ex);            return Mono.error(new Exception("1. json process fail", ex));        }    }

异常处理类MyErrorWebExceptionHandler.java,这里有一处需要重点关注的是:下面的代码仅是参考而已,您无需拘泥于CustomizeInfoException有关的逻辑,完全能按照业务需求自由设置返回的状态码和body:

package com.bolingcavalry.changebody.handler;import com.bolingcavalry.changebody.exception.CustomizeInfoException;import org.springframework.boot.autoconfigure.web.ErrorProperties;import org.springframework.boot.autoconfigure.web.WebProperties;import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;import org.springframework.boot.web.reactive.error.ErrorAttributes;import org.springframework.context.ApplicationContext;import org.springframework.http.MediaType;import org.springframework.web.reactive.function.BodyInserters;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Mono;import java.util.HashMap;import java.util.Map;public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {    public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties.Resources resources, ErrorProperties errorProperties, ApplicationContext applicationContext) {        super(errorAttributes, resources, errorProperties, applicationContext);    }    @Override    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {        // 返回码        int status;        // 最终是用responseBodyMap来生成响应body的        Map<String, Object> responseBodyMap = new HashMap<>();        // 这里和父类的做法一样,取得DefaultErrorAttributes整理出来的所有异常信息        Map<String, Object> error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));        // 原始的异常信息可以用getError方法取得        Throwable throwable = getError(request);        // 如果异常类是咱们定制的,就定制        if (throwable instanceof CustomizeInfoException) {            CustomizeInfoException myGatewayException = (CustomizeInfoException) throwable;            // http返回码、body的code字段、body的message字段,这三个信息都从CustomizeInfoException实例中获取            status = myGatewayException.getHttpStatus().value();            responseBodyMap.put("code", myGatewayException.getCode());            responseBodyMap.put("message", myGatewayException.getMessage());            responseBodyMap.put("data", null);        } else {            // 如果不是咱们定制的异常,就维持和父类一样的逻辑            // 返回码            status = getHttpStatus(error);            // body内容            responseBodyMap.putAll(error);        }        return ServerResponse                // http返回码                .status(status)                // 类型和以前一样                .contentType(MediaType.APPLICATION_JSON)                // 响应body的内容                .body(BodyInserters.fromValue(responseBodyMap));    }}

最后是配置类MyErrorWebFluxAutoConfiguration.java:

package com.bolingcavalry.changebody.config;import com.bolingcavalry.changebody.handler.MyErrorWebExceptionHandler;import org.springframework.beans.factory.ObjectProvider;import org.springframework.boot.autoconfigure.AutoConfigureBefore;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;import org.springframework.boot.autoconfigure.web.ServerProperties;import org.springframework.boot.autoconfigure.web.WebProperties;import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.boot.web.reactive.error.ErrorAttributes;import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.Order;import org.springframework.http.codec.ServerCodecConfigurer;import org.springframework.web.reactive.config.WebFluxConfigurer;import org.springframework.web.reactive.result.view.ViewResolver;import java.util.stream.Collectors;@Configuration(proxyBeanMethods = false)@AutoConfigureBefore(WebFluxAutoConfiguration.class)public class MyErrorWebFluxAutoConfiguration {    private final ServerProperties serverProperties;    public MyErrorWebFluxAutoConfiguration(ServerProperties serverProperties) {        this.serverProperties = serverProperties;    }    @Bean    @Order(-1)    public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,                                                             org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties,                                                             WebProperties webProperties, ObjectProvider<ViewResolver> viewResolvers,                                                             ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {        MyErrorWebExceptionHandler exceptionHandler = new MyErrorWebExceptionHandler(errorAttributes,                resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources(),                this.serverProperties.getError(), applicationContext);        exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));        exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());        exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());        return exceptionHandler;    }}

编码完成,该把程序运行起来验证效果了;

 

验证

启动应用gateway-change-body

用postman发起POST请求,地址是http://localhost:8081/hello/change,如下图,红框2中的http返回码是咱们代码里设置的,红框3显示返回的内容就是咱们定制的那三个字段:

至此,控制Spring Cloud Gateway应用异常返回的实战已经全部完成,从源码分析结合实战演练,希望欣宸的文章能陪伴您深入了解Spring Cloud Gateway,打造出更加强大的网关应用;

 

 

 

————————————————

版权声明:本文为CSDN博主「程序员欣宸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/boling_cavalry/article/details/120239199

更多请关注小编继续了解,免费赠送网页设计作业源代码哦!

 

如需要精品网页设计作业和毕业设计作品

最新毕业设计成品

版权所有© 帮我毕业网 并保留所有权利

QQ 1370405256 微信 biyebang

QQ:629001810微信:biyebang

收缩