[JAVA] Mémorandum d'étude sur l'intégration de Spring ~ Comprendre l'exemple d'intégration de Spring 3. Enricher ~

Objectif

Afin d'apprendre Spring Integration, j'ai compris l'exemple fourni par Spring Project et je l'ai réimplémenté + arrangé. Cet article est un mémorandum. Je pense donc qu'il y a plusieurs erreurs, mais je vous serais reconnaissant de bien vouloir souligner ce point. L'exemple est enregistré dans le Git suivant. spring-integration-sample

Cette fois à propos de _ ** Enricher ** _ basique En continuant de JMS Gateway, j'ai pensé que je pouvais le faire avec aggregator de JMS, mais avant de faire le système d'adaptateur tel que JMS Quand j'ai pensé à faire un composant typique, cet exemple de programme n'était pas seulement un enrichisseur, mais il semblait être basique avec une balise gateway '' normale, j'ai donc décidé de le faire en premier. À propos, la version de Spring Integration est 4.3.10.RELEASE ''.

Aperçu

Le concept d'enricher est simple: ajoutez des informations à l'en-tête du message ou à la charge utile en cours de route. Étant donné que l'exemple d'application n'ajoute que des informations à la charge utile, j'ai essayé de mettre en œuvre quelque chose qui ajoute des informations à l'en-tête.

Le déroulement de l'application est le suivant. AP start-> Entrez l'un de 1 à 3 sur la console et appuyez sur Enter (AP stop dans le cas de `` `q```) -> 1 à 4 donnera des informations différentes. Sortez le résultat donné sur la console. 1 à 4 sont les suivants.

  1. Mettez une valeur dans l'objet Utilisateur qui est Payload et affichez-la. 2.1 Payload est maintenant User.username
  2. Ajoutez des éléments à la carte de charge utile et affichez-les.
  3. Ajoutez des attributs à Haeder et affichez-les.

la mise en oeuvre

Vue d'ensemble

Le flux global ressemble à ce qui suit.

requestchannel(gateway) -> finduserenricherchannel -> serviceactivator -> finduserservicechannel -> replychannel(gateway) ->Sortie standard(Valeur de sortie dans la classe principale)

Tout d'abord, getBean l'interface de service définie par la balise `` `` gateway ''` dans la classe Main. Ensuite, la méthode à appeler est modifiée en fonction de la valeur d'entrée de la console. La liaison à la méthode appelée se fait avec la balise `` `` gateway, et `<int: selon le nom du canal spécifié par la valeur de la balise <int: method> . C'est un flux de délégation de traitement à la balise enricher> <int: service-activator> .

messagechannel -> headerenricher -> pollablechannel ->Sortie standard(Valeur de sortie dans la classe principale)

HeaderEnricher ne savait pas comment l'implémenter avec la balise gateway '', donc dans la classe Main, getBean``` respectivement le canal d'envoi et le canal de réception, et envoyer et recevoir. C'est l'implémentation la plus basique pour récupérer la valeur.

fichier de définition de bean

La structure de l'exemple de programme est composée de trois parties (gateway, enricher, service-activator), mais comme il est difficile sur Qiita si la définition du bean est longue, service-activator a été implémenté avec des annotations cette fois. 1 est une analyse des composants pour cet service-activator. 2 est la définition du bean du canal à envoyer à chaque enricher lors du routage du processus avec gateway. 3 est le paramètre de gateway, interface est défini par `` service-interface '', et l'élément enfant définit que le canal à envoyer est changé pour chaque méthode.

    <!-- 1 -->
    <context:component-scan base-package="org.ek.sample"/>
    
    <!-- 2 -->
    <int:channel id="findUserEnricherChannel"/>
    <int:channel id="findUserByUsernameEnricherChannel"/>
    <int:channel id="findUserWithMapEnricherChannel"/>
    <int:channel id="tryHeaderEnricherChannel"/>
    <int:channel id="requestChannel"/>
    <int:channel id="replyChannel"/>
         
	<!-- 3 -->
	<int:gateway id="gateway"
		default-request-timeout="5000"
		default-reply-timeout="5000"
		default-request-channel="requestChannel"
		default-reply-channel="replyChannel"
		service-interface="org.ek.sample.service.UserService">
		<int:method name="findUser"                  request-channel="findUserEnricherChannel"/>
        <int:method name="findUserByUsername"        request-channel="findUserByUsernameEnricherChannel"/>
        <int:method name="findUserWithUsernameInMap" request-channel="findUserWithMapEnricherChannel"/>
    </int:gateway>

