Spring Boot og Togglz Aspect

1. Oversigt

I denne vejledning skal vi se på, hvordan Togglz bibliotek kan bruges med en Spring Boot-applikation.

2. Togglz

Det Togglz biblioteket giver en implementering af Funktion skifter design mønster. Dette mønster refererer til at have en mekanisme, der gør det muligt at bestemme, under en applikations kørselstid, om en bestemt funktion er aktiveret eller ikke baseret på en skift.

Deaktivering af en funktion ved kørsel kan være nyttig i en række situationer, såsom at arbejde på en ny funktion, der endnu ikke er komplet, kun ønsker at give adgang til en funktion til en delmængde af brugere eller køre A / B-test.

I de følgende sektioner opretter vi et aspekt, der opfanger metoder med en kommentar, der giver et funktionsnavn, og bestemmer, om metoderne skal fortsættes, afhængigt af om funktionen er aktiveret eller ej.

3. Maven-afhængigheder

Sammen med Spring Boot afhængigheder, er Togglz biblioteket indeholder en Spring Boot Starter jar:

 org.springframework.boot spring-boot-starter-parent 2.0.1.RELEASE org.togglz togglz-spring-boot-starter 2.4.1 org.togglz togglz-spring-security 2.4.1 org.springframework.boot spring-boot- starter-web org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-test com.h2database h2 1.4.194 

De nyeste versioner af togglz-spring-boot-starter, togglz-spring-security, spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-test, h2 kan downloades fra Maven Central.

4. Togglz-konfiguration

Det togglz-spring-boot-starter biblioteket indeholder automatisk konfiguration til oprettelse af de nødvendige bønner som f.eks FeatureManager. Den eneste bønne, vi skal levere, er featureProvider bønne.

Lad os først oprette en optælling, der implementerer Funktion interface og indeholder en liste over funktionsnavne:

offentlig enum MyFeatures implementerer Feature {@Label ("Employee Management Feature") EMPLOYEE_MANAGEMENT_FEATURE; offentlig boolsk isActive () {return FeatureContext.getFeatureManager (). isActive (dette); }}

Tællingen definerer også en metode, der kaldes isActive () der verificerer, om en bestemt funktion er aktiveret.

Så kan vi definere en bønne af typen EnumBasedFeatureProvider i en Spring Boot-konfigurationsklasse:

@Configuration public class ToggleConfiguration {@Bean public FeatureProvider featureProvider () {returner ny EnumBasedFeatureProvider (MyFeatures.class); }}

5. Oprettelse af aspektet

Dernæst opretter vi et aspekt, der opfanger en brugerdefineret AssociatedFeature kommentar og kontrollerer funktionen, der er angivet i kommentarparameteren for at afgøre, om den er aktiv eller ej:

@Aspect @Component offentlig klasse FeaturesAspect {privat statisk endelig Logger LOG = Logger.getLogger (FeaturesAspect.class); @Around ("@within (featureAssociation) || @annotation (featureAssociation)") public Object checkAspect (ProceedingJoinPoint joinPoint, FeatureAssociation featureAssociation) kaster Throwable {if (featureAssociation.value (). IsActive ()) {return joinPoint.proceed () ; } ellers {LOG.info ("Feature" + featureAssociation.value (). name () + "er ikke aktiveret!"); returnere null; }}}

Lad os også definere den kaldte brugerdefinerede kommentar FeatureAssociation der vil have en værdi() parameter af typen MyFeatures enum:

@Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.METHOD, ElementType.TYPE}) offentlig @interface FeatureAssociation {MyFeatures-værdi (); }

Hvis funktionen er aktiv, fortsætter aspektet udførelsen af ​​metoden; hvis ikke, logger den en besked uden at køre metoden.

6. Aktivering af funktion

En funktion i Togglz kan være enten aktiv eller inaktiv. Denne adfærd styres af en aktiveret flag og eventuelt en aktiveringsstrategi.

For at indstille aktiveret flag til sandt, kan vi bruge @EnabledByDefault kommentar om definitionen af ​​enumværdi.

Togglz biblioteket giver også en række aktiveringsstrategier, der kan bruges til at bestemme, om en funktion er aktiveret baseret på en bestemt tilstand.

Lad os i vores eksempel bruge SystemPropertyActivationStrategy til vores EMPLOYEE_MANAGEMENT_FEATURE, som evaluerer funktionens tilstand baseret på værdien af ​​en systemegenskab. Det krævede ejendomsnavn og -værdi kan specificeres ved hjælp af @ActivationParameter kommentar:

public enum MyFeatures implementerer Feature {@Label ("Medarbejderstyringsfunktion") @EnabledByDefault @DefaultActivationStrategy (id = SystemPropertyActivationStrategy.ID, parameters = {@ActivationParameter (name = SystemPropertyActivationStrategy.PARAM_PROAM_PROAM_PARAM_PROAM_PARAM_PARAM_PROAM_PARAM_PROAM_PARAM_PRO) name = SystemPropertyActivationStrategy.PARAM_PROPERTY_VALUE, value = "true")}) EMPLOYEE_MANAGEMENT_FEATURE; // ...}

