Home > Java > javaTutorial > How to solve the pitfalls of integrating OpenFeign with SpringBoot

How to solve the pitfalls of integrating OpenFeign with SpringBoot

PHPz
Release: 2023-05-22 18:19:06
forward
957 people have browsed it

Project integration OpenFegin

Integration OpenFegin dependency

First of all, let me tell you about the configuration of the project. The SpringBoot version used by the overall project is 2.2.6. The native OpenFegin uses 11.0. We introduce OpenFegin in pom.xml as follows.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <skip_maven_deploy>false</skip_maven_deploy>
    <java.version>1.8</java.version>
    <openfegin.version>11.0</openfegin.version>
</properties>
<dependencies>
    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-core</artifactId>
        <version>${openfegin.version}</version>
    </dependency>

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-jackson</artifactId>
        <version>${openfegin.version}</version>
    </dependency>
</dependencies>
Copy after login

Here, I have omitted some other configuration items.

Next, I started using OpenFegin to call remote services in my project. Specific steps are as follows.

Realize remote calling

First, create the OpenFeignConfig class and configure the Contract used by OpenFegin by default.

@Configuration
public class OpenFeignConfig {
 @Bean
 public Contract useFeignAnnotations() {
  return new Contract.Default();
 }
}
Copy after login

Next, we write a general factory class for obtaining OpenFeign clients. This class is also relatively simple. It essentially uses a HashMap to cache all FeginClients. This FeginClient is essentially our custom one. Fegin interface, the Key in the cache is the base URL of the requested connection, and the cached Value is the FeginClient interface we defined.

public class FeginClientFactory {
 
 /**
  * 缓存所有的Fegin客户端
  */
 private volatile static Map<String, Object> feginClientCache = new HashMap<>();
 
 /**
  * 从Map中获取数据
  * @return 
  */
 @SuppressWarnings("unchecked")
 public static <T> T getFeginClient(Class<T> clazz, String baseUrl){
  if(!feginClientCache.containsKey(baseUrl)) {
   synchronized (FeginClientFactory.class) {
    if(!feginClientCache.containsKey(baseUrl)) {
     T feginClient = Feign.builder().decoder(new JacksonDecoder()).encoder(new JacksonEncoder()).target(clazz, baseUrl);
     feginClientCache.put(baseUrl, feginClient);
    }
   }
  }
  return (T)feginClientCache.get(baseUrl);
 }
}
Copy after login

Next, we define a FeginClient interface.

public interface FeginClientProxy {
 @Headers("Content-Type:application/json;charset=UTF-8")
 @RequestLine("POST /user/login")
 UserLoginVo login(UserLoginVo loginVo);
}
Copy after login

Next, we create the SpringBoot test class.

@RunWith(SpringRunner.class)
@SpringBootTest
public class IcpsWeightStarterTest {
 @Test
 public void testUserLogin() {
  ResponseMessage result = FeginClientFactory.getFeginClient(FeginClientProxy.class, "http://127.0.0.1").login(new UserLoginVo("zhangsan", "123456", 1));
  System.out.println(JsonUtils.bean2Json(result));
 }
}
Copy after login

Everything is ready, run the test. Damn it, something went wrong. The main problem is that an exception occurs when the LocalDateTime field returns the value through the OpenFeign request! ! !

Note: When an exception occurs at this time, the annotation we add to the LocalDateTime field is as follows.

import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;


@TableField(value = "CREATE_TIME", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime createTime;
Copy after login

Solution

Problem description

SpringBoot calls the HTTP interface through the native OpenFeign client. If the return value contains the LocalDateTime type (including other JSR -Time class of the java.time package in -310), a deserialization failure error may occur on the client. The error message is as follows:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ("2020-10-07T11:04:32")

Problem Analysis

From When the client calls fegin, it is equivalent to passing parameters in the URL, which is equivalent to a JSON conversion. The database takes out the '2020-10-07T11:04:32' data. This is the time type. After entering the JSON, it becomes the String type. T becomes a character and is no longer a special character, so the deserialization of the String string "2020-10-07T11:04:32" will fail.

Problem Solution

Add dependencies to the project.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.9</version>
</dependency>
Copy after login

Note: If you are using SpringBoot and the SpringBoot version is explicitly specified, you do not need to specify the version number when introducing jackson-datatype-jsr310.

Next, add the following annotation to the LocalDateTime type field of the POJO class.

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
Copy after login

The effect after adding is as follows.

import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;


@TableField(value = "CREATE_TIME", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
Copy after login

At this time, call the remote interface again and the problem is solved.

The above is the detailed content of How to solve the pitfalls of integrating OpenFeign with SpringBoot. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template