En 4, cela signifie que le traitement est confié à la méthode (service-activator '') qui saisit le canal de l'attribut request-channel ''. De plus, parmi les méthodes spécifiées dans l'attribut service-interface de la balise `` gateway, la méthode à déléguer à partir d'ici a un argument de org.ek.sample.domain.User`. Puisqu'il s'agit d'un fichier bean appelé `` et qu'il n'y a pas d'autres paramètres d'attribut, _serviceActivator_ doit définir la méthode en conséquence. Ensuite, l'élément enfant `` `<int: property>` `` représente le type à renvoyer est org.ek.sample.domain.User```, dont l'email et le mot de passe Cela signifie que seul l'attribut adopte le contenu de enricher. En d'autres termes, dans ce paramètre, quel que soit le nombre d'autres éléments manipulés avec enricher, il ne sera pas reflété dans la valeur à répondre.

    <int:channel id="findUserServiceChannel"/>
    <int:channel id="findUserByUsernameServiceChannel"/>

    <!-- 4 -->
    <int:enricher id="findUserEnricher"
                  input-channel="findUserEnricherChannel"
                  request-channel="findUserServiceChannel">
        <int:property name="email" expression="payload.email"/>
        <int:property name="password" expression="payload.password"/>
    </int:enricher>

    <!-- 5 -->
    <int:enricher id="findUserByUsernameEnricher"
                  input-channel="findUserByUsernameEnricherChannel"
                  request-channel="findUserByUsernameServiceChannel"
                  request-payload-expression="payload.username">
        <int:property name="email" expression="payload.email"/>
        <int:property name="password" expression="payload.password"/>
    </int:enricher>

    <!-- 6 -->
    <int:enricher id="findUserWithMapEnricher"
                  input-channel="findUserWithMapEnricherChannel"
                  request-channel="findUserByUsernameServiceChannel"
                  request-payload-expression="payload.username">
        <int:property name="user" expression="payload"/>
    </int:enricher>
    
    <int:channel id="tryHeaderEnricherPollarChannel" >
    	<int:queue capacity="10"/>
    </int:channel>
    
    <!-- 7 -->
    <int:header-enricher id="tryHeaderEnricher" 
    					input-channel="tryHeaderEnricherChannel" 
    					output-channel="tryHeaderEnricherPollarChannel">    			
    					<int:header name="headerTest" value="test" />		
    					<int:header name="addedHeader" ref="stringConv" method="upperCase" />
    </int:header-enricher>
    <bean id="stringConv" class="org.ek.sample.domain.StringConverter"/>

5 est presque identique à 4, mais la seule différence est que `` '' est défini. La méthode de serviceActivator spécifiée par cet enricher a un argument de String, donc ici cela signifie que l'élément nommé username de payload est lié à serviceActivator en tant qu'argument.

Aussi, 6 semble être le même que 5 à première vue, mais en 6 c'est la route lors de l'appel de la méthode avec l'argument Map dans service-interface```, et ici contrairement à 5, Map S'il y a un élément appelé username dans key, cela signifie qu'il est lié à l'argument method (identique à 5) de serviceActivator.

7 est headerEnricher, qui donne deux attributs à MessageHeaders passés du simple `ʻinput_channel```, le second utilise la référence de fichier bean (ref). Exprimé. J'ai créé une classe simple qui renvoie simplement la classe référencée avec l'argument en majuscule.

service-interface Il s'agit de l'interface définie par la balise `` passerelle ''.

public interface UserService {
	
	User findUser(User user);
	
	User findUserByUsername(User user);
	
	Map<String, Object> findUserWithUsernameInMap(Map<String, Object> userdata);

}

serviceActivator En fait, la classe de rôle Enricher est définie comme serviceActivator. Comme mentionné dans xml, la première méthode a un type d'argument de org.ek.sample.domain.User, et la deuxième méthode a un type d'argument de String. ..

@MessageEndpoint
@EnableIntegration
public class UserServiceEnricher {
	
	private static final Logger LOGGER = Logger.getLogger(UserServiceEnricher.class);
	
	@ServiceActivator(inputChannel="findUserServiceChannel")
	public User findUser(User user) {

		LOGGER.info(String.format("Calling method 'findUser' with parameter %s", user));
		return new User(user.getUsername() + "-test",//La chaîne de caractères ajoutée par le nom d'utilisateur n'est pas reflétée
				   "secret",
				   user.getUsername() + "@springintegration.org");
	}



	@ServiceActivator(inputChannel="findUserByUsernameServiceChannel")
	public User findUserByUsername(String username) {

		LOGGER.info(String.format("Calling method 'findUserByUsername' with parameter: %s", username));

		return new User(username, "secret", username + "@springintegration.org");

	}

Classe principale

Je vais omettre les parties autres que les plus importantes, mais elles sont les suivantes.

	User user = new User();

