• Link zu Xing
  • Link zu LinkedIn
  • Link zu X
  • Link zu Rss dieser Seite
  • Link zu GitHub
  • Newsletter
  • Kontaktieren Sie mich
Frank W. Rahn
  • Meine BlogbeiträgeZeigt meinen Blog an
  • RessourcenZeigt Ihnen eine Auswahl von Ressourcen
    • Franks aktueller IT-Werkzeugkasten
      • Diese Werkzeuge setze ich zur Zeit ein
    • Meine Präsentationen
      • Zeigt Ihnen meine Präsentationen
    • Weblinks
      • Meine Linksammlung
    • Buchtipps
      • Eine Liste von mir empfohlener Literatur
    • XML-Namespace
      • Zeigt meinem XML-Namespace
  • Franks aktueller IT-WerkzeugkastenDiese Werkzeuge setze ich zur Zeit ein
  • Meine PräsentationenZeigt Ihnen meine Präsentationen
  • WeblinksMeine Linksammlung
  • BuchtippsEine Liste von mir empfohlener Literatur
  • XML-NamespaceZeigt meinem XML-Namespace
  • Über mich …Die persönlichen Informationen über den Softwarearchitekt Frank Rahn
  • Click to open the search input field Click to open the search input field Suche
  • Menü Menü
SOA, Softwarearchitektur

Spring Boot Webanwendung: Die ersten Schritte (Tutorial)

Spring Boot Webanwendung

In diesem Beitrag zeige ich ein Beispiel mit einer Spring Boot Webanwendung. Diese Webanwendung ist eine einfache und unvollständige Wertpapierverwaltung mit Datenbankzugriffen (JPA) auf Basis von Spring Boot.

Inhaltsverzeichnis [anzeigen]

  • Die Komponenten der Spring Boot Webanwendung
  • Was ist Spring Boot?
  • Wie starte ich?
    • Was ist Spring Initializr?
    • Wie wird ein Spring Boot Projekt mit Maven im Eigenbau erstellt?
    • Die Main Application Class
    • Die Konfigurationsdatei application.properties
  • Wie wird der Datenbankzugriff mit Spring Data JPA auf H2 realisiert?
  • Wie wird die Spring Business Service Facade erstellt?
    • Das Erfassen der Metriken
  • Wie erstelle ich eine Weboberfläche mit Spring Boot?
    • Der embedded Webserver (Apache Tomcat)
    • Wie wird die Template Engine Thymeleaf konfiguriert?
    • Wie funktioniert ein Thymeleaf-Template?
    • Die Masken (Oberfläche, View, UI) und die Steuerung (Controller)
  • Die Literaturempfehlungen für dieses Beispiel
  • Der Quellcode und Download des Beispiels
  • Die Maven Befehle

Die Komponenten der Spring Boot Webanwendung

Bei diesem Beispiel werden die folgenden (Spring-) Komponenten eingesetzt.

  • Spring Boot für die Autokonfiguration und das Self-Containment
  • Spring Data JPA mit Hibernate ORM und der Datenbank H2
    • Weitergehende Informationen zum Thema in meinem Beitrag Spring mit JPA und Hibernate (Tutorial)
  • Spring MVC für die Steuerung der Oberfläche
    • Weitergehende Informationen zum Thema in meinem Beitrag Spring mit einer Webanwendung mit JPA und Validierung (Tutorial)
    • Umsetzung des Architekturstils ROCA-Styles
  • Thymeleaf als HTML5 Template Engine mit dem CSS Framework Bootstrap
    • Die JavaScript Komponenten von Bootstrap basieren auf der JavaScript Bibliothek jQuery
    • Als embedded Webserver wird der Apache Tomcat verwendet
  • Java SE 8 mit Apache Maven und Eclipse IDE

Das Spring Framework wird natürlich als Basis eingesetzt. Das Beispiel wurde zusätzlich mit meinen Erfahrungen aus laufenden Projekten angereichert.

Was ist Spring Boot?

Mit Spring Boot können autonomen (autarke oder selbständig ausführbare) Java Anwendungen (JAR) auf Basis des Spring Ökosystems erstellt werden (Self-contained).

Die erstellten Programme beinhalten alle benötigten Komponenten und Bibliotheken. Der Webserver wird, wie in diesem Beispiel, vorkonfiguriert in die Anwendung integriert (Auto-configuration).

Durch das Verwenden des Paradigmas Konvention vor Konfiguration kommt die Anwendungen ohne XML-Konfiguration aus (JavaConfig).

Gesteuert wird der Zusammenbau der Spring Boot Webanwendung durch das Buildsystem Apache Maven mit einem speziellen Plugin von Spring.

Spring Boot eignet sich auf Grund dieser genannten Eigenschaften hervorragend als Grundlage für Microservices (Martin Fowler) oder Self-contained Systems (SCS).

Durch die genannten Eigenschaften werden folgende Ziele mit von Spring Boot erreicht.

  • Schnelleres Aufsetzen von Spring Projekten durch Vereinfachungen.
  • Out-of-the-box Verhalten durch Autokonfigurationen mit sinnvollen Anfangswerten.
  • Nicht-funktionale Features werden bereitgestellt.

Wie starte ich?

Um eine Spring Boot Webanwendung zu Erstellen bieten sich die folgenden Möglichkeiten an.

  • Der Webservice Spring Initializr.
  • Ein Maven Projekt im Eigenbau.

Was ist Spring Initializr?

Über die bereits erwähnte Weboberfläche bzw. dem Webservice kann ein Spring Boot Projekt komfortabel zusammengestellt und als fertige Projektvorlage heruntergeladen werden. Die Weboberfläche ist auch in der Spring Tool Suite (STS) integriert.

