Formulare mit Java für die App Engine-Standardumgebung verwenden

In diesem Teil der Anleitung zu Bookshelf für Java wird erläutert, wie Sie aus Servlets auf Formulardaten zugreifen.

Diese Seite ist Teil einer mehrseitigen Anleitung. Wenn Sie dieses Beispiel von Beginn an durcharbeiten möchten, rufen Sie die Java Bookshelf-Anwendung auf und lesen Sie die Anleitung zur Einrichtung.

App auf lokalem Computer ausführen

So führen Sie die App lokal aus:

  1. Geben Sie im Verzeichnis getting-started-java/bookshelf-standard/2-structured-data den folgenden Befehl ein, um einen lokalen Webserver zu starten:

    mvn package appengine:run
  2. Rufen Sie in Ihrem Webbrowser http://localhost:8080/ auf.

App in der App Engine-Standardumgebung bereitstellen

So stellen Sie die App in der App Engine-Standardumgebung bereit:

  1. Um einen Datenspeicherindex zu erstellen, der in die Bookshelf-App hochgeladen wird, erstellen Sie mindestens ein Buch und klicken Sie dann auf Meine Bücher. Beachten Sie, dass beim Erstellen der App mit dem Befehl clean dieser lokale Index gelöscht wird. Führen Sie dies also beim Erstellen der App aus, die Sie bereitstellen möchten.
  2. Geben Sie im Verzeichnis getting-started-java/bookshelf-standard/2-structured-data den folgenden Befehl ein, um die App bereitzustellen:
    mvn appengine:deploy -Dappengine.appId=[YOUR-PROJECT-ID] -Dappengine.version=[YOUR-VERSION]
    Ersetzen Sie [YOUR-PROJECT-ID] durch Ihre Projekt-ID und [YOUR-VERSION] durch Ihre Version (zum Beispiel 1 oder 2) oder einen anderen zu verwendenden Stringwert.
  3. Geben Sie im Webbrowser die folgende URL ein:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    Ersetzen Sie Folgendes:

Nachdem Sie Ihre App aktualisiert haben, können Sie die aktualisierte Version noch einmal bereitstellen. Geben Sie dazu denselben Befehl wie bei der ersten Bereitstellung der App ein und dieselbe Projekt-ID und Version an. Dadurch wird die aktuell bereitgestellte App überschrieben. Wenn Sie in der aktualisierten Befehlszeile einen anderen Versionsstring angeben, erstellt die neue Bereitstellung eine neue Version Ihrer App und befördert sie zur aktuell bereitgestellten Version.

Sie können die Kosten senken, indem Sie die nicht standardmäßigen Versionen der App löschen.

So löschen Sie eine Anwendungsversion:

  1. Rufen Sie in der Cloud Console die Seite Versionen für App Engine auf.

    Zur Seite "Versionen"

  2. Klicken Sie auf das Kästchen für die nicht standardmäßige App-Version, die Sie löschen möchten.
  3. Klicken Sie auf Löschen , um die Anwendungsversion zu löschen.

Ausführliche Informationen zum Bereinigen kostenpflichtiger Ressourcen finden Sie im letzten Schritt dieser Anleitung im Abschnitt Bereinigen.

Nutzereingaben mit Formularen abwickeln

Mit dem Formular können Sie Bucheinreichungen in die App aufnehmen und dort bearbeiten.

Bild des Formulars zum Hinzufügen/Bearbeiten

Wenn Ihr Browser /create anfordert, lädt das Servlet Google Kubernetes Engine das CreateBookServlet und ruft die doGet-Methode auf. Anschließend wird die Anfrage an das Servlet /base.jsp weitergeleitet, das das Servlet /form.jsp enthält. Nachdem Sie das Formular gesendet haben, wird die doPost-Methode von CreateBookServlet aufgerufen.

In CreateBookServlet.java verarbeitet die Methode doGet die Anfrage nach einem Formular und richtet die von der JSP-Datei verwendeten Attribute ein:

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
  req.setAttribute("action", "Add");          // Part of the Header in form.jsp
  req.setAttribute("destination", "create");  // The urlPattern to invoke (this Servlet)
  req.setAttribute("page", "form");           // Tells base.jsp to include form.jsp
  req.getRequestDispatcher("/base.jsp").forward(req, resp);
}

Die Datei base.jsp dient als Grundlage für die HTML-Seiten der App. Hierzu wird zuerst die JSP Standard-Tag-Bibliothek eingebunden. Die JSTL-Core-Tags sind Tags, die mit <c: beginnen. Sie stellen die Variable, die Ablaufsteuerung, die URL-Verwaltung und sonstige Unterstützungen bereit. JSTL-Funktionen werden durch Tags identifiziert, die mit <fn: beginnen, und stellen Sammlungen und Bibliotheken zur Stringbearbeitung bereit. Hier sehen Sie eine Zusammenfassung der von der Bookshelf-App verwendeten JSTL-Tags:

