Maison  >  Article  >  Java  >  Comment résoudre les pièges de l'intégration d'OpenFeign avec SpringBoot

Comment résoudre les pièges de l'intégration d'OpenFeign avec SpringBoot

PHPz
PHPzavant
2023-05-22 18:19:06867parcourir

Le projet intègre OpenFegin

Intégrer les dépendances OpenFegin

Tout d'abord, permettez-moi de vous parler de la configuration du projet. La version SpringBoot utilisée par l'ensemble du projet est la 2.2.6, et la version native d'OpenFegin utilise la 11.0. La méthode suivante dans le pom OpenFegin est introduite dans .xml.

<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>

Ici, j'ai omis quelques autres éléments de configuration.

Ensuite, j'ai commencé à utiliser OpenFegin pour appeler des services distants dans mon projet. Les étapes spécifiques sont les suivantes.

Implémentez les appels à distance

Tout d'abord, créez la classe OpenFeignConfig et configurez le contrat utilisé par OpenFegin par défaut.

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

Ensuite, nous écrivons une classe d'usine générale pour obtenir des clients OpenFeign. Cette classe est également relativement simple. Elle utilise essentiellement un HashMap pour mettre en cache tous les FeginClients. Ce FeginClient est essentiellement notre interface Fegin personnalisée, la clé est l'URL de base. de la connexion demandée, et la valeur mise en cache est l'interface FeginClient que nous avons définie.

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);
 }
}

Ensuite, nous définissons une interface FeginClient.

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

Ensuite, nous créons la classe de test SpringBoot.

@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));
 }
}

Tout est prêt, lancez le test. Bon sang, quelque chose s'est mal passé. Le principal problème est qu'une exception se produira lorsque le champ LocalDateTime renvoie la valeur via la requête OpenFeign ! ! !

Remarque : Lorsqu'une exception se produit à ce moment-là, l'annotation que nous ajoutons au champ LocalDateTime est la suivante.

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;

Résoudre le problème

Description du problème

SpringBoot appelle l'interface HTTP via le client natif OpenFeign Si la valeur de retour contient le type LocalDateTime (y compris d'autres classes d'heure du package java.time dans JSR-310), cela peut être possible sur le client. Une erreur d'échec de désérialisation se produira. Le message d'erreur est le suivant :

Causé par : com.fasterxml.jackson.databind.exc.InvalidDefinitionException : Impossible de construire une instance de `java.time.LocalDateTime` (aucun créateur, comme la construction par défaut, n'existe) : aucune chaîne- constructeur d'arguments/méthode d'usine pour désérialiser à partir de la valeur de chaîne ("2020-10-07T11:04:32")

Analyse du problème

Appeler fegin depuis le client équivaut également à transmettre des paramètres d'URL, ce qui équivaut à un Conversion JSON, base de données Supprimez les données '2020-10-07T11:04:32". C'est un type d'heure à ce moment. Après avoir entré JSON, il devient un type String. T devient un caractère et n'est plus un caractère spécial . Par conséquent, la désérialisation de la chaîne "2020 -10-07T11:04:32" échouera

Problème résolu

Ajoutez des dépendances dans le projet.

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

Remarque : si vous utilisez SpringBoot et que la version SpringBoot est clairement. spécifié, introduisez jackson -datatype-jsr310, vous n'avez pas besoin de spécifier le numéro de version

Ensuite, ajoutez l'annotation suivante au champ de type LocalDateTime de la classe POJO

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

L'effet après l'ajout est le suivant

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;
.

À ce moment, appelez à nouveau l'interface distante. Problème résolu

.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer