当前位置: 首页 > article >正文

ruoyi源码解析学习 - 微服务版 - ruoyi-gateway

com.ruoyi.gateway

今天简单看看若依的gateway的配置模块干了啥

最近面试很多外包公司,都对低代码平台有点要求,这些代码虽说用起来不费劲,但是其中还是有很多细节能让我学习学习的。(微服务版,上次搞jeecgboot的笔试题差点把我人带走了)

在这里插入图片描述

简单的看一眼,总共分为4个文件夹和1个启动类。

0. pom文件

<parent>
   <groupId>com.ruoyi</groupId>
   <artifactId>ruoyi</artifactId>
   <version>3.6.4</version>
</parent>

dependencies
spring-cloud-starter-gateway
spring-cloud-starter-alibaba-nacos-discovery
spring-cloud-starter-alibaba-nacos-config
spring-cloud-starter-alibaba-sentinel
spring-cloud-alibaba-sentinel-gateway
sentinel-datasource-nacos
spring-boot-starter-actuator
spring-cloud-loadbalancer
kaptcha
ruoyi-common-redis
springdoc-openapi-webflux-ui

1. 先看一眼启动类

emm,没什么特别就加了一个注解,用来剔除数据库的自动配置的。

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })

2. 从头开始看,第一个是config

  • config
    • properties(首先也是一个目录,里面写了一些属性)
    • CaptchaConfig:验证码的配置
    • GatewayConfig:网关限流配置
    • KaptchaTextCreator:验证码文本生成器(这里是no usages的)
    • RouterFunctionConfiguration:路由配置
    • SpringDocConfig:文档的配置类

CaptchaConfig

这里用的是google的kaptcha的包,里面注册了两个bean,一个是default的验证码bean,一个是数字的bean。

GatewayConfig:这里主要是注册了一个自定义的限流处理

@Configuration
public class GatewayConfig{
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    // 这里的SentinelFallbackHandler自定义的限流处理,跳转过去看看
    public SentinelFallbackHandler sentinelGatewayExceptionHandler(){
        return new SentinelFallbackHandler();
    }
}

// 自定义限流异常处理
public class SentinelFallbackHandler implements WebExceptionHandler{
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange){
        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试");
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex){
        if (exchange.getResponse().isCommitted()){
            return Mono.error(ex);
        }
        if (!BlockException.isBlockException(ex)){
            return Mono.error(ex);
        }
        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
    }

    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable){
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }
}

好像没啥特别,就是封装了一些自定义的返回,ServletUtils.webFluxResponseWriter这里也是一个返回的封装。

@Order(Ordered.HIGHEST_PRECEDENCE)

@Order用于指定Bean的加载顺序,注解的参数越小优先级越高,越会被优先加载。

public interface Ordered {
    int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; 
    int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

    int getOrder();
}

KaptchaTextCreator 这个就不展开研究了,给我的话可能梭哈cv一下就完事了。

RouterFunctionConfiguration

这个配置类里面注入了handler的ValidateCodeService,这个类主要是用于获取验证码的
@Autowired
private ValidateCodeHandler validateCodeHandler;

	@Bean
    public RouterFunction routerFunction() {
    	// 当接收到 /get的请求以及 ediaType.TEXT_PLAIN的时候就跑到handler里面去,也就是注入的获取验证码的handler
        return RouterFunctions.route(
                RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                validateCodeHandler);
    }

	// handler里面调用创建验证码的方法
	@Component
	public class ValidateCodeHandler implements HandlerFunction<ServerResponse> {
	    @Autowired
	    private ValidateCodeService validateCodeService;
	
	    @Override
	    public Mono<ServerResponse> handle(ServerRequest serverRequest) {
	        AjaxResult ajax;
	        try {
	            ajax = validateCodeService.createCaptcha();
	        } catch (CaptchaException | IOException e) {
	            return Mono.error(e);
	        }
	        return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax));
	    }
	}

也是注册了一个bean,返回了.route这个方法,也跳转进去看看干嘛的。

