Java >> Java Tutorial >  >> Tag >> Spring

Spring From the Trenches:Verwenden von umgebungsspezifischen Cron-Ausdrücken mit der @Scheduled-Anmerkung

Die @Scheduled Annotation bietet eine einfache Möglichkeit, geplante Aufgaben in Spring-basierten Anwendungen zu erstellen. Wir können es verwenden, um unsere Aufgaben zu planen, indem wir entweder periodische Planung oder Cron-Ausdrücke verwenden.

Obwohl die Zeitplanung auch nützlich sein kann, geben uns die Cron-Ausdrücke viel mehr Kontrolle über den Aufruf der geplanten Aufgaben. Deshalb sind sie in realen Anwendungen sehr nützlich.

Die Verwendung von Cron-Ausdrücken hat jedoch einen großen Nachteil, wenn sie nicht richtig gemacht wird.

Lassen Sie uns herausfinden, was das ist.

Erstellen einer geplanten Aufgabe

Nehmen wir an, wir wollen einen Task erstellen, der einmal pro Sekunde aufgerufen wird und einfach eine Nachricht ins Log schreibt.

Wir können diese Aufgabe erstellen, indem wir diesen Schritten folgen (Wir werden die erforderliche Konfiguration überspringen, da sie im zweiten Teil dieses Beitrags beschrieben wird):

  1. Erstellen Sie eine Klasse namens ScheduledJob .
  2. Annotieren Sie die Klasse mit @Component Anmerkung.
  3. Erstellen Sie einen privaten Logger Feld und instanziieren Sie das erstellte Feld.
  4. Erstellen Sie eine öffentliche Methode namens run() und stellen Sie sicher, dass der Rückgabetyp void ist .
  5. Kommentieren Sie die Methode mit @Scheduled annotation und setzen Sie den verwendeten Cron-Ausdruck als Wert von cron -Attribut (Cron Scheduler in Spring bietet einen schönen Überblick über Cron-Ausdrücke).
  6. Implementieren Sie die Methode, indem Sie eine einzelne Nachricht in das Protokoll schreiben.

Der Quellcode des ScheduledJob Klasse sieht wie folgt aus:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledJob.class);

    @Scheduled(cron = "0-59 * * * * *")
    public void run() {
        LOGGER.debug("run()");
    }
}

Das Problem unserer Implementierung ist, dass der Cron-Ausdruck fest codiert ist. Dies bedeutet, dass es nicht möglich ist, unterschiedliche Konfigurationen in unterschiedlichen Umgebungen zu verwenden.

Wenn wir in verschiedenen Umgebungen unterschiedliche Scheduling-Konfigurationen verwenden möchten, müssen wir die Konfiguration manuell ändern, bevor wir die bereitgestellte Binärdatei erstellen.

Das ist natürlich fehleranfällig. Da die Folgen einer falschen Scheduling-Konfiguration schwerwiegend sein können, müssen wir einen Weg finden, unsere Cron-Ausdrücke aus dem Code in die Konfigurationsdateien unseres Projekts zu verschieben.

Cron-Ausdrücke in eine Eigenschaftendatei verschieben

Auf der Suche nach einer Lösung für unser Problem bin ich auf diesen Thread gestoßen. Die in diesem Blogbeitrag beschriebene Lösung basiert auf dieser Diskussion.

Die Anforderungen unserer Lösung sind folgende:

  • Es muss unterschiedliche Konfigurationen für Produktions- und Entwicklungsumgebung haben.
  • Wenn die geplante Aufgabe in der Entwicklungsumgebung ausgeführt wird, muss sie einmal pro Sekunde aufgerufen werden.
  • Wenn die geplante Aufgabe in der Produktionsumgebung ausgeführt wird, muss sie einmal pro Minute aufgerufen werden.

Wir können diese Anforderungen erfüllen, indem wir diesen Schritten folgen:

  1. Maven konfigurieren.
  2. Erstellen Sie die Eigenschaftendateien.
  3. Konfigurieren Sie den Anwendungskontext.
  4. Ändern Sie die Aufgabenklasse.

Fangen wir an.

Maven konfigurieren

Wir können Maven konfigurieren, indem wir diesen Schritten folgen:

  1. Erstellen Sie Profile sowohl für die Entwicklungs- als auch für die Produktionsumgebung.
  2. Ressourcenfilterung konfigurieren.

Lassen Sie uns weitermachen und herausfinden, wie das gemacht wird.

Profile für Entwicklungs- und Produktionsumgebung erstellen