JSTL-Tag Beschreibung
<c:if ... Den Ausdruck test auswerten und den Inhalt einfügen, wenn der Wert wahr ist.
<c:choose> Bedingungs-Tag, das den Kontext für c:when und c:otherwise festlegt.
<c:when ... Fügt Inhalte hinzu, wenn test wahr ist.
<c:otherwise> Wenn c:when nicht wahr ist, wird dieser Inhalt hinzugefügt.
<c:import url="" /> Fügt den Inhalt von url in die Seite ein.
<c:out value="" /> Den Ausdruck für value auswerten und als codierte Version anzeigen.
${fn:escapeXml()} Escape-Sonderzeichen für Webseiten.


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<html lang="en">
  <head>
    <title>Bookshelf - Java on Google Cloud Platform</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
  </head>
  <body>
    <div class="navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <div class="navbar-brand">Bookshelf</div>
        </div>
        <ul class="nav navbar-nav">
          <li><a href="/">Books</a></li>
          <c:if test="${isAuthConfigured}"><li><a href="/books/mine">My Books</a></li></c:if>
        </ul>
        <p class="navbar-text navbar-right">
          <c:choose>
          <c:when test="${not empty token}">
          <!-- using pageContext requires jsp-api artifact in pom.xml -->
          <a href="/logout">
            <c:if test="${not empty userImageUrl}">
              <img class="img-circle" src="${fn:escapeXml(userImageUrl)}" width="24">
            </c:if>
            ${fn:escapeXml(userEmail)}
          </a>
          </c:when>
          <c:when test="${isAuthConfigured}">
          <a href="/login">Login</a>
          </c:when>
          </c:choose>
        </p>
      </div>
    </div>
    <c:import url="/${page}.jsp" />
  </body>
</html>

Das HTML-Formular wird mithilfe von JavaServer Pages erstellt. Dies ist vergleichbar mit einer Vorlagen-Engine für Java. Sie werden aber als Servlets ausgeführt. Der nachstehende JSP-Code legt fest, dass das Formular Texteingabefelder für Titel, Autor, Erscheinungsdatum und Beschreibung, ein Feld für das Titelbild sowie eine Schaltfläche zum Speichern enthält:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<div class="container">
  <h3>
    <c:out value="${action}" /> book
  </h3>

  <form method="POST" action="${destination}">

    <div class="form-group">
      <label for="title">Title</label>
      <input type="text" name="title" id="title" value="${fn:escapeXml(book.title)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="author">Author</label>
      <input type="text" name="author" id="author" value="${fn:escapeXml(book.author)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="publishedDate">Date Published</label>
      <input type="text" name="publishedDate" id="publishedDate" value="${fn:escapeXml(book.publishedDate)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="description">Description</label>
      <textarea name="description" id="description" class="form-control">${fn:escapeXml(book.description)}</textarea>
    </div>

    <div class="form-group ${isCloudStorageConfigured ? '' : 'hidden'}">
      <label for="image">Cover Image</label>
      <input type="file" name="file" id="file" class="form-control" />
    </div>

    <div class="form-group hidden">
      <label for="imageUrl">Cover Image URL</label>
      <input type="hidden" name="id" value="${book.id}" />
      <input type="text" name="imageUrl" id="imageUrl" value="${fn:escapeXml(book.imageUrl)}" class="form-control" />
    </div>

    <button type="submit" class="btn btn-success">Save</button>
  </form>
</div>

Formular übermitteln

Die Methode doPost erstellt ein Book-Objekt, liest Parameter aus dem Formular von den req.getParameter()-Aufrufen ein und übergibt das Book-Objekt dann an ein neues BookDao-Objekt, das die neue Buchentität zu Datastore hinzufügt. Nachdem das Buch in Datastore gespeichert wurde, wird die Seite auf /read umgeleitet, sodass Sie sehen können, was gerade gespeichert wurde. Der Zugriff auf die Sitzung und die Erstellung von Büchern werden später erläutert:

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
  Book book = new Book.Builder()
      .author(req.getParameter("author"))   // form parameter
      .description(req.getParameter("description"))
      .publishedDate(req.getParameter("publishedDate"))
      .title(req.getParameter("title"))
      .imageUrl(null)
      .build();

  BookDao dao = (BookDao) this.getServletContext().getAttribute("dao");
  try {
    Long id = dao.createBook(book);
    resp.sendRedirect("/read?id=" + id.toString());   // read what we just wrote
  } catch (Exception e) {
    throw new ServletException("Error creating book", e);
  }
}