tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
0
ZUGRIFFE
1291
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo,

    hier mal ein kleines Beispiel für modulare Webanwendungen mit JEE6 Web Profile und web-fragments.
    web-fragments sind eine Erweiterung im Java EE 6 Web Profile, die es ermöglichen Web-Anwendungen aus einzelnen Teilen (wie etwa Servlet-, Filter- Definitionen, Ressourcen (Bilder, jsp, js, css, html) zusammensetzen zu können.
    Eine gute Übersicht bietet beispielsweise 2).

    Dieses Konzept möchte ich nun mit diesem Artikel vorstellen.

    Dazu skizziere ich eine kleine Webanwendung, welche aus 3 Modulen (module1, module2,module3)
    und einem Untermodul (module3.sub1) besteht. Das komplette Beispiel-Setting findet man im Anhang

    Für das Beispiel verwende ich die Spring Source Tool Suite (STS) 2.5.2, maven 2.2.x, Java EE 6 Web Profile
    und Tomcat 7.0.8

    Um die Konfiguration zu vereinfachen legen wir uns ein Maven Projekt mit dem Namen de.tutorials.build
    und packaging pom an. Dieses Projekt dient als parent-Projekt für alle weiteren Projekte.

    pom.xml (de.tutorials.build)
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    <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>
        <groupId>de.tutorials</groupId>
        <artifactId>de.tutorials.build</artifactId>
        <version>3.0.0-SNAPSHOT</version>
        <packaging>pom</packaging>
     
        <dependencies>
            <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-web-api</artifactId>
                <version>6.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
     
        <repositories>
            <repository>
                <id>java.net2</id>
                <name>Repository hosting the jee6 artifacts</name>
                <url>http://download.java.net/maven/2</url>
            </repository>
        </repositories>
    </project>

    Anstatt die Abhängigkeiten zum Servlet API 3.0 etc. manuell zu definieren geben wir hier einfach
    das javaee-web-api als dependency an.


    Anschließend legen wir mit Maven eine web-app (de.tutorials.web.app) an.

    Diese web-app ist unsere Basis Anwendungen die wir mit Modulen ausbauen werden.

    pom.xml (de.tutorials.web.app)
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>de.tutorials</groupId>
        <artifactId>de.tutorials.web.app</artifactId>
        <packaging>war</packaging>
        <version>3.0.0-SNAPSHOT</version>
        <name>de.tutorials.web.app</name>
        <url>http://maven.apache.org</url>
     
        <parent>
            <groupId>de.tutorials</groupId>
            <artifactId>de.tutorials.build</artifactId>
            <version>3.0.0-SNAPSHOT</version>
            <relativePath>../de.tutorials.build</relativePath>
        </parent>
     
        <dependencies>
     
             
        </dependencies>
        <build>
            <finalName>de.tutorials.web.app</finalName>
        </build>
    </project>
    Wie man sieht wird das parent-Projekt über einen relativen Pfad referenziert... am besten legt
    man die Web App mit dem m2eclipse Plugin erstmal ohne die Angabe eines Parent-Projektes an und
    fügt die Angabe dann später von Hand im pom.xml hinzu.


    Die web.xml unseres web-app Projektes definieren wir so:

    web.xml (de.tutorials.web.app)
    Code xml:
    1
    2
    3
    4
    5
    6
    
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
          version="3.0" metadata-complete="false">
      <display-name>de.tutorials.web.app</display-name>
    </web-app>

    Durch das "metadata-complete" Attribute können wir definieren, ob wir eine erweiterbare web-app definieren oder nicht.
    Mit metadata-complete=false kennzeichnen wir die web-app als erweiterbar.

    In der web-app definieren wir unter src/main/webapp folgende index.jsp:
    HTML-Code:
    <%@page import="de.tutorials.web.app.modules.ModuleLister"%>
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    	pageEncoding="ISO-8859-1"%>
    <!DOCTYPE html>
    <html>
    <body>
    <h1>Modules</h1>
    
    <ul>
    <%for (String moduleId : ModuleLister.getModules(getServletContext())){%>
    	<li><a href="<%=moduleId%>.jsp"><%=moduleId%></a></li>
    <%}%>
    </ul>
    
    </body>
    </html>
    Hier listen wir unsere Fragmente bzw. "module" auf.
    Das Auflisten der web-fragments führen wir mit der Klasse ModuleLister durch:

    ModuleLister:
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    package de.tutorials.web.app.modules;
     
    import java.net.URL;
    import java.util.Collections;
    import java.util.Set;
    import java.util.TreeSet;
     
    import javax.servlet.ServletContext;
    import javax.xml.parsers.DocumentBuilderFactory;
     
    import org.w3c.dom.Document;
     
    public class ModuleLister {
        public static Set<String> getModules(ServletContext sc) throws Exception {
            Set<String> set = new TreeSet<String>();
            for (URL webFragmentUrl : Collections.list(sc.getClassLoader().getResources("META-INF/web-fragment.xml"))) {
                String fragmentId = extractFragmentId(webFragmentUrl);
                set.add(fragmentId);
            }
            return set;
        }
     
        private static String extractFragmentId(URL webFragmentUrl)
                throws Exception {
            Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(webFragmentUrl.toURI().toString());
            String fragmentId = d.getDocumentElement().getAttribute("id");
            return fragmentId;
        }
    }

    Da nun unsere Infrastruktur steht fügen wir nun ein paar Module hinzu.
    Dazu erstellen wir 4 Maven Java Projekte (simple-project) mit bei diesen
    Projekten stellen wir jeweils die Execution Environment (Java Build Path -> Libraries -> JRE -> Edit)
    auf JSE 1.6

    pom.xml de.tutorials.app.module1:
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    <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>
      <groupId>de.tutorials</groupId>
      <artifactId>de.tutorials.app.module1</artifactId>
      <version>3.0.0-SNAPSHOT</version>
        <parent>
            <groupId>de.tutorials</groupId>
            <artifactId>de.tutorials.build</artifactId>
            <version>3.0.0-SNAPSHOT</version>
            <relativePath>../de.tutorials.build</relativePath>
        </parent>
    </project>

    Die Projekte in den Modul Projekten legen wir im Verzeichnis src/main/resources ein Verzeichnis META-INF an.
    In META-INF legen wir eine Datei namens web-fragment.xml mit folgendem Inhalt an:

    web-fragment.xml (de.tutorials.app.module1)
    Code xml:
    1
    2
    3
    4
    5
    6
    
    <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
          version="3.0"
          id="module1">
    </web-fragment>
    Damit deklarieren wir das Projekt als Web-Fragment Projekt mit der Id "module1",.
    Danach legen wir unter META-INF ein Verzeichnis mit dem Namen resources an.

    Dort legen wir die Datei module1.jsp mit folgendem Inhalt an:

    module1.jsp (de.tutorials.app.module1)
    HTML-Code:
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    	pageEncoding="ISO-8859-1"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Module 1</title>
    </head>
    <body>
    Module 1
    </body>
    </html>
    Wenn wir nun in unserer Web-App das module1 verwenden möchten, so definieren wir in der pom.xml (de.tutorials.web.app)
    im Abschnitt dependencies die Abhängigkeit zu unserem module1-Projekt:

    pom.xml (de.tutorials.web.app mit modul1)
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>de.tutorials</groupId>
        <artifactId>de.tutorials.web.app</artifactId>
        <packaging>war</packaging>
        <version>3.0.0-SNAPSHOT</version>
        <name>de.tutorials.web.app</name>
        <url>http://maven.apache.org</url>
     
        <parent>
            <groupId>de.tutorials</groupId>
            <artifactId>de.tutorials.build</artifactId>
            <version>3.0.0-SNAPSHOT</version>
            <relativePath>../de.tutorials.build</relativePath>
        </parent>
     
        <dependencies>
     
            <dependency>
                <groupId>de.tutorials</groupId>
                <artifactId>de.tutorials.app.module1</artifactId>
                <version>3.0.0-SNAPSHOT</version>
            </dependency>
     
        </dependencies>
        <build>
            <finalName>de.tutorials.web.app</finalName>
        </build>
    </project>

    Startet man nun die web-app mit Tomcat und ruft die index.jsp Seite auf so sieht man dass unter Modules
    unser module1 erscheint.

    Definiert man die restlichen Module so erhält man am Ende folgende Ausgabe der index.jsp:
    HTML-Code:
    <!DOCTYPE html>
    <html>
    <body>
    <h1>Modules</h1>
    <ul>
    	<li><a href="module1.jsp">module1</a></li>
    	<li><a href="module2.jsp">module2</a></li>
    	<li><a href="module3.jsp">module3</a></li>
    	<li><a href="module3.sub1.jsp">module3.sub1</a></li>
    </ul>
    </body>
    </html>
    Der web-fragments Mechanismus ist sehr flexibel. So kann ein Modul durch Abhängigkeiten zu weiteren Modulen auch
    deren web-fragments auflesen.

    Im angehängten Beispiel hat man beispielsweise folgende Abhängigkeitsstruktur:
    de.tutorials.web.app -> de.tutorials.app.module3 -> de.tutorials.app.module3.sub1

    Dabei definieren die Module de.tutorials.app.module3 und auch de.tutorials.app.module3.sub1 web-fragments
    welche zur Laufzeit im Servlet Container verwendet werden.

    Mit diesem Mechainsmus kann man sehr einfach erweiterbare Web-Anwendungen entwerfen. Verwendet man viele
    Module die über web-fragments Komponenten zur web-app beisteuern so kann es wichtig sein die Reihenfolge
    in der diese web-fragments ausgewertet werden zu bestimmen. Dazu gibt es mehrere Möglichkeiten siehe 1).
    Natürlich kann man sich bei diesem Ansatz auch sehr leicht in den Fuß schießen... beispielsweise könnte durch das hinzufügen eines "fremden" jars plötzlich ein neues Servlet aktiv werden... hier ist einige Vorsicht geboten, jedoch existieren auch einige Mechanismen zur Kontrollierten Verwendung von web-fragments bereit (explizite Nennung der erlaubten Fragment Ids, bestimmte Servlets lassen sich deaktiveren etc. siehe 2) )

    Weitere Ressourcen:
    1) http://blogs.sun.com/swchan/entry/se...0_web_fragment
    2) http://www.linuxtag.org/2010/fileadm...Tomcat%207.pdf

    Gruß Tom
    Angehängte Dateien Angehängte Dateien
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

Ähnliche Themen

  1. Eclipse Fragments
    Von illuzione im Forum Swing, Java2D/3D, SWT, JFace
    Antworten: 0
    Letzter Beitrag: 22.05.09, 12:05
  2. Profile
    Von Zack im Forum PHP
    Antworten: 4
    Letzter Beitrag: 19.12.07, 18:53
  3. Profile abspeichern
    Von cri im Forum Sonstige Grafik-Programme
    Antworten: 3
    Letzter Beitrag: 07.08.04, 19:54
  4. Profile löschen
    Von kesnw im Forum Microsoft Windows
    Antworten: 0
    Letzter Beitrag: 29.06.04, 11:15