Wie wir uns erinnern, müssen wir Maven-Profile sowohl für die Entwicklungs- als auch für die Produktionsumgebung erstellen.

Wir können das in der Entwicklungsumgebung verwendete Profil erstellen, indem wir diesen Schritten folgen:

  1. Fügen Sie den Profilen ein neues Profil hinzu Abschnitt der POM-Datei.
  2. Legen Sie die ID fest des erstellten Profils an 'dev'.
  3. Stellen Sie sicher, dass das Entwicklungsprofil standardmäßig aktiv ist.
  4. Erstellen Sie eine Eigenschaft namens build.profile.id und setze seinen Wert auf 'dev'.

Wir können das Produktionsprofil erstellen, indem wir diesen Schritten folgen:

  1. Fügen Sie den Profilen ein neues Profil hinzu Abschnitt der POM-Datei.
  2. Legen Sie die ID fest des erstellten Profils an 'prod'.
  3. Erstellen Sie eine Eigenschaft namens build.profile.id und setze seinen Wert auf 'prod'.

Der Profilabschnitt unserer pom.xml Datei sieht wie folgt aus:

<profiles>
	<profile>
		<id>dev</id>
		<activation>
			<activeByDefault>true</activeByDefault>
		</activation>
		<properties>
			<build.profile.id>dev</build.profile.id>
		</properties>
	</profile>
	<profile>
		<id>prod</id>
		<properties>
			<build.profile.id>prod</build.profile.id>
		</properties>
	</profile>
</profiles>

Wir verwenden die build.profile.id -Eigenschaft, wenn wir die Ressourcenfilterung unseres Builds konfigurieren. Mal sehen, wie das gemacht wird.

Konfigurieren der Ressourcenfilterung

Wir können die Ressourcenfilterung konfigurieren, indem wir diesen Schritten folgen:

  1. Konfigurieren Sie den Speicherort der Konfigurationsdatei, die die profilspezifischen Eigenschaften enthält (Der Wert der build.profile.id Eigenschaft identifiziert das verwendete Profil).
  2. Konfigurieren Sie den Speicherort des Ressourcenverzeichnisses und aktivieren Sie die Ressourcenfilterung.

Der relevante Teil unserer pom.xml Datei sieht wie folgt aus:

<filters>
    <filter>profiles/${build.profile.id}/config.properties</filter>
</filters>
<resources>
    <resource>
        <filtering>true</filtering>
        <directory>src/main/resources</directory>
    </resource>
</resources>

Erstellen der Eigenschaftendateien

Wir können die erforderlichen Eigenschaftendateien erstellen, indem wir diesen Schritten folgen:

  1. Wir müssen eine Eigenschaftendatei für die Entwicklungsumgebung erstellen.
  2. Wir müssen eine Eigenschaftendatei für die Produktionsumgebung erstellen.
  3. Wir müssen eine Eigenschaftsdatei erstellen, die von unserer Anwendung gelesen wird.

Fangen wir an.

Erstellen der Eigenschaftendatei für die Entwicklungsumgebung

Wir können die Eigenschaftendatei für die Entwicklungsumgebung erstellen, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine Datei namens config.properties zu den profiles/dev Verzeichnis.
  2. Legen Sie den Wert von scheduling.job.cron fest Eigenschaft auf '0-59 * * * * *'. Dadurch wird sichergestellt, dass die Aufgabe einmal pro Sekunde aufgerufen wird.

Der Inhalt der profiles/dev/config.properties Datei sieht wie folgt aus:

scheduling.job.cron=0-59 * * * * *

Erstellen der Eigenschaftendatei für die Produktionsumgebung

Wir können die Eigenschaftendatei für die Produktionsumgebung erstellen, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine Datei namens config.properties zu den profiles/prod Verzeichnis.
  2. Legen Sie den Wert von scheduling.job.cron fest Eigenschaft auf '0 0-59 * * * *'. Dadurch wird sichergestellt, dass die Aufgabe einmal pro Minute aufgerufen wird.

Der Inhalt von profiles/prod/config.properties Datei sieht wie folgt aus:

scheduling.job.cron=0 0-59 * * * *

Erstellen der Eigenschaftendatei unserer Anwendung

Wir können die Eigenschaftendatei unserer Anwendung erstellen, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine Datei namens application.properties zu src/main/resources Verzeichnis.
  2. Legen Sie den Wert von scheduling.job.cron fest Eigenschaft zu '${scheduling.job.cron}'. Dadurch wird sichergestellt, dass der Platzhalter durch den richtigen Cron-Ausdruck ersetzt wird.

