1. Background
Because of the business relationship, we have to dock with many different third-party companies. These service providers all provide API based on HTTP. But the details of the API vary greatly from company to company. Some are based onRESTFUL
Some of them are based on the traditional HTTP specification; others need to be in theheader
Some of them need to be signedSSL
Two way authentication, some only needSSL
One way authentication of; some withJSON
Some of them are serialized byXML
Method. There are so many differences in details like this.
It’s normal that different companies have different API specifications. But for me, if I want the code to be elegant. I have to solve a pain point:
There are so many differences in API of different service providers, how to maintain a set of public HTTP calling suite that does not involve business. It’s best to distinguish them by configuration or simple parameters. Make convenient calls?
Of course, I know that there are many excellent and famous HTTP open source frameworks that can implement any form of HTTP call. I have used them in many years of development experience. such asapache
OfhttpClient
Bag, excellentOkhttp
,jersey client
。
these ones herehttp
The interface usage of open source framework is relatively different. Whichever you choose, in my scenario, I don’t want to write a lot of HTTP calling code when calling every third-party HTTP API.
So, in this scenario, I have to encapsulate each different HTTP API. Only in this way can the code be more elegant and the coupling degree between business code and HTTP call logic be lower.
Unfortunately, I’m lazy. On the one hand, it takes a lot of time to encapsulate. On the other hand, there should be a better choice for encapsulating the underlying HTTP call. I don’t want to build my own wheels.
So, I found an excellent open source HTTP framework, which can shield all the differences brought by different details of HTTP API. Through simple configuration, it can complete extremely complex HTTP calls just like calling RPC framework.
Forest
https://gitee.com/dt_flys/forest
2. Get started
Forest
YesSpringboot
So you just need to introduce a dependency
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>spring-boot-starter-forest</artifactId>
<version>1.3.0</version>
</dependency>
Define your own interface class
public interface MyClient {
@Request(url = "http://baidu.com")
String simpleRequest();
@Request(
url = "http://ditu.amap.com/service/regeo",
dataType = "json"
)
Map getLocation(@DataParam("longitude") String longitude, @DataParam("latitude") String latitude);
}
Configure the scan package of the proxy interface class in the boot class
@SpringBootApplication
@ForestScan(basePackages = "com.example.demo.forest")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
At this time, you can inject your proxy interface from the spring container and call the HTTP API just like calling local methods
@Autowired
private MyClient myClient;
@Override
public void yourMethod throws Exception {
Map result = myClient.getLocation("124.730329","31.463683");
System.out.println(JSON.toJSONString(result,true));
}
Log printing,Forest
Printed the internal HTTP framework, and the actual request URL and return. Of course, the log can be configured to control the switch.
3. Features
I think this open source framework can help you improve a lot of efficiency, especially for those who are engaged in the development of third-party API.
Forest
The bottom layer encapsulates two different HTTP frameworksApache httpClient
andOKhttp
. Therefore, this open source framework does not duplicate the underlying implementation, but focuses on ease of use.
I use itForest
Finally, I completed the project of docking with multiple service providers’ APIs. It took me only one hour to transform these different styles of APIs into local methods. Then the project went online smoothly.
Forest
As a higher-level HTTP framework, you don’t need to write a lot of code. Most of the time, you can complete the localized call of HTTP only through some configuration. However, this framework can cover a wide range of areas, meeting most of your HTTP calls.
Forest
It has the following characteristics:
- with
Httpclient
andOkHttp
Back end framework - By calling local methods to send HTTP requests, the decoupling between business logic and HTTP protocol is realized
- Lighter than feign, independent
Spring Cloud
And any registry - Support all request methods:
GET
,HEAD
,OPTIONS
,TRACE
,POST
,DELETE
,PUT
,PATCH
- Support flexible template expression
- Supports filters to filter incoming data
- Method definition based on annotation and configuration
Http
request - support
Spring
andSpringboot
integrate - realization
JSON
andXML
Serialization and deserialization of - Support JSON transformation framework:
Fastjson
,Jackson
,Gson
- support
JAXB
FormalXML
transformation - support
SSL
One way and two way encryption of - Support the setting of HTTP connection pool
- Can pass
OnSuccess
andOnError
Interface parameters realize callback of request results - The configuration is simple. Generally, only
@Request
One annotation can complete the definition of most requests - Support asynchronous request call
4. Two great functions
The usage and configuration methods are not described one by one here. You can read the detailed documents if you are interested
https://dt_flys.gitee.io/forest
Here, I just want to analyze two good functions of this framework
4.1 Mapping and binding function of template expression and parameter
Template expressions are very convenient to use, for example, chestnuts
@Request(
url = "@Request(
url = "${0}/send?un=${1}&pw=${2}&ph=${3}&ct=${4}",
type = "get",
dataType = "json"
)
public Map send(
String base,
String userName,
String password,
String phone,
String content
);
/send?un=&pw=&ph=&ct=",
type = "get",
dataType = "json"
)
public Map send(
String base,
String userName,
String password,
String phone,
String content
);
The above values can be obtained by subscript of serial number or by name
@Request(
url = "${base}/send?un=${un}&pw=${pw}&ph=&ct=${ct}",
type = "get",
dataType = "json"
)
public Map send(
@DataVariable("base") String base,
@DataVariable("un") String userName,
@DataVariable("pw") String password,
@DataVariable("ph") String phone,
@DataVariable("ct") String content
);
You can even simplify writing like this:
@Request(
url = "${base}/send",
type = "get",
dataType = "json"
)
public Map send(
@DataVariable("base") String base,
@DataParam("un") String userName,
@DataParam("pw") String password,
@DataParam("ph") String phone,
@DataParam("ct") String content
);
The above three writing methods are equivalent
Of course, you can also bind parameters to header and body. You can even use some expressions to simply sequence objects into JSON or XML
@Request(
url = "${base}/pay",
contentType = "application/json",
type = "post",
dataType = "json",
headers = {"Authorization: "},
data = "${json($0)}"
)
public PayResponse pay(PayRequest request, String auth);
Of course, please refer to the document for details of data binding
4.2 yesHTTPS
Our support
In the past, when using other HTTP frameworks to process HTTPS, I always found it very troublesome, especially the two-way certificate. Every time I encounter problems, I can only go to Baidu. Then according to the experience of others to modify their own code.
Forest
We are very considerate in this aspect. The bottom layer perfectly encapsulates the support for single and two-way certificates of HTTPS. It can be quickly completed by simple configuration. For example, two way certificate Chestnut:
@Request(
url = "${base}/pay",
contentType = "application/json",
type = "post",
dataType = "json",
keyStore = "pay-keystore",
data = "${json($0)}"
)
public PayResponse pay(PayRequest request);
amongpay-keystore
Corresponding toapplication.yml
Insidessl-key-stores
forest:
...
ssl-key-stores:
- id: pay-keystore
file: test.keystore
keystore-pass: 123456
cert-pass: 123456
protocols: SSLv3
This setting is OK, and the rest is the call in the form of local code.
5. Finally
Forest
There are many other function settings. If you are interested, please read the documents and examples carefully.
But what I want to say is that I believe that many people will say that this is not trueFeign
Is that right?
I’m developingSpring Cloud
It was also used for a period of time in the projectFeign
, personal feelingForest
It’s really different in configuration and usageFeign
It’s a similar design, butFeign
My role is more asSpring Cloud
A member of the ecology. As the role of RPC communication, it undertakes not only HTTP communication, but also load balancing of the call address issued by the registry.
andForest
This open source project is positioned as a high-level HTTP tool, focusing on friendliness and ease of use. From the perspective of use, personal feelingForest
Configuration is more simple and direct. Many functions can also solve the pain points of many people.
The spirit of open source is commendable, good open source needs everyone’s contribution and support. I hope this article can bring you a new choice when choosing the HTTP client frameworkForest
6. Contact the author
Wechat focuses on getting more technical dry goods