Spring Tool Suite - New Spring Starter Project - Projektinformationen
Spring Tool Suite - New Spring Starter Project - Projektinformationen
Spring Tool Suite - New Spring Starter Project - Spring-Komponenten
Spring Tool Suite - New Spring Starter Project - Spring-Komponenten
Spring Tool Suite - New Spring Starter Project - Der Abschluß
Spring Tool Suite - New Spring Starter Project - Der Abschluß

In der folgenden Bildergalerie wird gezeigt, wie für dieses Beispiel die Weboberfläche genutzt werden könnte.

Spring Initializr - Eine Abhängigkeit auswählen
Spring Initializr - Eine Abhängigkeit auswählen
Spring Initializr - Die Projektinformationen zusammengestellt
Spring Initializr - Die Projektinformationen zusammengestellt
Spring Initializr - Der Download des Projektes
Spring Initializr - Der Download des Projektes

Wie wird ein Spring Boot Projekt mit Maven im Eigenbau erstellt?

Dieses Beispiel einer Spring Boot Webanwendung verwendet eine hierarchische Projektstruktur und ist in meinem Git Repository microservices auf GitHub veröffentlicht.

Die hierarchische Projektstruktur der Wertpapierverwaltung

Die hierarchische Projektstruktur der Wertpapierverwaltung (© Frank Rahn)

In der obersten Maven pom.xml wird die Referenz auf das Parent-POM (Project Object Modell) von Spring Boot spring-boot-starter-parent gesetzt. Durch diese Parent-POM wird auch die POM der Spring Boot Dependencies referenziert. In dieser POM werden alle Abhängigkeiten von Spring Boot verwaltet, die in den einzelnen Spring Modulen verwendet werden können – insbesondere die von Drittherstellern.

Tipp

Die POM spring-boot-dependency kann für Unternehmen als unternehmensweiter Standard für die Nutzung von Fremdbibliotheken bzw. zum Management des Portfolios (BOM: Bill of Material) verwendet werden.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.3.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>

  <groupId>de.rahn</groupId>
  <artifactId>microservices</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>Microservices</name>
  <description>Die Parent-POM für die Microservices auf Basis von Spring Boot.</description>
  <url>https://github.com/frank-rahn/microservices</url>

  <modules>
    <module>securities-management</module>
  </modules>
...

Zusätzlich wird noch die Java Version 8 definiert.

  <properties>
    <!-- Java Version -->
    <java.version>1.8</java.version>

    <!-- APT-Generatoren -->
    <hibernate-jpamodelgen.version>${hibernate.version}</hibernate-jpamodelgen.version>

    <!-- Versione der Plugins -->
    <maven-processor-plugin.version>3.1.0</maven-processor-plugin.version>
    <jacoco-maven-plugin.version>0.7.6.201602180812</jacoco-maven-plugin.version>
    <coveralls-maven-plugin.version>4.1.0</coveralls-maven-plugin.version>
  </properties>

  <organization>
    <name>Frank W. Rahn</name>
    <url>https://www.frank-rahn.de/</url>
  </organization>

  <scm>
    <url>https://github.com/frank-rahn/microservices</url>
    <connection>scm:git:git://github.com/frank-rahn/microservices.git</connection>
    <developerConnection>scm:git:ssh://git@github.com:frank-rahn/microservices.git</developerConnection>
    <tag>master</tag>
  </scm>

  <issueManagement>
    <system>GitHub Issues</system>
    <url>https://github.com/frank-rahn/microservices/issues</url>
  </issueManagement>

  <ciManagement>
    <system>Travis CI</system>
    <url>https://travis-ci.org/frank-rahn/microservicess</url>
  </ciManagement>

  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>https://www.apache.org/licenses/LICENSE-2.0</url>
      <distribution>manual</distribution>
    </license>
  </licenses>

  <developers>
    <developer>
      <name>Frank Rahn</name>
      <email>frank+git at frank-rahn.de</email>
      <organization>Frank W. Rahn</organization>
      <roles>
        <role>Developer</role>
        <role>Contributor</role>
      </roles>
    </developer>
  </developers>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
          <downloadSources>true</downloadSources>
          <!-- Workaround for http://jira.codehaus.org/browse/MECLIPSE-94 -->
          <eclipseProjectDir>.</eclipseProjectDir>
          <additionalProjectnatures>
            <projectnature>org.eclipse.m2e.core.maven2Nature</projectnature>
            <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
          </additionalProjectnatures>
          <additionalBuildcommands>
            <buildCommand>
              <name>org.eclipse.m2e.core.maven2Builder</name>
            </buildCommand>
            <buildCommand>
              <name>org.springframework.ide.eclipse.core.springbuilder</name>
            </buildCommand>
          </additionalBuildcommands>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <executions>
          <execution>
            <id>attach-sources</id>
            <goals>
               <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <version>${maven-processor-plugin.version}</version>
        <dependencies>
          <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>${hibernate-jpamodelgen.version}</version>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco-maven-plugin.version}</version>
        <configuration>
          <excludes>
            <exclude>**/*_.*</exclude>
          </excludes>
        </configuration>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-prepare-agent-integration</id>
            <goals>
              <goal>prepare-agent-integration</goal>
            </goals>
          </execution>
          <execution>
            <id>default-report</id>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
          <execution>
            <id>default-report-integration</id>
            <goals>
              <goal>report-integration</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <profiles>
    <profile>
      <id>travis</id>
      <activation>
        <property>
          <name>env.TRAVIS</name>
          <value>true</value>
        </property>
      </activation>

      <build>
        <plugins>
          <plugin>
            <groupId>org.eluder.coveralls</groupId>
            <artifactId>coveralls-maven-plugin</artifactId>
            <version>${coveralls-maven-plugin.version}</version>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

</project>

Zu Abschluss muss noch das Maven Plugin von Spring Boot für die Erstellung der Spring Boot Webanwendung konfiguriert werden. Dieses wird im Modul securities-management/server-web durchgeführt. In diesem Modul befindet sich der ausführbare Teil der Spring Boot Webanwendung.

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <layout>ZIP</layout>
        </configuration>
      </plugin>
      <plugin>
        <groupId>pl.project13.maven</groupId>
        <artifactId>git-commit-id-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

Dieses waren die wichtigsten Elemente aus der Maven Konfiguration. Die übrigen Einstellungen sind technologie- oder projektspezifisch.

Die Main Application Class

Die Main Application Class ist die Startklasse einer Spring Boot Anwendung, welche die main()-Methode bereitstellt. In diesem Beispiel liegt sie im Modul securities-management/server-web und startet die komplette Spring Boot Webanwendung.

/**
 * Die Startklasse für diesen Server.
 *
 * @author Frank W. Rahn
 */