Der Inhalt von src/main/resources/application.properties Datei sieht wie folgt aus:

scheduling.job.cron=${scheduling.job.cron}

Konfigurieren des Anwendungskontexts

Wir können den Anwendungskontext unserer Anwendung konfigurieren, indem wir entweder eine Java-Konfigurationsklasse oder eine XML-Konfigurationsdatei verwenden.

Beide Möglichkeiten werden im Folgenden beschrieben.

Java-Konfiguration

Wir können die Anwendungskontext-Konfigurationsklasse erstellen, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine Klasse namens ExampleApplicationContext .
  2. Annotieren Sie die Klasse mit @Configuration Anmerkung.
  3. Aktivieren Sie die Planung, indem Sie die Klasse mit @EnableScheduling kommentieren Anmerkung.
  4. Kommentieren Sie die Klasse mit @ComponentScan Anmerkung und konfigurieren Sie die gescannten Pakete.
  5. Kommentieren Sie die Klasse mit @PropertySource Anmerkung und stellen Sie sicher, dass die Eigenschaften aus einer Eigenschaftendatei namens application.properties geladen werden die aus dem Klassenpfad gefunden wird.
  6. Erstellen Sie einen neuen PropertySourcesPlaceHolderConfigurer Bohne.

Der Quellcode unserer Anwendungskontext-Konfigurationsklasse sieht wie folgt aus:

import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
@ComponentScan(basePackages = {
        "net.petrikainulainen.spring.trenches.scheduling"
})
@PropertySource("classpath:application.properties")
public class ExampleApplicationContext {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();

        properties.setLocation(new ClassPathResource( "application.properties" ));
        properties.setIgnoreResourceNotFound(false);

        return properties;
    }
}

XML-Konfiguration

Wir können die Anwendungskontext-Konfigurationsdatei erstellen, indem wir diesen Schritten folgen:

  1. Verwenden Sie den Eigenschaftsplatzhalter Element des Kontextes Namespace zum Laden der Eigenschaften aus der Eigenschaftendatei namens application.properties die aus dem Klassenpfad gefunden wird.
  2. Verwenden Sie die Anmerkungskonfiguration Element des Kontextes Namespace, um sicherzustellen, dass die "allgemeinen" Anmerkungen von unseren Bean-Klassen erkannt werden.
  3. Verwenden Sie den Komponenten-Scan Element des Kontextes Namensraum zum Konfigurieren der gescannten Pakete.
  4. Aktivieren Sie die Planung mithilfe der anmerkungsgesteuerten Element der Aufgabe Namensraum.

Der Quellcode unserer Anwendungskontext-Konfigurationsdatei sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">

    <context:property-placeholder location="classpath:application.properties" ignore-resource-not-found="false"/>

    <context:annotation-config/>
    <context:component-scan base-package="net.petrikainulainen.spring.trenches.scheduling"/>
    <task:annotation-driven/>
</beans>

Ändern der geplanten Aufgabe

Unser letzter Schritt besteht darin, unsere Aufgabenklasse zu ändern und sicherzustellen, dass der verwendete Cron-Ausdruck aus der application.properties gelesen wird Datei. Wir können dies tun, indem wir den Wert von cron setzen Attribut von @Scheduled Anmerkung zu '${scheduling.job.cron}'.

Der Quellcode des ScheduledJob Klasse sieht wie folgt aus:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledJob.class);

    @Scheduled(cron = "${scheduling.job.cron}")
    public void run() {
        LOGGER.debug("run()");
    }
}

Zusammenfassung

Wir haben jetzt eine geplante Aufgabe erstellt, die den verwendeten Cron-Ausdruck aus einer Eigenschaftendatei liest. Dieser Blogbeitrag hat uns drei Dinge gelehrt:

  • Wir haben gelernt, dass die Hartcodierung des verwendeten Cron-Ausdrucks es schwierig macht, unterschiedliche Konfigurationen in verschiedenen Umgebungen zu verwenden.
  • Wir haben gelernt, wie wir Maven verwenden können, um die profilspezifischen Konfigurationseigenschaften in profilspezifische Konfigurationsdateien aufzuteilen.
  • Wir haben gelernt, den Anwendungskontext unserer Anwendung zu konfigurieren und den verwendeten Cron-Ausdruck aus einer Eigenschaftendatei zu lesen.

Die Beispielanwendung dieses Blogbeitrags ist wie immer auf Github verfügbar.


Java-Tag