maven项目下feign公共模块
- 导包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sc-login</artifactId>
<groupId>org.login</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.login</groupId>
<artifactId>login-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>none</mainClass> <!-- 取消查找本项目下的Main方法:为了解决Unable to find main class的问题 -->
<classifier>execute</classifier> <!-- 为了解决依赖模块找不到此模块中的类或属性 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 目录
api目录
login-common 主要存放 feign 接口,提给给其他微服务调用
login-server 主要是存放业务代码
- 实现
feign 接口
package com.zl.common.api;
import com.zl.common.api.fallback.RoleClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.zl.server.domain.user.model.entity.User;
/**
* @author z
*/
@Primary
@FeignClient(name = "login", primary = false, qualifier = "loginClient", fallback = LoginClientFallback.class)
public interface LoginClient {
/**
* 获取用户信息
*
* @param userId 用户id
* @return 用户信息
*/
@GetMapping("/user/getUserInfo")
User getUserInfo(@RequestParam String userId);
}
@FeignClient 中的 name,value 属性值为application.properties的 spring.application.name=login 的值
@GetMapping("/user/getUserInfo") 属性值为controller路径加上接口路径
feign接口熔断
package com.zl.common.api.fallback;
import com.zl.common.api.LoginClient;
import org.springframework.stereotype.Component;
import com.zl.server.domain.user.model.entity.User;
/**
* LoginClient fallback
*
* @author z
* @date 2022-04-02 11:30
*/
@Component
public class LoginClientFallback implements LoginClient {
@Override
public User getUserInfo(String userId) {
return null;
}
}
在熔断上面加 @Component 注解,才能使 LoginClientFallback 生效
feign接口实现
package com.zl.server.domain.user.web.api;
import com.zl.common.api.LoginClient;
import com.zl.server.domain.user.service.ISysUserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import com.zl.server.domain.user.model.entity.User;
import javax.annotation.Resource;
/**
* 用户 api 实现feign接口,并调用返回结果
*
* @author z
* @date 2022-04-02 11:37
*/
@RestController
@ApiIgnore
public class LoginClientController implements LoginClient {
/**
* 用户 service
*/
@Resource
private ISysUserService iSysUserService;
/**
* 获取用户信息
*
* @param userId 用户id
* @return 用户信息
*/
@GetMapping("/user/getUserInfo")
@Override
public User getUserInfo(@RequestParam String userId) {
User list = iSysUserService.getUserInfo(userId);
return User;
}
}
需要
controller实现feign接口
,与前端交互的controller分开便于管理
在启动类LoginApplication中加入@EnableFeignClients(basePackages = {"com.zl.**.api"})
注解使feign接口生效
最后,将这个公共的feign模块包引入到其他的模块中就可以调用了
问题:
- application.properties 配置了 server.servlet.context-path为/user,导致feign接口调用失败
解决:
在 @FeignClient 注解里使用 path 属性指定请求前缀,@FeignClient(name = "login", path="user")
- 出现:NoUniqueBeanDefinitionException: No qualifying bean of type 'com.zl.api.xxxClient' available
解决:
@Resource(name = "loginClient")
private LoginClient loginClient;
@Qualifier
注解,使用场景跟上面的primary关系很淡,一般场景直接@Autowired直接注入就可以了。
如果我们的Feign Client有fallback实现,默认@FeignClient注解的primary=true, 意味着我们使用@Autowired注入是没有问题的,会优先注入你的FeignClient。
如果你把primary设置成false了,直接用@Autowired注入的地方就会报错,不知道要注入哪个对象。
解决方案很明显,你可以将primary设置成true即可,如果由于某些特殊原因,你必须得去掉primary=true的设置,这种情况下我们怎么进行注入,我们可以配置一个qualifier,然后使用@Qualifier注解进行注入