Vi har indstillet vores funktion til kun at være aktiveret, hvis medarbejder. funktion ejendom har værdien rigtigt.

Andre typer aktiveringsstrategier leveret af Togglz bibliotek er:

  • BrugernavnActivationStrategy - gør det muligt for funktionen at være aktiv for en specificeret liste over brugere
  • UserRoleActivationStrategy - den aktuelle brugers rolle bruges til at bestemme tilstanden for en funktion
  • ReleaseDateActivationStrategy - aktiverer automatisk en funktion på en bestemt dato og et bestemt tidspunkt
  • GradualActivationStrategy - aktiverer en funktion for en bestemt procentdel af brugerne
  • ScriptEngineActivationStrategy - tillader brug af et brugerdefineret script skrevet på et sprog, der understøttes af ScriptEngine af JVM for at bestemme, om en funktion er aktiv eller ej
  • ServerIpActivationStrategy - en funktion er aktiveret baseret på IP-adresser på serveren

7. Test af aspektet

7.1. Eksempel på anvendelse

For at se vores aspekt i aktion, lad os oprette et simpelt eksempel, der indeholder en funktion til styring af medarbejderne i en organisation.

Da denne funktion vil blive udviklet, kan vi tilføje metoder og klasser, der er kommenteret med vores @AssociatedFeature kommentar med værdien EMPLOYEE_MANAGEMENT_FEATURE. Dette sikrer, at de kun er tilgængelige, hvis funktionen er aktiv.

Lad os først definere en Medarbejder enhedsklasse og lager baseret på forårsdata:

@Entity offentlig klassemedarbejder {@Id privat lang id; privat dobbelt løn // standard konstruktør, getters, setters}
offentlig grænseflade EmployeeRepository udvider CrudRepository {}

Lad os derefter tilføje en Medarbejderstjeneste med en metode til at øge en medarbejders løn. Vi tilføjer @AssociatedFeature kommentar til metoden med parameteren EMPLOYEE_MANAGEMENT_FEATURE:

@Service offentlig klasse SalaryService {@Autowired EmployeeRepository medarbejderRepository; @FeatureAssociation (værdi = MyFeatures.EMPLOYEE_MANAGEMENT_FEATURE) offentlig tomrumsforøgelseSalary (lang id) {Medarbejdermedarbejder = workerRepository.findById (id) .orElse (null); medarbejder.setSalary (medarbejder.getSalary () + medarbejder.getSalary () * 0,1); workerRepository.save (medarbejder); }} 

Metoden kaldes fra en / stigningLøn slutpunkt, som vi vil kalde til test:

@Controller offentlig klasse SalaryController {@Autowired SalaryService salaryService; @PostMapping ("/ increaseSalary") @ResponseBody public void increaseSalary (@RequestParam long id) {lønService.increaseSalary (id); }}

7.2. JUnit-test

Lad os først tilføje en test, hvor vi kalder vores POST-kortlægning efter indstilling af medarbejder. funktion ejendom til falsk. I dette tilfælde bør funktionen ikke være aktiv, og værdien af ​​medarbejderens løn bør ikke ændre sig:

@Test offentlig ugyldighed givenFeaturePropertyFalse_whenIncreaseSalary_thenNoIncrease () kaster undtagelse {Medarbejder emp = ny medarbejder (1, 2000); medarbejderRepository.save (emp); System.setProperty ("medarbejderfunktion", "falsk"); mockMvc.perform (post ("/ increaseSalary") .param ("id", emp.getId () + "")). og Expect (status (). er (200)); emp = workerRepository.findOne (1L); assertEquals ("forkert løn", 2000, emp.getSalary (), 0,5); }

Lad os derefter tilføje en test, hvor vi udfører opkaldet efter at have indstillet ejendommen til rigtigt. I dette tilfælde skal lønværdien øges:

@Test offentlig ugyldighed givenFeaturePropertyTrue_whenIncreaseSalary_thenIncrease () kaster undtagelse {Medarbejder emp = ny medarbejder (1, 2000); medarbejderRepository.save (emp); System.setProperty ("medarbejderfunktion", "sand"); mockMvc.perform (post ("/ increaseSalary") .param ("id", emp.getId () + "")). og Expect (status (). er (200)); emp = workerRepository.findById (1L) .orElse (null); assertEquals ("forkert løn", 2200, emp.getSalary (), 0,5); }

8. Konklusioner

I denne vejledning har vi vist, hvordan vi kan integrere Togglz bibliotek med Spring Boot ved hjælp af et aspekt.

Den fulde kildekode for eksemplet kan findes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found