使用Feign调用RestFul接口
Feign使编写Java HTTP客户端更加容易
Feign是受Retrofit,JAXRS-2.0和WebSocket启发的Java到HTTP客户端绑定程序。Feign的第一个目标是减少与ReSTfulness无关的将Denominator统一绑定到HTTP API 的复杂性。
为什么Feign而不是X?
Feign使用Jersey和CXF等工具为ReST或SOAP服务编写Java客户端。此外,Feign允许您在诸如Apache HC之类的http库之上编写自己的代码。Feign通过可自定义的解码器和错误处理功能,以最小的开销和代码将代码连接到http API,可以将其写入任何基于文本的http API。
Feign如何工作?
Feign通过将注释处理为模板化请求来工作。在输出之前,参数以简单的方式应用于这些模板。尽管Feign仅限于支持基于文本的API,但它极大地简化了系统方面,例如重播请求。此外,Feign知道这一点,就可以轻松对转换进行单元测试。
Java版本相容性
Feign 10.x及更高版本建立在Java 8上,并且可以在Java 9、10和11上运行。对于那些需要JDK 6兼容性的应用程序,请使用Feign9.x。
基本
使用通常看起来像这样,是对典型Retrofit示例的改编。
interface GitHub { @RequestLine("GET /repos/{owner}/{repo}/contributors") List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo); @RequestLine("POST /repos/{owner}/{repo}/issues") void createIssue(Issue issue, @Param("owner") String owner, @Param("repo") String repo); } public static class Contributor { String login; int contributions; } public static class Issue { String title; String body; List<String> assignees; int milestone; List<String> labels; } public class MyApp { public static void main(String... args) { GitHub github = Feign.builder() .decoder(new GsonDecoder()) .target(GitHub.class, "https://api.github.com"); // Fetch and print a list of the contributors to this library. List<Contributor> contributors = github.contributors("OpenFeign", "feign"); for (Contributor contributor : contributors) { System.out.println(contributor.login + " (" + contributor.contributions + ")"); } } }
改造Json请求的接口案例:
依赖pom.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2012-2019 The Feign Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <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"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>io.github.openfeign</groupId> <artifactId>parent</artifactId> <version>10.7.1-SNAPSHOT</version> </parent> <artifactId>feign-jackson</artifactId> <name>Feign Jackson</name> <description>Feign Jackson</description> <properties> <main.basedir>${project.basedir}/..</main.basedir> </properties> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>feign-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.databind.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>feign-core</artifactId> <type>test-jar</type> <scope>test</scope> </dependency> </dependencies> </project>
Jackson编码器
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import java.lang.reflect.Type; import java.util.Collections; import feign.RequestTemplate; import feign.codec.EncodeException; import feign.codec.Encoder; import feign.Util; public class JacksonEncoder implements Encoder { private final ObjectMapper mapper; public JacksonEncoder() { this(Collections.<Module>emptyList()); } public JacksonEncoder(Iterable<Module> modules) { this(new ObjectMapper() .setSerializationInclusion(JsonInclude.Include.NON_NULL) .configure(SerializationFeature.INDENT_OUTPUT, true) .registerModules(modules)); } public JacksonEncoder(ObjectMapper mapper) { this.mapper = mapper; } @Override public void encode(Object object, Type bodyType, RequestTemplate template) { try { JavaType javaType = mapper.getTypeFactory().constructType(bodyType); template.body(mapper.writerFor(javaType).writeValueAsBytes(object), Util.UTF_8); } catch (JsonProcessingException e) { throw new EncodeException(e.getMessage(), e); } } }
Jackson解码器
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.RuntimeJsonMappingException; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Type; import java.util.Collections; import feign.Response; import feign.Util; import feign.codec.Decoder; public class JacksonDecoder implements Decoder { private final ObjectMapper mapper; public JacksonDecoder() { this(Collections.<Module>emptyList()); } public JacksonDecoder(Iterable<Module> modules) { this(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .registerModules(modules)); } public JacksonDecoder(ObjectMapper mapper) { this.mapper = mapper; } @Override public Object decode(Response response, Type type) throws IOException { if (response.body() == null) return null; Reader reader = response.body().asReader(); if (!reader.markSupported()) { reader = new BufferedReader(reader, 1); } try { // Read the first byte to see if we have any data reader.mark(1); if (reader.read() == -1) { return null; // Eagerly returning null avoids "No content to map due to end-of-input" } reader.reset(); return mapper.readValue(reader, mapper.constructType(type)); } catch (RuntimeJsonMappingException e) { if (e.getCause() != null && e.getCause() instanceof IOException) { throw IOException.class.cast(e.getCause()); } throw e; } } }
实体类 QueryGroupNeedListReq
@Data public class QueryGroupNeedListReq { private String arrivearea; private String tripdepAirPort; private String triparrAirPort; private String status; private String startDate; private String endDate; private List<String> settlementNoList; private EcsOperator ecsOperator; private PageParam page = new PageParam(); }
GroupNeedClient.java
public interface GroupNeedClient { @Headers("Content-Type: application/json") @RequestLine("POST /groupNeed/queryGroupNeedList") public ResponseData<QueryGroupNeedListDTORes> queryGroupNeedList(@RequestBody QueryGroupNeedListReq queryGroupNeedListReq); }
调用接口
String userBase = "http://10.79.3.114:8908"; GroupNeedClient groupNeedClient = Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()) .target(GroupNeedClient.class,userBase); ResponseData<QueryGroupNeedListDTORes> queryGroupNeedListDTOResResponseData = groupNeedClient.queryGroupNeedList(queryGroupNeedListRe);

浙公网安备 33010602011771号