@SpringBootApplication
public class SecuritiesManagementApplication {

  /**
   * @param args
   */
  public static void main(String[] args) {
    SpringApplication.run(SecuritiesManagementApplication.class, args);
  }

}

Die Konfigurationsdatei application.properties

Diese Konfigurationsdatei befindet sich im Modul securities-management/server-web und enthält einige wichtige Einträge. Elemente die mit @ geklammert sind, werden durch Werte aus den Maven-Properties ersetzt.

# Allgemeine Informationen
spring.application.name = @project.name@
...

Alternativ kann diese Konfigurationsdatei auch im Format YAML (YAML Ain’t Markup Language) angelegt werden.

Wie wird der Datenbankzugriff mit Spring Data JPA auf H2 realisiert?

Der Datenbankzugriff wurde im Modul securities-management/domains ausgelagert. Für die Autokonfiguration des Datenbankzugriffs werden die folgenden Starter und Abhängigkeiten benötigt.

  • spring-boot-starter-data-jpa
    Dieser Starter fügt die Abhängigkeiten für die Komponente Spring Data JPA hinzu und konfiguriert sie. Die Implementierung basiert auf dem O/R-Mapper von Hibernate und dem Java Standard JPA (Java Persistence API).
  • spring-boot-starter-validation
    Dieser Starter stellt die Bean Validierung v1.1 nach dem JSR-303 bzw. JSR-349 zu Verfügung. Dazu wird die Implementierung des Hibernate Validator verwendet.
  • com.h2database:h2
    Diese Abhängigkeit bindet die In-Memory Datenbank H2 in das Projekt ein und konfiguriert die zugehörige DataSource.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.rahn.finances</groupId>
    <artifactId>securities-management</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>..</relativePath>
  </parent>

  <artifactId>domains</artifactId>

  <name>Securities Management Domains</name>
  <description>Die Domänen der Wertpapierverwaltung.</description>

  <dependencies>
    <!-- Spring Starter -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    <!-- Libraries -->
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>process</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/generated-sources/annotations</outputDirectory>
              <processors>
                <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
              </processors>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

Zusätzlich müssen in der application.properties im Modul securities-management/server-web einige Einträge hinzugefügt werden.

# Allgemeine Informationen
spring.application.name = @project.name@

# JPA / Hibernate
spring.jpa.show-sql = true

# Database H2
spring.h2.console.enabled = true
...

Nach dem gleichen Muster, wie in meinem Beitrag Spring mit JPA und Hibernate (Tutorial) beschrieben, werden die JPA Entitäten im Package de.rahn.finances.domains.entities definiert.

Das Domänmodell der Wertpapierverwaltung

Das Domänmodell der Wertpapierverwaltung (© Frank Rahn)

Anders, als im verwiesenen Beitrag, wird anstelle der abstrakten und generischen Datenzugriffsobjekte (DAO) eine Repository gemäß des Domain-Driven Design (*) von Eric J. Evans verwendet, die durch Spring Data JPA umgesetzt wird.

/**
 * Der Zugriff auf die Wertpapiere.
 *
 * @author Frank W. Rahn
 */
public interface SecuritiesRepository extends JpaRepository<Security, String> {

  /**
   * Liefere die {@link Page} der Wertpapiere unter der Berücksichtigung der Filterparameter.
   *
   * @param pageable die Information über die Paginierung
   * @param inventory Filter: <code>true</code>, nur der aktuelle Bestand wird angezeigt
   * @param type Filter: nur die Wertpapiere dieser Art anzeigen
   * @return Eine Seite der Liste aller gefilterten Wertpapiere
   */
  Page<Security> findByInventoryOrType(Pageable pageable, boolean inventory, SecurityType type);

}

Die Deklaration der Datenbankzugriffsschicht erfolgt in der Konfigurationsklasse DomainsConfiguration .

/**
 * Die Spring Configuration für die Domains.
 *
 * @author Frank W. Rahn
 */
@Configuration
@EntityScan(basePackageClasses = { de.rahn.finances.domains.entities.PackageMarker.class })
@EnableJpaRepositories(basePackageClasses = { de.rahn.finances.domains.repositories.PackageMarker.class })
public class DomainsConfiguration {
  // Leer
}

Wie wird die Spring Business Service Facade erstellt?

