在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:OpenFeign/feign开源软件地址:https://github.com/OpenFeign/feign开源编程语言:Java 99.7%开源软件介绍:Feign makes writing java http clients easierFeign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness. Why Feign and not X?Feign uses tools like Jersey and CXF to write java clients for ReST or SOAP services. Furthermore, Feign allows you to write your own code on top of http libraries such as Apache HC. Feign connects your code to http APIs with minimal overhead and code via customizable decoders and error handling, which can be written to any text-based http API. How does Feign work?Feign works by processing annotations into a templatized request. Arguments are applied to these templates in a straightforward fashion before output. Although Feign is limited to supporting text-based APIs, it dramatically simplifies system aspects such as replaying requests. Furthermore, Feign makes it easy to unit test your conversions knowing this. Java Version CompatibilityFeign 10.x and above are built on Java 8 and should work on Java 9, 10, and 11. For those that need JDK 6 compatibility, please use Feign 9.x Feature overviewThis is a map with current key features provided by feign: RoadmapFeign 11 and beyondMaking API clients easier
Short Term - What we're working on now. |
Annotation | Interface Target | Usage |
---|---|---|
@RequestLine |
Method | Defines the HttpMethod and UriTemplate for request. Expressions , values wrapped in curly-braces {expression} are resolved using their corresponding @Param annotated parameters. |
@Param |
Parameter | Defines a template variable, whose value will be used to resolve the corresponding template Expression , by name provided as annotation value. If value is missing it will try to get the name from bytecode method parameter name (if the code was compiled with -parameters flag). |
@Headers |
Method, Type | Defines a HeaderTemplate ; a variation on a UriTemplate . that uses @Param annotated values to resolve the corresponding Expressions . When used on a Type , the template will be applied to every request. When used on a Method , the template will apply only to the annotated method. |
@QueryMap |
Parameter | Defines a Map of name-value pairs, or POJO, to expand into a query string. |
@HeaderMap |
Parameter | Defines a Map of name-value pairs, to expand into Http Headers |
@Body |
Method | Defines a Template , similar to a UriTemplate and HeaderTemplate , that uses @Param annotated values to resolve the corresponding Expressions . |
Overriding the Request Line
If there is a need to target a request to a different host then the one supplied when the Feign client was created, or you want to supply a target host for each request, include a
java.net.URI
parameter and Feign will use that value as the request target.@RequestLine("POST /repos/{owner}/{repo}/issues") void createIssue(URI host, Issue issue, @Param("owner") String owner, @Param("repo") String repo);
Feign Expressions
represent Simple String Expressions (Level 1) as defined by URI Template - RFC 6570. Expressions
are expanded using
their corresponding Param
annotated method parameters.
Example
public interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repository);
class Contributor {
String login;
int contributions;
}
}
public class MyApp {
public static void main(String[] args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
/* The owner and repository parameters will be used to expand the owner and repo expressions
* defined in the RequestLine.
*
* the resulting uri will be https://api.github.com/repos/OpenFeign/feign/contributors
*/
github.contributors("OpenFeign", "feign");
}
}
Expressions must be enclosed in curly braces {}
and may contain regular expression patterns, separated by a colon :
to restrict
resolved values. Example owner
must be alphabetic. {owner:[a-zA-Z]*}
RequestLine
and QueryMap
templates follow the URI Template - RFC 6570 specification for Level 1 templates, which specifies the following:
encoded
via a @Param
annotation.We also have limited support for Level 3, Path Style Expressions, with the following restrictions:
Examples:
{;who} ;who=fred
{;half} ;half=50%25
{;empty} ;empty
{;list} ;list=red;list=green;list=blue
{;map} ;semi=%3B;dot=.;comma=%2C
public interface MatrixService {
@RequestLine("GET /repos{;owners}")
List<Contributor> contributors(@Param("owners") List<String> owners);
class Contributor {
String login;
int contributions;
}
}
If owners
in the above example is defined as Matt, Jeff, Susan
, the uri will expand to /repos;owners=Matt;owners=Jeff;owners=Susan
For more information see RFC 6570, Section 3.2.7
Undefined expressions are expressions where the value for the expression is an explicit null
or no value is provided.
Per URI Template - RFC 6570, it is possible to provide an empty value
for an expression. When Feign resolves an expression, it first determines if the value is defined, if it is then
the query parameter will remain. If the expression is undefined, the query parameter is removed. See below
for a complete breakdown.
Empty String
public void test() {
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("param", "");
this.demoClient.test(parameters);
}
Result
http://localhost:8080/test?param=
Missing
public void test() {
Map<String, Object> parameters = new LinkedHashMap<>();
this.demoClient.test(parameters);
}
Result
http://localhost:8080/test
Undefined
public void test() {
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("param", null);
this.demoClient.test(parameters);
}
Result
http://localhost:8080/test
See Advanced Usage for more examples.
What about slashes?
/
@RequestLine templates do not encode slash
/
characters by default. To change this behavior, set thedecodeSlash
property on the@RequestLine
tofalse
.
What about plus?
+
Per the URI specification, a
+
sign is allowed in both the path and query segments of a URI, however, handling of the symbol on the query can be inconsistent. In some legacy systems, the+
is equivalent to the a space. Feign takes the approach of modern systems, where a+
symbol should not represent a space and is explicitly encoded as%2B
when found on a query string.If you wish to use
+
as a space, then use the literalcharacter or encode the value directly as
%20
The @Param
annotation has an optional property expander
allowing for complete control over the individual parameter's expansion.
The expander
property must reference a class that implements the Expander
interface:
public interface Expander {
String expand(Object value);
}
The result of this method adheres to the same rules stated above. If the result is null
or an empty string,
the value is omitted. If the value is not pct-encoded, it will be. See Custom @Param Expansion for more examples.
Headers
and HeaderMap
templates follow the same rules as Request Parameter Expansion
with the following alterations:
See Headers for examples.
A Note on
@Param
parameters and their names:All expressions with the same name, regardless of their position on the
@RequestLine
,@QueryMap
,@BodyTemplate
, or@Headers
will resolve to the same value. In the following example, the value ofcontentType
, will be used to resolve both the header and path expression:public interface ContentService { @RequestLine("GET /api/documents/{contentType}") @Headers("Accept: {contentType}") String getDocumentByType(@Param("contentType") String type); }Keep this in mind when designing your interfaces.
Body
templates follow the same rules as Request Parameter Expansion
with the following alterations:
Encoder
before being placed on the request body.Content-Type
header must be specified. See Body Templates for examples.Feign has several aspects that can be customized.
For simple cases, you can use Feign.builder()
to construct an API interface with your custom components.
For request setting, you can use options(Request.Options options)
on target()
to set connectTimeout, connectTimeoutUnit, readTimeout, readTimeoutUnit, followRedirects.
For example:
interface Bank {
@RequestLine("POST /account/{id}")
Account getAccountInfo(@Param("id") String id);
}
public class BankService {
public static void main(String[] args) {
Bank bank = Feign.builder()
.decoder(new AccountDecoder())
.options(new Request.Options(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true))
.target(Bank.class, "https://api.examplebank.com");
}
}
Feign can produce multiple api interfaces. These are defined as Target<T>
(default HardCodedTarget<T>
), which allow for dynamic discovery and decoration of requests prior to execution.
For example, the following pattern might decorate each request with the current url and auth token from the identity service.
public class CloudService {
public static void main(String[] args) {
CloudDNS cloudDNS = Feign.builder()
.target(new CloudIdentityTarget<CloudDNS>(user, apiKey));
}
class CloudIdentityTarget extends Target<CloudDNS> {
/* implementation of a Target */
}
}
Feign includes example GitHub and Wikipedia clients. The denominator project can also be scraped for Feign in practice. Particularly, look at its example daemon.
Feign intends to work well with other Open Source tools. Modules are welcome to integrate with your favorite projects!
Gson includes an encoder and decoder you can use with a JSON API.
Add GsonEncoder
and/or GsonDecoder
to your Feign.Builder
like so:
public class Example {
public static void main(String[] args) {
GsonCodec codec = new GsonCodec();
GitHub github = Feign.builder()
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
}
}
Jackson includes an encoder and decoder you can use with a JSON API.
Add JacksonEncoder
and/or JacksonDecoder
to your Feign.Builder
like so:
public class Example {
public static void main(String[] args) {
GitHub github = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.target(GitHub.class, "https://api.github.com");
}
}
For the lighter weight Jackson Jr, use JacksonJrEncoder
and JacksonJrDecoder
from
the Jackson Jr Module.
SaxDecoder allows you to decode XML in a way that is compatible with normal JVM and also Android environments.
Here's an example of how to configure Sax response parsing:
public class Example {
public static void main(String[] args) {
Api api = Feign.builder()
.decoder(SAXDecoder.builder()
.registerContentHandler(UserIdHandler.class)
.build())
.target(Api.class, "https://apihost");
}
}
JAXB includes an encoder and decoder you can use with an XML API.
Add JAXBEncoder
and/or JAXBDecoder
to your Feign.Builder
like so:
public class Example {
public static void main(String[] args) {
Api api = Feign.builder()
.encoder(new JAXBEncoder())
.decoder(new JAXBDecoder())
.target(Api.class, "https://apihost");
}
}
JAXRSContract overrides annotation processing to instead use standard ones supplied by the JAX-RS specification. This is currently targeted at the 1.1 spec.
Here's the example above re-written to use JAX-RS:
interface GitHub {
@GET @Path("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@PathParam("owner") String owner, @PathParam("repo") String repo);
}
public class Example {
public static void main(String[] args) {
GitHub github = Feign.builder()
.contract(new JAXRSContract())
.target(GitHub.class, "https://api.github.com");
}
}
OkHttpClient directs Feign's http requests to OkHttp, which enables SPDY and better network control.
To use OkHttp with Feign, add the OkHttp module to your classpath. Then, configure Feign to use the OkHttpClient:
public class Example {
public static void main(String[] args) {
GitHub github = Feign.builder()
.client(new OkHttpClient())
.target(GitHub.class, "https://api.github.com");
}
}
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论