Préface
Lorsque nous utilisons l'annotation @discoveryclient, aurons-nous la question suivante: Pourquoi effectue-t-il le fonctionnement de l'enregistrement d'un service? Ne devrait-il pas être utilisé comme découverte de service? Explorons en profondeur son code source.
1. Interface de cycle de vie de Springframework
Pour comprendre ce problème, nous devons comprendre cette interface importante:
/ * * Copyright 2002-2015 L'auteur ou les auteurs originaux. * * Licencié sous la licence Apache, version 2.0 (la "licence"); * Vous ne pouvez pas utiliser ce fichier sauf conforme à la licence. * Vous pouvez obtenir une copie de la licence à * * http://www.apache.org/licenses/license-2.0 * * sauf si la loi applicable ou convenu par écrit, le logiciel * distribué sous la licence est distribué sur une base "en tant que", * sans garantie ou conditions de toute nature, exprimée ou impliquée. * Voir la licence pour la langue spécifique régissant les autorisations et les * limitations sous la licence. * / package org.springframework.context; / ** * Une interface commune de définition des méthodes pour le contrôle du cycle de vie start / stop. * Le cas d'utilisation typique est de contrôler le traitement asynchrone. * <b> Remarque: cette interface n'implique pas une sémantique spécifique de démarrage automatique. * Envisagez d'implémenter {@Link SmartLifecycle} à cette fin. </b> * * <p> peut être implémenté par les deux composants (généralement un bean de printemps défini dans un contexte * Spring) et les conteneurs (généralement un printemps {@link applicationContext} * lui-même). Les conteneurs propageront les signaux de démarrage / arrêt à tous les composants qui * s'appliquent dans chaque conteneur, par exemple pour un scénario d'arrêt / redémarrage au moment de l'exécution. * * <p> peut être utilisé pour les invocations directes ou pour les opérations de gestion via JMX. * Dans ce dernier cas, le {@link org.springframework.jmx.export.mbeanExporter} * sera généralement défini avec un * {@Link Org.SpringFramework.jmx.export.Assebler.Interface-BasedMBeanInfoAssebler}, * Interface. * * <p> Notez que l'interface de cycle de vie n'est prise en charge que sur <b> singleton de niveau supérieur * Beans </b>. Sur tout autre composant, l'interface de cycle de vie restera non détectée * et donc ignorée. Notez également que l'interface {@link smartlifecycle} étendue * fournit l'intégration avec les phases de démarrage et d'arrêt du contexte de l'application. * * @Author Juergen Hoeller * @Since 2.0 * @see SmartLifecycle * @see ConfigurableApplicationContext * @see org.springframework.jms.Listener.abstractMessageLentenConainer * @see org.springframework.Scheling.Quartz.schedUlUl / ** * Démarrez ce composant. * <p> ne doit pas lancer une exception si le composant est déjà en cours d'exécution. * <p> Dans le cas d'un conteneur, cela propagera le signal de démarrage à tous les * composants qui s'appliquent. * @see smartlifecycle # IsautostArtup () * / void start (); / ** * Arrêtez ce composant, généralement de manière synchrone, de sorte que le composant est * complètement arrêté au retour de cette méthode. Envisagez d'implémenter {@Link SmartLifecycle} * et sa variante {@code stop (runnable)} Lorsque le comportement d'arrêt asynchrone est nécessaire. * <p> Notez que cette notification d'arrêt n'est pas garantie avant la destruction: sur * Arrêt régulier, {@Code Lifecycle} Les haricots recevront d'abord une notification d'arrêt avant * Les rappels de destruction généraux se propagent; Cependant, lors de l'actualisation à chaud pendant la durée de vie d'un contexte ou sur les tentatives de rafraîchissement abandonnées, seuls les méthodes de détruire seront appelées. * <p> ne devrait pas lancer une exception si le composant n'est pas encore démarré. * <p> Dans le cas d'un conteneur, cela propagera le signal d'arrêt à tous les composants * qui s'appliquent. * @see smartlifeccycle # stop (runnable) * @see org.springframework.beans.factory.disposablebean # destre () * / void stop (); / ** * Vérifiez si ce composant est en cours d'exécution. * <p> Dans le cas d'un conteneur, cela ne reviendra {@code true} que si <i> tous les composants </i> * qui s'appliquent sont en cours d'exécution. * @return si le composant est actuellement en cours d'exécution * / booléen isrunning ();}Cette interface définit la méthode de contrôle du cycle de vie start / stop. Lorsque le conteneur Spring IOC démarre ou s'arrête, un signal de démarrage ou d'arrêt sera envoyé à chaque composant, afin que nous puissions faire ce que nous voulons dans la méthode correspondante. Nous pouvons trouver à travers le diagramme de classe que nous utilisons couramment la classe ClassPathxmlApplicationContext implémente cette interface
Voyons brièvement le cas et créons la classe MyLifecycle:
package org.hzgj.spring.study.context; import org.springframework.context.smartlifecycle; public class MyLifecycle implémente SmartLifecycle {@Override public void start () {System.out.println ("MyLifecycle Start ...."); } @Override public void stop () {System.out.println ("Mylifecycle stop ....."); } @Override public boolean isrunning () {return false; } @Override public boolean isautostartup () {return true; } @Override public void stop (Runnable Rappel) {} @Override public int getphase () {System.out.println ("phase"); retour 10; }}Ici, nous héritons de Smartlifecycle. L'interface hérite du cycle de vie. La méthode Isrunning est utilisée pour détecter si le composant actuel est à l'état de course. Notez qu'il ne peut s'exécuter que lorsque la valeur de retour Isrunning est fausse.
Nous configurons MyLifecycle dans le fichier de configuration de Spring et exécutons via ClassPathxmlApplicationContext pour obtenir les résultats suivants:
De plus, la méthode Getphase ici est de définir la valeur de la scène (elle peut être comprise comme une priorité. Plus la valeur est petite, plus le cycle de vie correspondant est exécuté en premier)
2. Recherche de code source DiscoveryClient
@Enablediscoveyclient
/ * * Copyright 2013-2015 L'auteur ou les auteurs originaux. * * Licencié sous la licence Apache, version 2.0 (la "licence"); * Vous ne pouvez pas utiliser ce fichier sauf conforme à la licence. * Vous pouvez obtenir une copie de la licence à * * http://www.apache.org/licenses/license-2.0 * * sauf si la loi applicable ou convenu par écrit, le logiciel * distribué sous la licence est distribué sur une base "en tant que", * sans garantie ou conditions de toute nature, exprimée ou impliquée. * Voir la licence pour les autorisations de gouvernance linguistique spécifiques et les * limitations sous la licence. * / package org.springframework.cloud.client.discovery; import java.lang.annotation.documented; import java.lang.annotation.elementtype; import java.lang.annotation.inherite java.lang.annotation.target; import org.springframework.context.annotation.import; / ** * annotation pour activer une implémentation DiscoveryClient. * @Author Spencer Gibb * / @ Target (elementType.Type) @retention (RetenderPolicy.Runtime) @ documenté @ hérité @ import (ENablediscoveryClientImportSelector.class) public @Interface EmptimediscoveryClient {/ ** * If True, le Serviceregry enregistrera automatiquement le serveur local. * / boolean autoregister () par défaut true;} Veuillez noter que @Import(EnableDiscoveryClientImportSelector.class) Nous pouvons nous référer à cette classe:
/ * * Copyright 2013-2015 L'auteur ou les auteurs originaux. * * Licencié sous la licence Apache, version 2.0 (la "licence"); * Vous ne pouvez pas utiliser ce fichier sauf conforme à la licence. * Vous pouvez obtenir une copie de la licence à * * http://www.apache.org/licenses/license-2.0 * * sauf si la loi applicable ou convenu par écrit, le logiciel * distribué sous la licence est distribué sur une base "en tant que", * sans garantie ou conditions de toute nature, exprimée ou impliquée. * Voir la licence pour la langue spécifique régissant les autorisations et les * limitations sous la licence. * / package org.springframework.cloud.client.discovery; import org.springframework.boot.bind.relatedpropertyResolver; import org.springframework.cloud.commons.util.springfactoryImportSelect org.springframework.core.annotation.annotationAtTributes; import org.springframework.core.annotation.order; import org.springframework.core.env.configurable environment; import org.springframework.core.env.environment; import; org.springframework.core.env.mappropertysource; import org.springframework.core.type.annotationMetadata; import java.util.arraylist; import java.util.arrays; * / @ Order (ordonné.lowest_precedence - 100) classe publique ENTIPEDISCOVERYCLIENTIMPORTSELLECTEOR étend SpringFactoryImportSelector <EablediscoveryClient> {@Override public String [] selectImports (annotationMetadata metadata) {string [] import AnnotationAtTributes Attributes = annotationAttributes.Frommap (metadata.getAntoTationAttributes (getAnnotationClass (). GetName (), true)); booléen autoregister = attributs.getBoolean ("autoregister"); if (autoregister) {list <string> import ImportsList.add ("org.springframework.cloud.client.serviceRegistry.AutoServiceRegistrationConfiguration"); importations = importations.toArray (new String [0]); } else {Environment Env = Getenvironment (); if (configurableenvironment.class.isinstance (Env)) {configurableenvironment configenv = (configurableenvironment) env; LinkedHashMap <String, objet> map = new LinkedHashMap <> (); map.put ("printemps.cloud.service-registry.auto-inscription.enabled", false); MAPPROPERTYSOURCE PropertySource = new MappRopertySource ("SpringCloudDiscoveryClient", map); configenv.getPropertySources (). AddLast (propriétéSource); }} return importations; } @Override Protected Boolean iSenabled () {return new RelaxEdPropertyResolver (GETENVIRONMENT ()). GetProperty ("Spring.cloud.discovery.enabled", boolean.class, boolean.true); } @Override Protected Boolean HasdefaultFactory () {return true; }} La méthode de réécriture de cette classe provient de l'interface importselector. Nous pouvons suivre la classe en fonction du code sous if(autoRegister) : org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration . Jetons un coup d'œil au diagramme structurel:
Nous pouvons savoir que cette classe implémente l'interface de cycle de vie, alors jetons un coup d'œil à la méthode de démarrage, qui est dans sa classe parent AbstractDiscoverylifecycle:
/ * * Copyright 2013-2015 L'auteur ou les auteurs originaux. * * Licencié sous la licence Apache, version 2.0 (la "licence"); * Vous ne pouvez pas utiliser ce fichier sauf conforme à la licence. * Vous pouvez obtenir une copie de la licence à * * http://www.apache.org/licenses/license-2.0 * * sauf si la loi applicable ou convenu par écrit, le logiciel * distribué sous la licence est distribué sur une base "en tant que", * sans garantie ou conditions de toute nature, exprimée ou impliquée. * Voir la licence pour la langue spécifique régissant les autorisations et les * limitations sous la licence. * / package org.springframework.cloud.client.discovery; import java.util.concurrent.atomic.atomicboolean; import java.util.concurrent.atomic.atomicinteger org.apache.commons.logging.logfactory; import org.springframework.beans.beansexception; import org.springframework.boot.context.embedded.embededServletContainerinitializeEvent; import org.springframework.cloud.client.discovery.event.instère org.springframework.cloud.client.servicegistry.serviceRegistry; import org.springframework.context.applicationcontext; import org.springframework.context.applicationContexware; import org.springframework.context.applicationner; Méthodes de cycle de vie qui peuvent être utiles et communes à diverses implémentations DiscoveryClient. * * @deprecated Use {@link org.springframework.cloud.client.serviceRegistry.abstractautoServiciceRegistration} à la place. Ce cours sera supprimé dans le train à prochain. * * @Author Spencer Gibb * / @ déprécatedPublic Résumé Classe AbstractDiscoverylifecycle implémente DiscoveryLifecycle, ApplicationContextAware, ApplicationListener <EmbedDeDServletContainerInitializeEvent> {private static Final Logger = LogFactory.getLog (AbstractDiscoveryLifECCyled static static); Class); Autostartup booléen privé = true; ATOMICBOOLÉAN PRIVÉ RUNACTION = NOUVEAU ATOMICBOOLEAN (FAUX); INT PRIVÉ ORDRE = 0; Contexte privé ApplicationContext; environnement privé; Port atomicInteger privé = nouveau atomicInteger (0); Application Context Protected getContext () {return Context; } @Override public void setApplicationContext (ApplicationContext ApplicationContext) lève BeanSException {this.context = applicationContext; this.environment = this.context.getEnvironment (); } @Deprecated Protected Environment Getenvironment () {Return Environment; } @Deprecated Protected atomicInteger getport () {return port; } @Override public boolean isautostartup () {return this.autostartup; } @Override public void stop (Runnable Callback) {try {stop (); } catch (exception e) {logger.error ("Un problème s'est produit en essayant d'arrêter le cycle de vie de découverte", e); } callback.run (); } @Override public void start () {if (! IseNabled ()) {if (logger.isdebugeNabled ()) {logger.debug ("Discovery Lifecycle Disabled. Ne pas démarrer"); } retour; } // Définissez le port si le non -curport est 0 et this.port! = 0 if (this.port.get ()! = 0 && getConfiguredport () == 0) {setConfiguredport (this.port.get ()); } // Initialiser uniquement si non secreport est supérieur à 0 et il n'est pas déjà en cours d'exécution // en raison de ContainerportInitializer ci-dessous if (! this.running.get () && getConfiguredport ()> 0) {register (); if (sailgisterManagement ()) {registerManagement (); } this.context.publisheVent (new INSCENEGISTEREDEVENT <> (this, getConfiguration ())); this.running. .pareAndset (false, true); }} @Deprecated Protected Abstract int getConfiguredport (); @Deprecated Protected Abstract void SetConfiguredport (int port); / ** * @return si le service de gestion doit être enregistré auprès du {@Link ServiceRegistry} * / Protected boolean sailgisterManagement () {return getmanagementport ()! = null && managementserverportUtils.isdifferent (this.context); } / ** * @return L'objet utilisé pour configurer l'enregistrement * / @deprecated objet abstrait protégé getConfiguration (); / ** * Enregistrez le service local avec DiscoveryClient * / Protected Abstract void Register (); / ** * Enregistrez le service de gestion local avec le DiscoveryClient * / Protected void RegisterManagement () {} / ** * Dé-registrer le service local avec DiscoveryClient * / Abstract Protected void deregister (); / ** * Dé-registrer le service de gestion local avec le DiscoveryClient * / Protected void deregisterManagement () {} / ** * @return true, si le {@Link DiscoveryLifeCycle} est activé * / abstrait protégé boolean iseabled (); / ** * @return le serviceId du service de gestion * / @deprecated String Protected getManAmentServiceID () {// todo: Configurable Management Suffix return this.context.getid () + ": gestion"; } / ** * @return Nom du service du service de gestion * / @deprecated String Protected getManAmentServiceName () {// todo: Configurable Management suffix return getAppName () + ": Management"; } / ** * @return Le port de serveur de gestion * / @deprecated protégée entier GetManagementport () {return managementserverportUtils.getport (this.context); } / ** * @return le nom de l'application, actuellement la propriété Spring.Application.Name * / @deprecated String Protected GetAppName () {return this.environment.getProperty ("Spring.Application.name", "Application"); } @Override public void stop () {if (this.running.compareAndSet (true, false) && isEnabled ()) {deRegister (); if (omnifrEgistManagement ()) {deRegisterManagement (); }}} @Predestroy public void destrust () {stop (); } @Override public boolean isrunning () {return this.running.get (); } protégée atomicboolean getrunning () {return running; } @Override public int getOrder () {return this.order; } @Override public int getphase () {return 0; } @Override @deprecated public void onApplicationEvent (EmbedDedServletContainerInitializeEvent Event) {// todo: prenez SSL en compte // n'enregistrez pas le port de gestion comme le port if (! "Management" .Equals (event.getApplicationContext (). event.geteMedDedServletContainer (). Getport ()); this.start (); }}}Notez qu'il y a un morceau de ce code dans la méthode de démarrage:
if (! this.running.get () && getConfiguredport ()> 0) {registre (); if (sailgisterManagement ()) {registerManagement (); } this.context.publisheVent (new INSCENEGISTEREDEVENT <> (this, getConfiguration ())); this.running. .pareAndset (false, true); } Veuillez noter register() est une méthode abstraite de cette classe. Alors regardons le code de la classe AbstractAutoServiceRiceing, et je ne publierai que les parties clés ici:
// ..... protégée abstraitautoServiciceRegistration (ServiceRegistry <r> ServiceRegistry, autoServiceRegistrationProperties Properties) {this.serviceRegistry = ServiceRegistry; this.properties = propriétés; } //....../** * Enregistrez le service local avec le {@Link ServiceRegistry} * / @Override Protected void Register () {this.serviceRegistry.Register (getRegistration ()); }Nous pouvons constater qu'un type de service de service est passé dans le constructeur, qui est une interface que SpringCloud nous fournit pour l'enregistrement des services. Ici, EurekaserviceRegistry implémente cette interface:
/ * * Copyright 2013-2016 L'auteur ou les auteurs originaux. * * Licencié sous la licence Apache, version 2.0 (la "licence"); * Vous ne pouvez pas utiliser ce fichier sauf conforme à la licence. * Vous pouvez obtenir une copie de la licence à * * http://www.apache.org/licenses/license-2.0 * * sauf si la loi applicable ou convenu par écrit, le logiciel * distribué sous la licence est distribué sur une base "en tant que", * sans garantie ou conditions de toute nature, exprimée ou impliquée. * Voir la licence pour la langue spécifique régissant les autorisations et les * limitations sous la licence. * * / package org.springframework.cloud.netflix.eureka.serviceRegistry; import java.util.hashmap; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import org.springframework.cloug com.netflix.appinfo.instanceinfo; / ** * @author spencer gibb * / public class eurekaserviceRegistry implémente ServiceRegistry <EurekaSergistring> {private static final log = logfactory.getLog (eurekaserveregry.class); @Override public void registre (eurekarepringing reg) {peut-êtreInitializeClient (reg); if (log.isinfoenabled ()) {log.info ("Enregistrement de l'application" + reg.getInstanceConfig (). getAppName () + "avec eureka avec statut" + reg.getInstanceConfig (). getInitialStatus ()); } reg.getApplicationInfomanager () .SetInstancestatus (reg.getInstanceConfig (). getInitialStatus ()); if (reg.GethEalthCheckHandler ()! = null) {reg.geteurekaclient (). registerHealthcheck (reg.GethEalthCheckHandler ()); }} private void peut-êtreInitializEClient (eurekaRegistration reg) {// force l'initialisation des éventuelles proxys étendus reg.getApplicationInfomanager (). getInfo (); reg.geteurekaclient (). getApplications (); } @Override public void deRegister (eurekaretings reg) {if (reg.getApplicationInfomanager (). GetInfo ()! = Null) {if (log.isinfoenabled ()) {Log.info ("non réenregistrer l'application" + reg.getInstanceConfig (). GetAppname () + " } reg.getApplicationInfomanager (). setInStancestatus (instanceInfo.instancestatus.down); // La fermeture du client Eureka devrait se produire avec eurekarepringing.close () // L'inscription automatique créera un bean qui sera correctement distribué // Les inscriptions manuelles devront appeler Close ()}} @Override public void setSatus (eurekaregistration Enregistrement, String Status) {instanceInfo Info = Registration.getApplicationInfomanAgor (). // TODO: comment gérer correctement la suppression? if ("Cancel_override" .EqualSignoreCase (status)) {Enregistrement.geTeureKaclient (). AnnuleverRideStatus (info); retour; } // TODO: comment faire face aux types de statut entre les systèmes de découverte? InstanceInfo.instancestatus newstatus = instanceInfo.instancestatus.toenum (statut); Enregistrement.geTeureKaclient (). SetStatus (NewStatus, info); } @Override public Object GetStatus (EureKareEggmentation Enregistrement) {HashMap <String, Object> Status = new HashMap <> (); InstanceInfo info = Enregistrement.getApplicationInfomanager (). GetInfo (); status.put ("status", info.getStatus (). toString ()); status.put ("OverridDenstatus", info.getOverriddenStatus (). ToString ()); statut de retour; } public void close () {}}Nous pouvons donc résumer les points suivants:
1. L'utilisation de @discoveryClient pour enregistrer le service utilise le mécanisme de cycle de vie, et register() de ServiceRegistry sera exécutée lorsque le conteneur sera démarré.
2. L'utilisation de @discoveryClient est plus flexible que @enableeurekaclient et @enableeurekaserver, car elle bloque la mise en œuvre de l'enregistrement des services, et nous pouvons même personnaliser le centre d'enregistrement.
3. Cela recherchera également automatiquement l'implémentation de l'interface DiscoveryClient pour la découverte de service.
3. DiscoveryClient Practical Redis Enregistrement Center
Ci-dessous, nous mettons en œuvre une exigence basée sur Redis en tant que centre d'enregistrement pour comprendre DiscoveryClient. Soit dit en passant, comprenons les interfaces importantes de SpringCloud: ServiceRegistry, ServiceInstance. Avant cela, nous ajouterons la prise en charge de Redis:
Groupe de compilation: «org.springframework.boot», nom: «Spring-boot-starter-data-redis»
1. Implémentez l'interface d'enregistrement
Package com.hzgj.lyrk.member; import org.springframework.beans.factory.annotation.value; importation org.springframework.cloud.client.serviceRegistry.Registration; import org.springframework.sterreteotype.netounter; import java.net.inetaddress; import java.net.netweetwork; import; java.net.uri; Importer java.util.enumeration; import java.util.map; @componentpublic class Rediscrigmentation implémente l'inscription {@value ("$ {server.port}") Port entier privé; @Value ("$ {printemps.application.name}") String privé ApplicationName; hôte de chaîne privée; public void sethost (string host) {this.host = host; } public void setport (port entier) {this.port = port; } public void setApplicationName (String ApplicationName) {this.ApplicationName = applicationName; } @Override public String getServiceId () {return applicationName + ":" + gethost () + ":" + getport (); } @Override public String gethost () {try {if (host == null) return getLocalHostlanAddress (). GethostAddress (); else return hôte; } catch (exception e) {e.printStackTrace (); } return null; } @Override public int getport () {return port; } @Override public boolean issesecure () {return false; } @Override public uri getUri () {return null; } @Override Public Map <String, String> getMetAdata () {return null; } public String getServiceName () {return this.ApplicationName; } public InetAddress getLocalHostLanAddress () lève une exception {try {InetAddress CandidateAddress = null; // Traverse toutes les interfaces réseau pour (énumération ifaces = networkInterface.getNetWorkInterfaces (); ifaces.hasmoreElements ();) {NetworkInterface iface = (NetworkInterface) ifaces.NextElement (); // Traverse l'IP sous toutes les interfaces pour (énumération inEtAddrs = iface.getinetAddress (); inetAddrs.hasmoreElements ();) {InetAddress IneTADDR = (inetAddress) InetAdDr.NEXTElement (); if (! InetAddr.isloopBackAddress ()) {// Excluez l'adresse de type de boucle de boucle if (InetAdDdr.IssiteLocalAddress ()) {// S'il s'agit d'une adresse de site-local, il est retourne inetaddr; } else if (candidateaddress == null) {// L'adresse du type de site local n'a pas été trouvée, enregistrez d'abord l'adresse candidate candidateaddress = InetAddr; }}}}} if (candidateaddress! = null) {return candidateaddress; } // Si aucune adresse non-boucle n'est trouvée, vous ne pouvez utiliser que la solution la plus sélectionnée. InetAddress jdkSuppLiedAddress = InetAddress.getLocalHost (); Retour JDKSuppliedAddress; } catch (exception e) {e.printStackTrace (); } return null; }}Cette interface hérite de l'introduction par le service, de sorte que la fonction principale de cette interface est de définir les spécifications d'une instance de service, comme ce qui est son serviceId, quel est le numéro de port, etc.
2. Implémentez l'interface de la service.
Package com.hzgj.lyrk.member; import org.springframework.beans.factory.annotation.autowired; import org.springframework.cloud.client.serviceregistry.serserciceregistry; import org.springframework.data.redis.Core.stringredistelet; ServiceRegistry <Discripting> {@autowired private stringRedistemplate reidemplate; @Override public void Register (Rederiction Enregistrement) {String ServiceId = Enregistrement.getServiceId (); redetemplate.opsforlist (). LeftPush (serviceId, Enregistrement.Gethost () + ":" + Enregistrement.Getport ()); } @Override public void deRegister (Redériction d'enregistrement) {redetemplate.opsforlist (). Re Support (Enregistrement.getServiceId (), 1, Enregistrement.Gethost () + ":" + Enregistrement.getport ()); } @Override public void close () {//redistemplate.d System.out.println ("fermé ..."); } @Override public void setStatus (Rederisticsing Registration, String Status) {} @Override public <T> T getStatus (Rediscrianding Registration) {return null; }}La fonction principale de cette interface est de définir comment s'inscrire, annuler le service, définir et obtenir l'état du service, etc.
3. Hériter
Package com.hzgj.lyrk.member; import org.springframework.beans.factory.annotation.autowired; import org.springframework.cloud.client.serviceregistry.abstractautautoServiceRegistration; import org.springframework.clouent.client.ServiceRegistry.abstrustaToserviceRegs; org.springframework.cloud.client.serviceRegistry.ServiceRegistry; Classe publique RedisAutoServiceRegistration étend AbstractAutoServiceRegistration <Redisrengistration> {@Autowired Private Redisrengration Redisrengistration; RedisAutoServiceRiCistration protégée (ServiceRegistry <Rediscription> ServiceRegistry, autoServiceRegistrationProperties Properties) {super (ServiceRegistry, Properties); // ServiceRegistry.Register (getRegistration ()); } @Override Protected int getConfiguredport () {return rediscrivation.getport (); } @Override Protected void SetConfiguredport (int port) {} @Override Protected objet getConfiguration () {return null; } @Override Protected Boolean iSenabled () {return true; } @Override Protected Rediscrivation GetRegistration () {Return Rediscriand; } @Override Protected Rediscrivation getManagement Iggation () {return null; }}4. Définissez la classe d'implémentation de DiscoveryClient redisdiscoveryclient
Package com.hzgj.lyrk.member; import org.apache.commons.lang.stringutils; import org.springframework.beans.factory.annotation.autowired; import org.springframework.cloud.client.sviceInstance; import org.springframework.cloud.client.discovery.discovery org.springframework.data.redis.core.stringredistemplate; importer java.util.arraylist; import java.util.list; import java.util.function.function; import java.util.stream.collectors; classe publique redevistemlate redistemlate; @Override public String Description () {return "Discovery Service in Redis Enregistrement Center"; } @Override public ServiceInstance getLocalServiceInstance () {return null; } @Override Public List <FermediNstance> GetInStances (String ServiceId) {return reidemplate.opsforlist (). Range (ServiceId, 0, -1). ParallelStream (). Map ((fonction <string, serviceInstance>) s -> {rediscripting rediscripistration = new rediscriisting (); rediscriisting.setApplicationName (serviceId); string hostname = stringUtils.split (s, ":") [0]; Port = stringUtils.split (s, ":") [); Rediscripting.setport (Integer.Parseint (port)); } @Override public list <string> getServices () {list <string> list = new ArrayList <> (); list.addall (redestemplate.keys ("*")); Liste de retour; }}Cette classe vise principalement à la découverte du service du centre d'enregistrement Redis
5. Définissez des classes d'assemblage automatiques pour créer des haricots correspondants
package com.hzgj.lyrk.member; import org.springframework.boot.autoconfigure.condition.conditionalonproperty; import org.springframework.boot.context.properties.enableConfigurationProperties; import org.springframework.cloud.client.serviceRegistry.AutoServiceEgistationProperties; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import; org.springframework.context.annotation.primary; @ configuration @ perteConfigurationProperties (redisConfig.class) @conditionalonproperty (value = "printemps.redis.registry.enable redisconfig) {System.out.println (redisConfig.Gethost ()); Renvoie un nouveau redésserviceRegistry (); } @Bean redisautoServiceRegistration redisautoServiciceRegistration (redserviceRegistry redésserviceRiceGistry) {return new redisautoServiciceAring (redessiciceRegistry, new autoServiceRegistrationProperties ()); } @Bean @primary redisdiscoveryclient redisdiscoveryClient () {return new redisdiscoveryClient (); }}6. Définissez la classe de démarrage
package com.hzgj.lyrk.member; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.cloud.client.discovery.discoveryClient; importation; org.springframework.cloud.client.discovery.enablediscoveryclient; import org.springframework.cloud.client.discovery.composite.compositediscoveryclientautoconfiguration; import org.springframework.cloud.client.discovery. org.springframework.context.configurableApplicationContex applicationContext = SpringApplication.Run (MemberApplication.Class, Args); DiscoveryClient DiscoveryClient = ApplicationContext.getBean (DiscoveryClient.class); DiscoveryClient.getServices (). ForEach (Action -> {System.out.println (Action);}); }}Ici, l'assemblage par défaut de DiscoveryClient est exclu dans l'annotation SpringbootApplication.
Lorsque nous commençons avec succès, nous pouvons constater que la console a sorti le nom et l'adresse du service correspondant:
Nous générons à nouveau le fichier JAR via Gradle Packaging and Run:
Java -Jar Membre-Server-0.0.1-Snapshot.jar --server.port = 8800
Nous pouvons voir que la valeur enregistrée du service qui a été mise en cache dans Redis:
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.