/**
	 * Route to the given handler function if the given request predicate applies.
	 * <p>For instance, the following example routes GET requests for "/user" to the
	 * {@code listUsers} method in {@code userController}:
	 * <pre class="code">
	 * RouterFunction&lt;ServerResponse&gt; route =
	 *     RouterFunctions.route(RequestPredicates.GET("/user"), userController::listUsers);
	 * </pre>
	 * @param predicate the predicate to test
	 * @param handlerFunction the handler function to route to if the predicate applies
	 * @param <T> the type of response returned by the handler function
	 * @return a router function that routes to {@code handlerFunction} if
	 * {@code predicate} evaluates to {@code true}
	 * @see RequestPredicates
	 */
	public static <T extends ServerResponse> RouterFunction<T> route(
			RequestPredicate predicate, HandlerFunction<T> handlerFunction) {
		// 这里就类似对断言进行了配置
		return new DefaultRouterFunction<>(predicate, handlerFunction);
	}

SpringDocConfig

这里做的是swagger的配置,多看了一眼这个订阅类型方法,好像是返回一些nacos的东西的,具体还得研究一下。

	@Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }

3. filter

AuthFilter:网关鉴权

	// 实现两个类
	public class AuthFilter implements GlobalFilter, Ordered

嗯?这个实现Ordered的类居然还能这样用,属实是我太菜了,这样就又能自己定义优先级了
@Override
public int getOrder() {
return -200;
}

其余的就是一些基本的鉴权验证了,判断令牌的状态等等等等

BlackListUrlFilter:黑名单过滤器

extends AbstractGatewayFilterFactory<>,网关的filter factory。

重写了GatewayFilterFactory里面的apply,然后判断是否为黑名单然后返回一个封装好的数据。(一个类套一个好家伙,倒也不复杂,果然写得好看的代码就是绕)

CacheRequestFilter:获取body的请求数据

这个又是个什么玩意?解决流不能重复读取的问题?也跟黑名单过滤器一样继承了相同的一个东西,然后在泛型里自己定义一个内部类来搞。

ValidateCodeFilter:验证码过滤器

跟上面也是同样的,what?AbstractGatewayFilterFactory这个东西有点牛的。

XssFilter:跨站脚本过滤器

implements GlobalFilter, Ordered

同样是实现了ordered,并且这次也实现了GlobalFilter这个东西,重写filter方法,主要是用来过滤请求的。这些类可以拿过来就用了。

4. handler

这里面的类都会在上面的类中被调用而抽出来放的。

  • 网关统一处理的异常
  • 自定义限流异常处理
  • 验证码的获取(这个在service中也抽出来了)

差不多就这样,得看看这个AbstractGatewayFilterFactory<>是个什么来头

在这里插入图片描述

看这个类的写法,跟若以这里抽出来的写的确实是类似的,但是apply方法不是放在这里的,还在上一级的GatewayFilterFactory中,确实里面都会搭配上一个内部类来使用。

在这里插入图片描述

这里就是上一级的GatewayFilterFactory

在这里插入图片描述

原来每一次都需要定义一个内部类是因为这里是一个class,所以为了方便直接就丢里面。

#学习完毕,done


http://www.kler.cn/a/321995.html

相关文章:

  • 【人工智能】多模态AI:如何通过融合文本、图像与音频重塑智能系统未来
  • Qt系统相关——QFile和QFileInfo
  • 笔记整理—内核!启动!—linux应用编程、网络编程部分(5)系统时间与信息
  • Django 依赖库管理
  • 【计网】从零开始掌握序列化 --- 基础知识储备与程序重构
  • Ubuntu24.04下安装Budgie桌面的注意事项
  • 【C++掌中宝】深入理解函数重载:概念、规则与应用
  • Map和Set,TreeMap和TreeSet,HashMap和HashSet
  • Docker安装和配置MySQL 5.7的完整指南
  • 【Unity与数据库01】开发者如何选择数据库
  • 深度学习:(五)初识神经网络
  • Unity2022.3.x各个版本bug集合及推荐稳定版本
  • 使用jQuery处理Ajax
  • kotlin——设计模式之责任链模式
  • 数据结构之二叉树(1)
  • 本地生活服务项目揭秘!谁搭建的本地生活服务商作业系统收益效果好?
  • 使用ELK Stack进行日志管理和分析:从入门到精通
  • JDK7和JDK8中的HashMap有什么区别?
  • 初学51单片机之I2C总线与E2PROM
  • Java 使用 Graham 扫描的凸包(Convex Hull using Graham Scan)