Die Business Logik wurde im Modul securities-management/services ausgelagert. Für die Autokonfiguration des Business Services werden die folgenden Starter und Abhängigkeiten benötigt.

  • spring-boot-starter-actuator
    Dieser Starter stellt die Funktionen für das Management und Monitoring der Spring Boot Webanwendungen zu Verfügung. Auf diese Funktionen kann per HTTP REST-Schnittstelle (Beispiel: http://localhost:8000/manage/health), per Java Management Extensions (JMX) oder über eine remote Shell (SSH oder Telnet) zugegriffen werden. Dazu werden allerdings weitere Starter benötigt.
    Dieser Starter ist für das Erfassen der Metriken des Services der Wertpapierverwaltung erforderlich (Siehe auch im Kapitel über Das Erfassen der Metriken).
  • spring-web
    Diese Abhängigkeit wird benötigt, damit die Ausnahmen SecurityNotFoundException des Services mit der Annotation ResponseStatus versehen werden kann. Dadurch kann später in der Oberfläche der HTTP-Statuscode 404 gesendet werden, falls ein Wertpapier in der Datenbank nicht gefunden wird.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.rahn.finances</groupId>
    <artifactId>securities-management</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>..</relativePath>
  </parent>

  <artifactId>services</artifactId>

  <name>Securities Management Services</name>
  <description>Die Services der Wertpapierverwaltung.</description>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
    </dependency>

    <dependency>
      <groupId>de.rahn.finances</groupId>
      <artifactId>domains</artifactId>
    </dependency>
  </dependencies>

</project>

Zusätzlich werden in der application.properties im Modul securities-management/server-web folgende Einträge hinzugefügt.

# JSON Formatieren
spring.jackson.serialization.indent-output = true

# Actuator
management.address = 127.0.0.1
management.context-path  = /manage

# Actuator /info
info.application.name = @project.name@
info.application.groupId = @project.groupId@
info.application.artifactId = @project.artifactId@
info.application.version = @project.version@
info.application.description = @project.description@

# Actuator /shutdown
endpoints.shutdown.enabled = true

# Actuator /health
endpoints.health.sensitive = false

# Actuator /env, /configprops, /autoconfig
endpoints.env.keys-to-sanitize = password,secret,key,passwort

Der Service der Wertpapierverwaltung wird, nach dem gleichen Muster wie in meinem Beitrag Spring an einem einfachem Beispiel (Tutorial) beschrieben, erstellt. Ein Unterschied besteht nur in der Konfiguration. Im Beitrag wird die Spring-XML-Konfiguration verwendet. Für die Spring Boot Webanwendung wurde jedoch die JavaConfig gewählt.

Das Servicemodell der Wertpapierverwaltung

Das Servicemodell der Wertpapierverwaltung (© Frank Rahn)

Die Deklaration des Services erfolgt in der Konfigurationsklasse ServicesConfiguration per @ComponentScan.

/**
 * Die Spring Configuration für die Services.
 *
 * @author Frank W. Rahn
 */
@Configuration
@ComponentScan(basePackageClasses = { de.rahn.finances.services.securities.PackageMarker.class })
public class ServicesConfiguration {
  // Leer
}

Das Erfassen der Metriken

Das Erfassen der Metriken wurde im Aspekt SecuritiesServiceMetricsAspect definiert. Der Aspekt erfasst die Daten und leitet sie an den Metrikenservice von Spring Boot Actuator weiter.

Weitere Informationen dazu siehe:

  • Typen von Metriken: Counter, Meter, Timer, Gauge und Histogram bei Dropwizard Metrics von Coda Hale
  • Namenskonventionen von Metriken bei Matt Aimonetti
/**
 * Ein Aspekt für die Metriken des {@link SecuritiesService}.
 *
 * @author Frank W. Rahn
 */
@Component
@Aspect
public class SecuritiesServiceMetricsAspect {

  /** Der Prefix für die Aufrufzähler. */
  public static final String PREFIX_METRICNAME_CALLS = "counter.securities.services.securities.invoked";

  /** Der Prefix für die Aufrufzähler. */
  public static final String PREFIX_METRICNAME_CALL = "counter.securities.services.securities.invoke.";

  /** Der Prefix für die Aufrufrate. */
  public static final String PREFIX_METRICNAME_EVENTS = "meter.securities.services.securities.used";

  /** Der Prefix für die Aufrufrate. */
  public static final String PREFIX_METRICNAME_TIMER = "timer.securities.services.securities.getsecurities.executed";

  /** Der Prefix für die Fehlerzähler. */
  public static final String PREFIX_METRICNAME_ERRORS = "counter.securities.services.securities.failed";

  /** Der Prefix für die Fehlerzähler. */
  public static final String PREFIX_METRICNAME_ERROR = "counter.securities.services.securities.failure.";

  /** Spring Boot Service für Counter und Meter. */
  @Autowired
  private CounterService counterService;

  /** Spring Boot Service für Guage, Timer und Histogram. */
  @Autowired
  private GaugeService gaugeService;

  /**
   * Für den Zugriff auf die Schnittstelle.
   */
  @Pointcut("this(de.rahn.finances.services.SecuritiesService)")
  private void onSecuritiesService() {
  }

  /**
   * Zähle die erfolgreichen lesenden Zugriffe.
   */
  @AfterReturning(pointcut = "execution(* de.rahn.finances.services.SecuritiesService.get*(..))")
  public void afterCallingSecuritiesServiceRead() {
    counterService.increment(PREFIX_METRICNAME_EVENTS);
    counterService.increment(PREFIX_METRICNAME_CALLS);
    counterService.increment(PREFIX_METRICNAME_CALL + "read");
  }

  /**
   * Zähle die erfolgreichen verändernden Zugriffe.
   */
  @AfterReturning(
    pointcut = "execution(* de.rahn.finances.services.SecuritiesService.save(..)) || execution(* de.rahn.finances.services.SecuritiesService.delete(..))")
  public void afterCallingSecuritiesServiceModified() {
    counterService.increment(PREFIX_METRICNAME_EVENTS);
    counterService.increment(PREFIX_METRICNAME_CALLS);
    counterService.increment(PREFIX_METRICNAME_CALL + "modified");
  }

  /**
   * Zähle alle geworfenen Ausnahmen.
   */
  @AfterThrowing(pointcut = "onSecuritiesService()", throwing = "exception")
  public void afterThrowsException(Exception exception) {
    counterService.increment(PREFIX_METRICNAME_ERRORS);
    counterService.increment(PREFIX_METRICNAME_ERROR + exception.getClass().getSimpleName().toLowerCase());
  }

  @Around("execution(org.springframework.data.domain.Page de.rahn.finances.services.SecuritiesService.getSecurities(org.springframework.data.domain.Pageable))")
  public Object doGetSecuritiesTimer(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = currentTimeMillis();

    Object returnValue = joinPoint.proceed();

    gaugeService.submit(PREFIX_METRICNAME_TIMER, currentTimeMillis() - start);

    return returnValue;
  }

}

Wie erstelle ich eine Weboberfläche mit Spring Boot?

In diesem Beispiel soll eine Weboberfläche auf der Basis von HTML5 mit dem CSS Framework Bootstrap von Twitter erstellt und zusätzlich die JavaScript Bibliothek jQuery verwendet werden. Die Oberfläche befindet sich, mit der eigentlichen Spring Boot Webanwendung, im Modul securities-management/server-web.

In dieser Bildergalerie werden die Masken dieses Beispiels gezeigt.

Die Startseite der Wertpapierverwaltung
Die Startseite der Wertpapierverwaltung
Die Liste aller Wertpapiere
Die Liste aller Wertpapiere
Die zweite Seite der Liste aller Wertpapiere
Die zweite Seite der Liste aller Wertpapiere
Ein Wertpapier bearbeiten
Ein Wertpapier bearbeiten
Die Management-API der Wertpapierverwaltung
Die Management-API der Wertpapierverwaltung
Der Status der Anwendung - Health Check
Der Status der Anwendung - Health Check

Der embedded Webserver (Apache Tomcat)

Für eine Spring Boot Webanwendung wird ein Webserver benötigt, der die HTML Seiten ausliefert. Bei Spring Boot wird dieses mit einem embedded Webserver durchgeführt. Dazu wird der Spring Boot Starter spring-boot-starter-web benötigt, der die komplette Laufzeitumgebung mit dem Apachen Tomcat bereitstellt. Einen Deployment Descriptor web.xml muss nicht erstellt werden. Zusätzlich werden in der application.properties im Modul securities-management/server-web folgende Einträge definiert.

In Zeile 11 wird beispielsweise der Standard-Port des Servers überschrieben.

# Allgemeine Informationen
spring.application.name = @project.name@

# JPA / Hibernate
spring.jpa.show-sql = true

# Database H2
spring.h2.console.enabled = true

# Tomcat
server.port = 8000
server.tomcat.accesslog.enabled = true
server.tomcat.accesslog.pattern = %h %t "%r" %s %b
...

Wie wird die Template Engine Thymeleaf konfiguriert?

Für die Autokonfiguration der Template Engine, in diesem Beispiel wird Thymeleaf verwendet, muss der Spring Boot Starter spring-boot-starter-thymeleaf verwendet werden. Da eine Abhängigkeit zum Starter spring-boot-starter-web besteht, kann dieser entfernt werden.

  <artifactId>server-web</artifactId>

  <name>Securities Management Server Web</name>
  <description>Der Webserver der Wertpapierverwaltung.</description>

  <dependencies>
    <dependency>
      <groupId>de.rahn.finances</groupId>
      <artifactId>commons</artifactId>
    </dependency>
    <dependency>
      <groupId>de.rahn.finances</groupId>
      <artifactId>services</artifactId>
    </dependency>

    <!-- Spring Starter -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <layout>ZIP</layout>
        </configuration>
      </plugin>
      <plugin>
        <groupId>pl.project13.maven</groupId>
        <artifactId>git-commit-id-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

In der application.properties wird das Zwischenspeichern der generierten Seiten abgeschaltet. Dieses sollte aber nur in der Entwicklungsumgebung geschehen, damit geänderte Webseiten direkt begutachtet werden können. In Produktionssystemen ist das Zwischenspeichern wieder einzuschalten.

# Allgemeine Informationen
spring.application.name = @project.name@

# JPA / Hibernate
spring.jpa.show-sql = true

# Database H2
spring.h2.console.enabled = true

# Tomcat
server.port = 8000
server.tomcat.accesslog.enabled = true
server.tomcat.accesslog.pattern = %h %t "%r" %s %b

# Thymeleaf
spring.thymeleaf.cache = false
...

Wie funktioniert ein Thymeleaf-Template?

Ein Template unter Thymeleaf ist eine valide HTML-Datei, die um den XML Namesraums von Thymeleaf erweitert wurde. Die Engine von Thymeleaf hält im Speicher für jedes Template einen DOM-Tree vor. Dieser DOM-Tree wird an den markierten Stellen mit dynamischen Inhalten angereichert.

<!DOCTYPE html>
<html
  xmlns:th="http://www.thymeleaf.org"
  xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"
>
<head>
  <meta charset="utf-8" />
  <title>Home</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" />
  <link rel="stylesheet" href="../static/css/style.css" th:href="@{/css/style.css}" />
</head>
<body>
  <div class="container">
    <h1 layout:fragment="header">Wertpapierverwaltung</h1>
    <div layout:fragment="content">
      <section>
        <h2>Wertpapierverwaltung</h2>
        <p><a href="securities.html" th:href="@{/securities}">Liste aller Wertpapiere</a></p>
      </section>
      <section>
        <h2>Management</h2>
        <p><a href="info.html" th:href="@{/info}">Management API</a></p>
      </section>
    </div>
  </div>
</body>
</html>

Thymeleaf unterstützt dabei eine Technik, die natural templating genannt wird. Wird ein Template direkt in den Browser geladen, so ignoriert der Browser den zusätzlichen XML Namesraum mit den Kontrollstrukturen und stellt die Webseite dar. Ein- und Ausgabefelder können im Template mit beispielhaften Werten belegt werden. Diese werden zur Laufzeit durch die dynamischen Inhalte ersetzt. Durch diese Technik ist es möglich, die Oberfläche der Spring Boot Webanwendung in Form eines klickbaren Prototypen zu erstellen. Die Webseiten können direkt im Browser angesehen werden.

Die Bildergalerie des klickbaren Prototypen für dieses Beispiel wird direkt nach dem Template security.html gezeigt.

<!DOCTYPE html>
<html
  xmlns:th="http://www.thymeleaf.org"
  xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"
>
<head>
  <meta charset="utf-8" />
  <title>Wertpapier</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" />
  <link rel="stylesheet" href="../static/css/style.css" th:href="@{/css/style.css}" />
</head>
<body>
  <div class="container">
    <h1 layout:fragment="header">Wertpapier</h1>
    <div layout:fragment="content">
      <section class="panel panel-default">
        <div class="panel-heading">
          <h2 class="panel-title">Wertpapier</h2>
        </div>
        <div class="panel-body">
          <form id="security" th:object="${security}" th:action="@{/security}" action="#" method="post" role="form">
            <div th:if="${#fields.hasErrors('${security}')}" class="alert alert-danger" role="alert">
              <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><p th:errors="${security}">Allgemeiner Fehler</p>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('id')}? 'has-error has-feedback'">
              <label for="id" class="control-label">ID:</label>
              <input type="text" class="form-control" th:field="*{id}" value="8ad72f6f-2a39-4846-8940-f6139f3d5597" readonly="readonly"/><span th:if="${#fields.hasErrors('id')}" class="glyphicon glyphicon-remove form-control-feedback"></span>
              <div th:if="${#fields.hasErrors('id')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{id}">Fehler in der ID</span></div>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('isin')}? 'has-error has-feedback'">
              <label for="isin" class="control-label">ISIN:</label>
              <input type="text" class="form-control" th:field="*{isin}" value="DE0001234560" /><span th:if="${#fields.hasErrors('isin')}" class="glyphicon glyphicon-remove form-control-feedback"></span>
              <div th:if="${#fields.hasErrors('isin')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{isin}">Fehler in der ISIN</span></div>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('wkn')}? 'has-error has-feedback'">
              <label for="wkn" class="control-label">Wertpapier-Kennnummer:</label>
              <input type="text" class="form-control" th:field="*{wkn}" value="123456" /><span th:if="${#fields.hasErrors('wkn')}" class="glyphicon glyphicon-remove form-control-feedback"></span>
              <div th:if="${#fields.hasErrors('wkn')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{wkn}">Fehler in der Wertpapier-Kennnummer</span></div>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('name')}? 'has-error has-feedback'">
              <label for="name" class="control-label">Name des Wertpapiers:</label>
              <input type="text" class="form-control" th:field="*{name}" value="Firma A AG" /><span th:if="${#fields.hasErrors('name')}" class="glyphicon glyphicon-remove form-control-feedback"></span>
              <div th:if="${#fields.hasErrors('name')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{name}">Fehler im Name</span></div>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('symbol')}? 'has-error has-feedback'">
              <label for="symbol" class="control-label">Symbol des Wertpapiers:</label>
              <input type="text" class="form-control" th:field="*{symbol}" value="A01" /><span th:if="${#fields.hasErrors('symbol')}" class="glyphicon glyphicon-remove form-control-feedback"></span>
              <div th:if="${#fields.hasErrors('symbol')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{symbol}">Fehler im Symbol</span></div>
            </div>
            <div class="form-group" th:classappend="${#fields.hasErrors('type')}? 'has-error has-feedback'">
              <label for="type" class="control-label">Wertpapierart:</label>
              <select class="form-control" th:field="*{type}">
                <option value="stock" th:each="e: ${securityTypeList}" th:value="${e.key}" th:text="${e.value}">Aktie</option>
              </select>
              <div th:if="${#fields.hasErrors('type')}" class="alert alert-danger" role="alert"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a> <span th:errors="*{type}">Fehler in der Wertpapierart</span></div>
            </div>
            <div class="text-center">
              <a class="btn btn-default" href="securities.html" th:href="@{/securities}">Abbrechen</a>
              <button type="submit" class="btn btn-danger">Speichern</button>
            </div>
          </form>
        </div>
      </section>
    </div>
  </div>
