当前位置:网站首页>Utilisez l'annotation + réflexion pour éliminer le Code de duplication.

Utilisez l'annotation + réflexion pour éliminer le Code de duplication.

2021-11-25 17:37:23 Un peu de Tangcheng.

Auteur:Leilei Chen

1.1 Scénario de cas

Supposons que la banque offre API Interface,Un peu spécial pour la sérialisation des paramètres,Non utilisé JSON,Au lieu de cela, nous devons assembler les paramètres ensemble pour former une grande chaîne:

1)Selon la BanqueAPIOrdre des documents,Tous les paramètres forment des données de longueur fixe,Et les assembler comme une chaîne entière

2)Parce que chaque paramètre a une longueur fixe,La longueur non atteinte nécessite un traitement de remplissage

  • La partie du paramètre de type chaîne qui n'est pas pleine de longueur doit être remplie à droite du soulignement,C'est - à - dire que le contenu de la chaîne est à gauche
  • Le paramètre de type numérique n'est pas en longueur à0Remplissage à gauche,C'est - à - dire que les chiffres réels sont à droite
  • La représentation du type de monnaie exige que le montant soit arrondi vers le bas2BIT à minute,En fractions,Remplissez également à gauche comme type de nombre
  • ParamétrageMD5 Opération comme signature

1.2 Mise en oeuvre préliminaire du Code

       
public class BankService {

//Créer une méthode utilisateur
public static String createUser(String name, String identity, String mobile, int age) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
//Chaîne à gauche,Remplir l'excédent_
stringBuilder.append(String.format("%-10s", name).replace(' ', '_'));
//Chaîne à gauche,Remplir l'excédent_
stringBuilder.append(String.format("%-18s", identity).replace(' ', '_'));
//Les chiffres à droite,Pour l'espace supplémentaire0Remplissage
stringBuilder.append(String.format("%05d", age));
//Chaîne à gauche,Pour l'espace supplémentaire_Remplissage
stringBuilder.append(String.format("%-11s", mobile).replace(' ', '_'));
//Ajouter enfinMD5Comme signature
stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));
return Request.Post("http://localhost:45678/reflection/bank/createUser")
.bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON)
.execute().returnContent().asString();
}

//Mode de paiement
public static String pay(long userId, BigDecimal amount) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
//Les chiffres à droite,Pour l'espace supplémentaire0Remplissage
stringBuilder.append(String.format("%020d", userId));
//Montant arrondi à2BIT à minute,En fractions,À droite en chiffres,Pour l'espace supplémentaire0Remplissage
stringBuilder.append(String.format("%010d", amount.setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue()));
//Ajouter enfinMD5Comme signature
stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));
return Request.Post("http://localhost:45678/reflection/bank/pay")
.bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON)
.execute().returnContent().asString();
}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

Ce faisant, il peut essentiellement répondre aux besoins,Mais il y a des problèmes.:

  • Les logiques de traitement se répètent entre elles,Un peu de négligence peut apparaîtreBug
  • Assemblage de chaînes dans le processus de traitement、Logique d'apposition et d'envoi des demandes,Répétez toutes les méthodes
  • Type de paramètre et ordre des paramètres entrants de la méthode réelle,Pas nécessairement compatible avec les exigences d'interface,Sujet aux erreurs
  • Paramètre de niveau de code codé dur,Impossible de vérifier clairement

1.3 Code optimisé avec interface et réflexion

1.3.1 L'implémentation définit tous les paramètres de l'interfacePOJOCatégorie

       
@Data
public class CreateUserAPI {
private String name;
private String identity;
private String mobile;
private int age;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

1.3.2 Définir l'annotation elle - même

       
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
public @interface BankAPI {
String desc() default "";
String url() default "";
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface BankAPIField {
int order() default -1;
int length() default -1;
String type() default "";
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

1.3.3 L'assemblage dynamique des paramètres d'interface est réalisé par la réflexion et l'annotation

       
private static String remoteCall(AbstractAPI api) throws IOException {
//DeBankAPICommentaire obtenir l'adresse demandée
BankAPI bankAPI = api.getClass().getAnnotation(BankAPI.class);
bankAPI.url();
StringBuilder stringBuilder = new StringBuilder();
Arrays.stream(api.getClass().getDeclaredFields()) //Obtenir tous les champs
.filter(field -> field.isAnnotationPresent(BankAPIField.class)) //Rechercher les champs marqués d'une annotation
.sorted(Comparator.comparingInt(a -> a.getAnnotation(BankAPIField.class).order())) //Selon la noteorderTrier les champs
.peek(field -> field.setAccessible(true)) //Les paramètres permettent d'accéder aux champs privés
.forEach(field -> {
//Obtenir des commentaires
BankAPIField bankAPIField = field.getAnnotation(BankAPIField.class);
Object value = "";
try {
//Réflexion obtenir la valeur du champ
value = field.get(api);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//Formater la chaîne de manière correcte en fonction du type de champ
switch (bankAPIField.type()) {
case "S": {
stringBuilder.append(String.format("%-" + bankAPIField.length() + "s", value.toString()).replace(' ', '_'));
break;
}
case "N": {
stringBuilder.append(String.format("%" + bankAPIField.length() + "s", value.toString()).replace(' ', '0'));
break;
}
case "M": {
if (!(value instanceof BigDecimal))
throw new RuntimeException(String.format("{} De {} Ça doit l'être.BigDecimal", api, field));
stringBuilder.append(String.format("%0" + bankAPIField.length() + "d", ((BigDecimal) value).setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue()));
break;
}
default:
break;
}
});
//Logique de signature
stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));
String param = stringBuilder.toString();
long begin = System.currentTimeMillis();
//Envoyer une demande
String result = Request.Post("http://localhost:45678/reflection" + bankAPI.url())
.bodyString(param, ContentType.APPLICATION_JSON)
.execute().returnContent().asString();
log.info("Appelez la BanqueAPI {} url:{} Paramètres:{} Ça prend du temps:{}ms", bankAPI.desc(), bankAPI.url(), param, System.currentTimeMillis() - begin);
return result;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

Obtenu dynamiquement par réflexionclassInformations sur,Et dansruntimePour compléter le processus d'assemblage.

L'avantage est que le développement sera beaucoup plus facile et intuitif,Et ensuite cacher la logique et les détails,Et s'est concentré sur une méthode,Réduction de la duplication,Et pendant l'entretienbugL'apparition de.

1.3.4 Application au Code

       
@BankAPI(url = "/bank/createUser", desc = "Créer une interface utilisateur")
@Data
public class CreateUserAPI extends AbstractAPI {
@BankAPIField(order = 1, type = "S", length = 10)
private String name;
@BankAPIField(order = 2, type = "S", length = 18)
private String identity;
@BankAPIField(order = 4, type = "S", length = 11) //Attention iciorderDoit être conformeAPIOrdre dans le tableau
private String mobile;
@BankAPIField(order = 3, type = "N", length = 5)
private int age;
}



@BankAPI(url = "/bank/pay", desc = "Interface de paiement")
@Data
public class PayAPI extends AbstractAPI {
@BankAPIField(order = 1, type = "N", length = 20)
private long userId;
@BankAPIField(order = 2, type = "M", length = 10)
private BigDecimal amount;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

版权声明
本文为[Un peu de Tangcheng.]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/11/20211125173308759D.html

随机推荐