			if ("1".equals(input)) {

				final User fullUser = service.findUser(user);
				printUserInformation(fullUser);

			} else if ("2".equals(input)) {

				final User fullUser = service.findUserByUsername(user);
				printUserInformation(fullUser);

			} else if ("3".equals(input)) {

                // 3
				final Map<String, Object> userData = new HashMap<String, Object>();
				userData.put("username", "foo_map");
				userData.put("username2", "bar_map");
				final Map<String, Object> enrichedUserData = service.findUserWithUsernameInMap(userData);
				printUserFullInformation(enrichedUserData);

			} else if("4".equals(input)){
              // 4
				MessageChannel mc = context.getBean("tryHeaderEnricherChannel", MessageChannel.class);
				PollableChannel pc = context.getBean("tryHeaderEnricherPollarChannel", PollableChannel.class);
				mc.send(new GenericMessage<String>("foo.bar"));
				printHeaderInfo(pc.receive().getHeaders());				
				
			} else{			
				LOGGER.info("\n\n    Please enter '1', '2', or '3' <enter>:\n\n");
			}	
            
            
            
            // omitted
            
            
                // 5
            	private static void printUserFullInformation(Map<String, Object> userdataMap) {
		for(Map.Entry<String, Object> entry : userdataMap.entrySet()) {
			Object val = entry.getValue();
			if(val instanceof User) {
				User user = (User) entry.getValue();
				LOGGER.info(String.format("\n\n    User found - Key of Map: '%s',  Username: '%s',  Email: '%s', Password: '%s'.\n\n",
						entry.getKey(), user.getUsername(), user.getEmail(), user.getPassword()));
			}else {
				LOGGER.info(String.format("\n\n    User found - Key of Map: '%s',  Username: '%s',  Email: '%s', Password: '%s'.\n\n",
						entry.getKey(), val, null, null));
			}
		}
	}
    
    // 6
    private static void printHeaderInfo(MessageHeaders mh) {
		LOGGER.info("\n\n    " + "headerTest :" + mh.get("headerTest") + ", addedHeader :" + mh.get("addedHeader"));
	}

La partie 3 est légèrement modifiée et les valeurs-clés username et username2 sont placées dans l'argument Map pour en faire un argument. De plus, toutes les valeurs de retour sont affichées avec _map.entrySet () _ (5), mais comme le montre le résultat ci-dessous, il semble qu'il s'agisse d'un élément créé avec l'élément de carte spécifié dans l'argument + enricher. y a-t-il. Le nom de la clé est défini par l'utilisateur par <int: property> '' en xml, et comme la charge utile a été spécifiée dans l'attribut value en xml, l'objet User devient la valeur de Map telle quelle.

0:10:42.631 INFO  [main][org.ek.sample.Main] 

    User found - Key of Map: 'username2',  Username: 'bar_map',  Email: 'null', Password: 'null'.


00:10:42.632 INFO  [main][org.ek.sample.Main] 

    User found - Key of Map: 'user',  Username: 'foo_map',  Email: 'secret', Password: '[email protected]'.


00:10:42.633 INFO  [main][org.ek.sample.Main] 

    User found - Key of Map: 'username',  Username: 'foo_map',  Email: 'null', Password: 'null'.

4 est headerEnricher, et si vous récupérez MessageHeader selon la méthode, les attributs seront ajoutés à l'en-tête comme spécifié dans xml. La raison pour laquelle seul l'en-tête est implémenté de cette manière est que, comme mentionné ci-dessus, la passerelle par défaut est de retourner la charge utile, il n'a donc pas été possible d'obtenir la valeur de l'en-tête ainsi que l'enrichissement de la charge utile. Cependant, cela seul semble difficile à utiliser, et j'ai pensé que je pourrais d'une manière ou d'une autre définir l'en-tête pour qu'il soit enrichi de la balise `` gateway '', mais je l'étudierai quand j'aurai le temps. Voici le résultat d'affichage de 6.

00:16:42.883 INFO  [main][org.ek.sample.Main] 

    headerTest :test, addedHeader :FOO.BAR

Cette fois, j'ai utilisé la balise `` gateway '', qui n'est pas un adaptateur, pour la première fois, j'ai donc eu l'impression d'avoir en quelque sorte compris les bases de l'intégration. À propos, dans quel ordre les échantillons doivent-ils être mis en œuvre afin d'apprendre efficacement l'intégration des ressorts?

Le code implémenté cette fois est le suivant. Exemple modifié

Recommended Posts

Mémorandum d'étude sur l'intégration de Spring ~ Comprendre l'exemple d'intégration de Spring 3. Enricher ~
Mémorandum d'étude sur l'intégration de Spring ~ Comprendre l'exemple d'intégration de Spring 1. Hello World ~
Mémorandum de l'étude sur l'intégration de Spring ~ Comprendre l'exemple d'intégration de Spring 2. Passerelle JMS ~
Mémorandum WebMvcConfigurer de Spring Boot 2.0 (printemps 5)
Mémorandum d'étude Java
Spring Boot Rappelez-vous
Mémorandum (Spring Web)
Mémorandum de la session d'étude Javasilver