</body>
</html>
Prototyp: Die Startseite der Wertpapierverwaltung
Prototyp: Die Startseite der Wertpapierverwaltung
Thymeleaf-Prototyp: Die Liste aller Wertpapiere
Thymeleaf-Prototyp: Die Liste aller Wertpapiere
Thymeleaf-Prototyp: Ein Wertpapier bearbeiten oder anlegen
Thymeleaf-Prototyp: Ein Wertpapier bearbeiten oder anlegen
Thymeleaf-Prototyp: Die Management-API der Wertpapierverwaltung
Thymeleaf-Prototyp: Die Management-API der Wertpapierverwaltung

Die Masken (Oberfläche, View, UI) und die Steuerung (Controller)

Durch die vollständig Integration von Thymeleaf in Spring MVC, werden die Controller, wie bei Spring gewohnt, implementiert (Siehe Beitrag Spring mit einer Webanwendung mit JPA und Validierung). Bei der Entwicklung wurde der Architekturstil ROCA-Styles berücksichtigt. Dieser Architekturstil besteht aus einer Sammlung von Empfehlungen zur Entkopplung von Server und Client. Diese Empfehlungen basieren auf den REST-Prinzipien für den Server und dem Prinzip von Progressive Enhancement für den Client.

Weitergehende Informationen zum Thema in meinem Beitrag Spring mit einer Webanwendung mit JPA und Validierung (Tutorial).

