应用 SpringCloud 的 Feign 组件可能为服务间的调用节俭编码工夫并进步开发效率,当服务自身不简单时能够独自将该组件拿出应用。
引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
引入 SpringBoot 打包的 Feign 依赖,须要留神的是 Feign 的版本与 SpringBoot 版本的对应关系,老版本的 Feign 并不叫 openfeign。因为我是用的 SpringBoot 版本是 2.0x,所以 openfeign 应用了 2.0x 版本,若应用诸如 2.1x 或其余高版本的 openfeign,在我的项目启动时会报“形象办法谬误”这类的异样。
编写接口作为服务调用入口
import com.bhz.demo.client.domain.req.ProductReceiveReq;
import com.bhz.demo.client.domain.resp.MemberPointBaseResp;
import com.bhz.demo.client.domain.resp.UserPointResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @Author guomz
* @create 2021/3/15 14:50
*/
@FeignClient(url = "www.123.com", name = "demoClient")
public interface DemoClient {@RequestMapping(value = "/demo/user/{uuid}/{name}", method = RequestMethod.GET)
DemoBaseResp<DemoUserResp> getUser(@PathVariable("uuid") String uuid, @PathVariable("name") String name);
@RequestMapping(value = "/demo/buy", method = RequestMethod.POST)
DemoBaseResp buyProduct(DemoBuyReq req);
}
Feign 的服务调用编写相似 mybatis 的 dao 接口,接口上方须要标注 @FeignClient
注解,该注解有 url
、name
、value
三个重要参数。其中 name
与value
等效,必须填写一个。在微服务环境下 name
或value
填写用于被注册核心发现的服务名,例如调用的用户服务叫 userService 则此处填写 userService,此使 url
能够不填写,因为曾经指定了调用方。url
则是间接指定服务的全门路,若同时填写 url
与name
,则以 url
为准,name
便被当作以后客户端的名称。
下面的示例并不属于简单的微服务环境,所以采纳间接指定 url
来调用其余服务。
办法定义上与 controller 基本一致,须要留神 post 办法不能传递多个参数,须要用 map 或对象进行封装。
调用服务
@Service
@Slf4j
public class DemoService {
@Autowired
private DemoClient demoClient;
public void getUser(Long id){demoClient.getUser("123", "abc");
}
}
在须要调用其余服务的模块中引入之前定义的接口即可。
对于调用 https 接口
调用 https 接口时会进行证书校验,若没有证书则会抛出 No subject alternative names present
异样,能够应用以下代码来绕过证书校验:
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
首先须要引入 Ribbon 依赖,在绕过证书的代码中存在一些须要被注入的类属于 Ribbon。Ribbon 的引入同样须要留神版本问题。
import feign.Client;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
/**feign client 配置
* @Author guomz
* @create 2021/3/16 9:52
*/
@Configuration
public class FeignConfiguration {
/**
* 调用 https 接口时绕过 ssl 证书验证
* @param cachingFactory
* @param clientFactory
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
@Bean
@ConditionalOnMissingBean public Client feignClient(@Qualifier("cachingLBClientFactory") CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException {SSLContext ctx = SSLContext.getInstance("TLSv1.2");
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) { }
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) { }
@Override
public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];
}
};
ctx.init(null, new TrustManager[]{tm}, null);
return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(), new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession sslSession) {return true;}
}),
cachingFactory, clientFactory);
}
}
之后是 Feign 的配置类,用来绕过 https 证书校验。