ruoyi框架确实能解决大部分开发问题,他有独立的模块,gateway和auth等。但是有些场景需要使用gateway来优先鉴权在分发,所以就需要调用后台system的接口来校验,所以需要使用feign接口调用。引用社区作者的话,gateway就应该单纯的做分发,但是有时候确实需要调用接口,下面就来正面刚。我使用的版本是v3.6.2但是不影响,只要框架不变都通用。
一、添加配置信息处理
如果你把@EnableRyFeignClients引入Gateway则需要引用security包。
则会报错 ServletWebServerFactory bean defined in the context.
***************************
APPLICATION FAILED TO START
***************************
Description:
Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
Action:
Check your application's dependencies for a supported servlet web server.
Check the configured web application type.
主要报错原因是因为gateway的pom引用了如下包
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
而security模块引用了如下包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency>
原因是gateway是基于Reactor思想实现的,security依赖了spring-web然而两者是不可同时使用的所以会提示报错,如果要忽视当前报错启动可以在yml中添加main配置
main:
web-application-type: reactive
这样就可以启动成功并且调用了,但是我试过不同的type依旧报错,所以直接采用第二种办法,
需要注意的是直接引用security模块式无法使用@Autowired的需要使用以下方法直接获取并使用
try {
RemoteUserService remoteUserService = SpringUtils.getBean(RemoteUserService.class);
CompletableFuture<R<LoginUser>> f = CompletableFuture.supplyAsync(() -> {
return remoteUserService.getUserInfo("莫小邪", SecurityConstants.INNER);
});
R<LoginUser> loginUser = f.get();
//获取数据并添加相关逻辑
} catch (Exception e) {
throw new RuntimeException(e);
}
二、使用 @EnableFeignClients注解
如果无法引用ruoyi原来的feign直接则可以使用原生注解,毕竟他的也是重新改了一下,需要注意的是扫包需要自己配置
@EnableFeignClients(basePackages= {"com.ruoyi"})
然后可以直接引用system_api包
<!-- RuoYi Api System --> <dependency> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-api-system</artifactId> </dependency>
需要注意的是当前项目只要 @Autowired 注入 OpenFeignClient ,就启动不起来。启动会卡死不刷日志也注册不上去。是因为启动不允许同步需要添加异步注解并使用Future的方式。如何接口可以查看下面连接,但是他说的不完全还有部分需要补充
主要是以下几个错误
1、需要添加异步启动来解决
block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-7
可以不使用添加异步注解直接获取bean然后使用异步请求
try {
RemoteUserService remoteUserService = SpringUtils.getBean(RemoteUserService.class);
CompletableFuture<R<LoginUser>> f = CompletableFuture.supplyAsync(() -> {
return remoteUserService.getUserInfo("莫小邪", SecurityConstants.INNER);
});
R<LoginUser> loginUser = f.get();
//获取数据并添加相关逻辑
} catch (Exception e) {
throw new RuntimeException(e);
}
2、依赖注入问题无法获取bean
'org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}' and exception = 'No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}'
需要添加新的bean在@Configuration下面就行
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
3、如何是拦截其他模块的Filter还需要在ruoyi-gateway-dev.yml下面对应的微服务filters下面添加自定义的Filter,如果获取不到body的值和信息还需要添加CacheRequestFilter即可,但是这些都是获取post请求body下面的内容,如果是get的可以自己处理下获取。
以下是排查处理问题相关链接大家可以参考