Die Literaturempfehlungen für dieses Beispiel

  • Spring Boot Documentation
  • Using Thymeleaf
  • Microservices: Grundlagen flexibler Softwarearchitekturen (*)
  • Microservices: Konzeption und Design (*)
  • Domain-Driven Design (*)

Der Quellcode und Download des Beispiels

Quellcode ansehen bei GitHub:
microservices

Download einer ZIP-Datei von GitHub:
microservices

Die Maven Befehle

Eclipse Konfiguration neu erzeugen: $ mvn eclipse:clean eclipse:eclipse

Anwendung bauen: $ mvn clean package

Anwendung ausführen:

$ cd securities-management/server-web 
$ mvn spring-boot:run
  • Über
  • Letzte Artikel
Frank Rahn
Frank Rahn
Frank Rahn ist Softwarearchitekt. Er unterstützt bei der Konzeption von Softwarearchitekturen mit Java-Technologie. Folge Sie ihm auf Facebook oder Twitter.

Benötigen Sie Unterstützung? Kontaktieren Sie ihn.

Hat Ihnen dieser Beitrag gefallen? Wir würden uns über Ihren Kommentar freuen! Bitte verwenden Sie Ihren bürgerlichen Namen.
Frank Rahn
Letzte Artikel von Frank Rahn (Alle anzeigen)
  • Wer ist der optimale Java Bean Mapper? - Freitag, 22. September 2023
  • Spring Boot Webanwendung: Die ersten Schritte (Tutorial) - Montag, 28. März 2016
  • Mainframe-Zugriff via Java - Sonntag, 04. Mai 2014
