Feign是一个声明式的Web服务客户端,使得编写Web服务客户端变得非常容易,
只需要创建一个接口,然后在上面添加注解即可。

Feign是spring cloud中服务消费端的调用框架,通常与ribbon,hystrix等组合使用。

但是在某些项目中,由于遗留原因,整个系统并不是spring cloud项目,甚至不是spring项目,而使用者关注的重点仅仅是简化http调用代码的编写。

如果采用httpclient或者okhttp这样相对较重的框架,对初学者来说编码量与学习曲线都会是一个挑战,而使用spring中RestTemplate,又没有配置化的解决方案,由此想到是否可以脱离spring cloud,独立使用Feign。

http://47.101.47.253:8082/reed/  中提供如下两个接口。

@RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String say(){
        return "reed";
    }

    @RequestMapping(value = "/hello1/{price}",method = RequestMethod.GET)
    public Integer price(@PathVariable("price") Integer price){
        return price;
    }

在demo工程中新建如下两个接口,

import feign.Param;
import feign.RequestLine;
public interface RemoteService {
    @RequestLine("GET /reed/hello")
    String getUserName();
    @RequestLine("GET /reed/hello1/{price}")
    String getPrice(@Param(value = "price") Integer price);
}

在main方法中可进行接口调用

public static void main(String[] args) {

        RemoteService service = Feign.builder()
                .options(new Request.Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3))
                .target(RemoteService.class, "http://47.101.47.253:8082");

        String result = service.getUserName();
        System.out.println(result);
        String price = service.getPrice(100);
        System.out.println(price);
    }

运行结果如下

如果需要调用的是Https的地址,在访问前需要加上如下操作,跳过ssl安全验证

// 跳过SSL验证 ,在获取connection之前调用这个方法 trustAllHttpsCertificates
    private static void trustAllHttpsCertificates() throws Exception {
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        javax.net.ssl.TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
                .getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
                .getSocketFactory());
    }
    static class miTM implements javax.net.ssl.TrustManager,
            javax.net.ssl.X509TrustManager {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }

feign调用非resful形式api

http://47.101.47.253:8080/find_music_entry_by_keywords?keyWords=qinghuaci

要想调用上面的接口

可以用如下形式

import com.cisco.reed.httpClient.MusicEntryVo;
import feign.Param;
import feign.RequestLine;

import java.net.URI;

public interface MusicFeignTest {

    @RequestLine("GET /find_music_entry_by_keywords?keyWords={keyWords}")
    MusicEntryVo findMusicEntry(
            URI uri,
            @Param(value = "keyWords") String keyWords);
}

Client代码如下

public static void main(String[] args) {
        String urlString = "http://47.101.47.253:8080";
        URI uri = URI.create(urlString);
        MusicFeignTest musicFeignTest = Feign.builder().options(new Request.Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3))
                .decoder(new JacksonDecoder()).encoder(new JacksonEncoder()).target(Target.EmptyTarget.create(MusicFeignTest.class));
        MusicEntryVo musicEntryVo = musicFeignTest.findMusicEntry(uri,"qinghuaci");
        System.out.println(musicEntryVo.toString());
    }

运行结果如下

MusicEntryVo(viewCounts=1, id=1, entryKeywords=qinghuaci, officialExplain=officialExplain, oralExplain=oralExplain, createUser=苏日乐格, createTime=Sat Aug 09 11:20:46 CST 2008, updateTime=Sat Aug 09 11:20:46 CST 2008)

或者采用如下的形式:

@RequestLine("GET /find_music_entry_by_keywords?keyWords={keyWords}")
MusicEntryVo findMusicEntry(@Param(value = "keyWords") String keyWords);

客户端代码

FeignTest feignTest = Feign.builder()
                .options(new Request.Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3))
                .decoder(new JacksonDecoder())
                .encoder(new JacksonEncoder())
                .target(FeignTest.class, "http://47.101.47.253:8080");
        MusicEntryVo musicEntryVo = feignTest.findMusicEntry("qinghuaci");

Post发送form表单形式的数据

 @RequestLine("POST /token")
    @Headers({"Content-Type: application/x-www-form-urlencoded","Accept: application/json"})
    AuthPojo getAuth(
            URI uri,
            String str
    );

调用 ,注意encoder的格式,然后将body以key value的形式拼接出来

public static void main(String[] args) throws Exception{
        String uriString = "https://login.microsoftonline.com";
          trustAllHttpsCertificates();
        URI uri = URI.create(uriString);
        AuthService authorizationService = Feign.builder().
                options(new Request.Options(1000, 3500))

                .retryer(new Retryer.Default(5000, 5000, 3))
                .decoder(new JacksonDecoder())
                //特别要注意,此处的encoder格式
                .encoder(new SpringFormEncoder()).target(Target.EmptyTarget.create(AuthService.class));
        String str = "grant_type=client_credentials&client_id=f6b81139-923f-41a7-816f-ddd02a199ed6&scope=https://graph.microsoft.com/.default";
        AuthPojo authPojo  = authorizationService.getAuth(uri,str );
        System.out.println(authPojo.toString());
        
    }