3 Kommentare/von Frank Rahn
Schlagworte: Annotations, AOP, Architektur, CSS, HTML, Java, Java SE, JavaScript, JPA, Microservices, MVC, ROCA, Self-contained Systems, Spring
Eintrag teilen
  • Teilen auf X
  • Teilen auf WhatsApp
  • Teilen auf LinkedIn
  • Per E-Mail teilen
  • Teilen auf Xing
https://www.frank-rahn.de/wp-content/uploads/spring-boot-webanwendung.jpg 1280 1734 Frank Rahn /wp-content/uploads/logo.png Frank Rahn2016-03-28 16:29:202025-10-01 17:48:37Spring Boot Webanwendung: Die ersten Schritte (Tutorial)
Das könnte Dich auch interessieren
AJAX - Asynchronous Javascript and XML AJAX: Mühelos einsetzen (Asynchronous Javascript and XML)
Das Schaubild eines RESTful Webservices RESTful-Webservices (REST-API-Design)
2 Klicks für mehr Datenschutz Social Share Privacy (2-Klick-Buttons für mehr Datenschutz)
Die REST-API des Webservice der Fahrerverwaltung Spring mit RESTful Webservice (Tutortial)
Die ApplicationContexte einer einfachen Spring Webanwendung Spring mit einer einfachen Webanwendung (Tutorial)
Die Stored Procedure "searchPersons" mit User-defined Types (UDT) Spring und Stored Procedure mit User-defined Types (Tutorial)
3 Kommentare
  1. Marcus E.
    Marcus E. sagte:
    Dienstag, 18. April 2017 um 14:26 Uhr

    Herzlichen Dank für die ganzen Informationen auf Ihrer Seite. Ich lese mich gerade zum Thema Spring & Java ein und finde mich hier sehr gut zurecht.

    Antworten
    • Frank Rahn
      Frank Rahn sagte:
      Dienstag, 18. April 2017 um 22:27 Uhr

      Vielen Dank und viel Spaß mit Spring und Java.

      Viele Grüße
      Frank Rahn

      Antworten
  2. Credo Systemz
    Credo Systemz sagte:
    Sonntag, 05. März 2017 um 6:15 Uhr

    awesome blog.. really helpful for all i got more clear ideas from this blog

    Antworten

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Ihre E-Mail-Adresse wird nicht veröffentlicht. Ihr Kommentar wird verschlüsselt an meinen Server gesendet. Erforderliche Felder sind mit * markiert.

Weitere Informationen und Widerrufshinweise finden Sie in meiner Datenschutzerklärung.

Wollen Sie kein neuen Beiträge mehr verpassen?
Dann abonnieren Sie bitte meinen Newsletter.
Meinen Newsletter abonnieren

Themen

  • Wer ist der optimale Java Bean Mapper?
  • Einführung in das Spring Framework, Boot, Batch, Data, REST, Security, Web, …
  • Franks aktueller IT-Werkzeugkasten
  • Git, GitHub, EGit, …

Navigation

  • Buchtipps
  • Newsletter
  • Weblinks
Search Search

Werbung

  • JProfiler
Beliebt
  • Das Klassendiagramm für den Java Bean Mapper Test am Beispiel "ByHand"
    Wer ist der optimale Java Bean Mapper?Freitag, 22. September 2023 - 20:59 Uhr
  • Das offizielle Logo von EGit
    GitHub mit Eclipse (EGit)Freitag, 26. Oktober 2012 - 16:15 Uhr
  • Grobe Übersicht üder den Spring Framework Container
    Einführung in das Spring FrameworkSonntag, 01. Mai 2011 - 18:30 Uhr
  • Die Stored Procedure "searchPersons" mit User-defined Types (UDT)
    Spring und Stored Procedure mit User-defined Types (Tut...Freitag, 26. Oktober 2012 - 21:45 Uhr
  • Spring Boot Webanwendung
    Spring Boot Webanwendung: Die ersten Schritte (Tutorial...Montag, 28. März 2016 - 16:29 Uhr
Schlagworte
Annotations AOP Architektur Autorisierung Cookies CRUD DAO DI Git HTML HTTP IoC Java Java EE Java SE JPA JSR Linux MVC Open Source Software PDF POJO REST (RESTful) ROCA Self-contained Systems Serviceorientierte Shell Sicherheit (Security) SOAP Spring SQL SVN Test Toolchain URI URL URN User-defined Type Versionsverwaltung VPN Webservice WS-* WSDL XML XML-Schema

Blogarchiv

Links

Mastodon
Twitter
LinkedIn
Xing
GitHub

Lizenz

Creative Commons Lizenzvertrag Die Texte (nicht Bilder) von Frank Rahn stehen unter einer Creative Commons Namensnennung - Keine Bearbeitungen 4.0 Deutschland Lizenz.

Affiliate-Links

Die mit (*) gekennzeichnete Links sind sogenannte Affiliate-Links. Kommt über einen solchen Link ein Einkauf zustande, werde ich mit einer Provision beteiligt. Für Sie entstehen dabei keine Mehrkosten. Wo, wann und wie Sie ein Produkt kaufen, bleibt natürlich Ihnen überlassen.

Blogkategorien

Copyright © Frank W. Rahn
  • Impressum / HaftungsausschlussDie notwendigen gesetzlichen Angaben dieser Webseite von Frank Rahn
  • DatenschutzerklärungDie Datenschutzerklärung von Frank Rahn
  • NewsletterKeine neuen Beiträge mehr verpassen!
  • BildnachweisDer komplette Bildnachweis von Frank Rahn
Link to: Mainframe-Zugriff via Java Link to: Mainframe-Zugriff via Java Mainframe-Zugriff via JavaLegStar modules for z/OS Link to: Wer ist der optimale Java Bean Mapper? Link to: Wer ist der optimale Java Bean Mapper? Das Klassendiagramm für den Java Bean Mapper Test am Beispiel "ByHand"Wer ist der optimale Java Bean Mapper?
Nach oben scrollen Nach oben scrollen Nach oben scrollen

Wir setzen auf unserer Webseite verschiedene Arten von Cookies ein, die auf Ihrem Gerät gespeichert werden. Einige dieser Cookies sind für die einwandfreie Funktion der Webseite notwendig, während andere Cookies Ihnen ein besseres Besuchererlebnis bieten.

DatenschutzerklärungImpressumAlle Cookies akzeptierenKeine Cookies akzeptierenIndividuelle Cookie-Einstellungen vornehmen

Cookie- und Datenschutzeinstellungen



Wie wir Cookies verwenden

Wir setzen auf unserer Webseite verschiedene Arten von Cookies ein, die auf Ihrem Gerät gespeichert werden.

Einige dieser Cookies sind für die einwandfreie Funktion der Webseite notwendig, während andere Cookies Ihnen ein besseres Besuchererlebnis bieten.

Klicken Sie links auf die verschiedenen Reitern, um mehr zu erfahren. Sie können auch einige Cookie-Einstellungen individuell anpassen. Beachten Sie, dass das Blockieren einiger Cookies die einwandfreie Funktion unserer Webseite beeinträchtigt.

Technisch notwendige Cookies

Diese Cookies sind unbedingt erforderlich, denn sie ermöglichen grundlegende Funktionen und sind für die einwandfreie Funktion der Webseite erforderlich.

Sie können diese Cookies jederzeit blockieren oder löschen, indem Sie Ihre Browsereinstellungen ändern und die Blockierung aller Cookies auf dieser Webseite erzwingen. Leider werden Sie dann immer wieder gefragt, ob Sie Cookies akzeptieren oder ablehnen wollen, wenn Sie unsere Webseite erneut besuchen.

Wir setzen die Cookies aviaPrivacyEssentialCookiesEnabled, aviaPrivacyMustOptInSetting, aviaPrivacyRefuseCookiesHideBar und aviaCookieConsent ein, um Ihre individuellen Cookie-Einstellungen zu speichern. Diese Informationen geben wir an keinen Drittanbietern weiter.

Diese Cookies haben eine Laufzeit von einem Jahr, dann müssen Sie die Einstellungen wiederholen.

Die VG WORT setzt das Sitzungscookie srp zur Messung von Zugriffen auf Texten, um die Kopierwahrscheinlichkeit des Textes zu erfassen. Damit partizipieren ich an den Ausschüttungen der VG WORT, welche die gesetzliche Vergütung für die Nutzungen urheberrechtlich geschützter Werke gemäß § 53 UrhG sicherstellen. Das Cookie wird dazu verwendet, um den Nutzer zu identifizieren und ggf. Daten mehrerer Aufrufe von Texten miteinander verknüpfen zu können.

Nach Angaben der VG WORT stellt das eingesetzte Verfahren sicher, dass einzelne Nutzer oder ihr Leseverhalten nicht ermittelbar sind, wenn die Anzahl der Textaufrufe gezählt wird. Alle von der VG Wort erfassten Daten werden sofort sicher verschlüsselt. Der Einsatz des Zählpixels wurde durch das Bayerische Landesamt für Datenschutzaufsicht begutachtet und als datenschutzkonform bewertet.

Datenschutzerklärung der VG WORT

Marketing-Cookies

Die Marketing-Cookies werden von Drittanbietern oder Publishern, wie z. B. Google Analytics, verwendet, um personalisierte Werbung anzuzeigen. Sie tun dies, indem sie Besucher über Webseiten hinweg verfolgen (Tracking).

Wir setzen keine Marketing-Cookies ein.

Datenschutzbestimmungen

Sie können unsere Cookies und Datenschutzeinstellungen im Detail in unserer Datenschutzerklärung nachlesen.

Cookie-Einstellungen übernehmenKeine Cookies akzeptieren
Nachrichtenleiste öffnen Nachrichtenleiste öffnen Nachrichtenleiste öffnen