Usar formularios con Java

En esta parte del tutorial de Bookshelf para Java, se muestra cómo acceder a los datos del formulario desde servlets.

Esta página forma parte de un tutorial de varias páginas. Para empezar en orden y consultar las instrucciones de configuración, ve a la sección relativa a la aplicación Bookshelf para Java.

Ejecutar la aplicación en la máquina local

Para ejecutar la aplicación de forma local, sigue estas instrucciones:

  1. Introduce el siguiente comando en el directorio getting-started-java/bookshelf/2-structured-data para iniciar un servidor web local:

    mvn -Plocal clean jetty:run-exploded -DprojectID=[YOUR-PROJECT-ID]
  2. Ve a http://localhost:8080 en el navegador web.

Desplegar la aplicación en el entorno flexible de App Engine

  1. Introduce este comando para desplegar la aplicación:

    mvn appengine:deploy -DprojectID=YOUR-PROJECT-ID
    
  2. Introduce la siguiente dirección en el navegador web. Sustituye [YOUR_PROJECT_ID] por el ID del proyecto:

    https://[YOUR_PROJECT_ID].appspot-preview.com
    

Si actualizas la aplicación, podrás desplegar la versión actualizada con el mismo comando que utilizaste para desplegar la aplicación por primera vez. El nuevo despliegue crea una nueva versión de la aplicación y la establece como la versión predeterminada. No obstante, se conservarán las versiones anteriores, al igual que las instancias de máquina virtual asociadas. Ten en cuenta que todas estas versiones de la aplicación y las instancias de máquina virtual son recursos facturables.

Si eliminas las versiones no predeterminadas de la aplicación, puedes reducir los costes.

Para eliminar una versión de la aplicación, sigue las instrucciones que figuran a continuación:

  1. In the GCP Console, go to the Versions page for App Engine.

    Go to the Versions page

  2. Select the checkbox for the non-default app version you want to delete.
  3. Click Delete to delete the app version.

Consulta la sección sobre cómo eliminar los recursos facturables en el último paso de este tutorial para obtener más información al respecto.

Gestionar los envíos de formularios que realizan los usuarios

El formulario para añadir o editar permite que los usuarios puedan agregar y editar presentaciones de libros dentro de la aplicación.

Imagen del formulario de añadir/editar

Cuando el navegador del usuario realiza la petición /create, el motor de contenedores de servlet carga el CreateBookServlet y llama al método doGet. A continuación, la petición se reenvía al servlet /base.jsp, que incluye el servlet /form.jsp. Una vez que el usuario envía el formulario, se llama al método doPost de CreateBookServlet.

En CreateBookServlet.java, hay dos anotaciones. La anotación @MultipartConfig indica al contenedor de servlets de Jetty que la aplicación utiliza el tipo MIME multipart/form-data para los datos del formulario. La anotación @WebServlet identifica la clase como un servlet y especifica otros atributos. En este caso, el servlet tiene un name de create y un urlPattern de /create. Los parámetros adicionales incluyen asyncSupported, que especifica que el servlet de contenedor puede procesar peticiones de forma asíncrona, y loadOnStartup, que le indica al contenedor que cargue el servlet y ejecute su método init():

@MultipartConfig
@WebServlet(name = "create", urlPatterns = {"/create"})

Con el método doGet, se procesa la petición de un formulario y se configuran los atributos que utilizará el archivo JSP:

@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);
}

El archivo base.jsp sirve como base para las páginas HTML de la aplicación. Comienza incluyendo la biblioteca de etiquetas estándar JSP. Las etiquetas básicas JSTL se identifican mediante etiquetas que empiezan por <c: y proporcionan variables, control del flujo, administración de URLs y otros tipos de soporte. Las funciones JSTL se identifican mediante etiquetas que comienzan por <fn: y ofrecen bibliotecas de gestión de colecciones y de cadenas. Aquí se presenta un resumen de las etiquetas JSTL que utiliza la aplicación Bookshelf:

Etiqueta JSTL Descripción
<c:if ... Evalúa la expresión test e incluye contenido en caso de ser "true".
<c:choose> Etiqueta condicional que establece el contexto para c:when y c:otherwise.
<c:when ... Incluye contenido si test es "true".
<c:otherwise> Si c:when no es "true", incluye este contenido.
<c:import url="" /> Incluye el contenido de la url dentro de la página.
<c:out value="" /> Evalúa la expresión de value y muestra una versión codificada.
${fn:escapeXml()} Caracteres especiales de escape para páginas web.


<%@ 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>

El formulario HTML se crea mediante JavaServer Pages, que es como un motor de plantillas de Java, pero se ejecuta como servlets. El siguiente código JSP especifica que el formulario incluye campos de entrada de texto para el título, el autor, la fecha de publicación, la descripción y la imagen de portada, así como un botón de guardado:

<%@ 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}" enctype="multipart/form-data">

    <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>

Envío de formulario

El método doPost crea un CloudStorageHelper y un BookDao. A los parámetros de formulario se accede mediante las funciones req.getParameter() y la página se redirige a /read para ver lo que se acaba de escribir. Posteriormente hablaremos sobre el acceso a la sesión y la creación de libros:

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
  BookDao dao = (BookDao) this.getServletContext().getAttribute("dao");
  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();
  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);
  }
}
¿Te ha resultado útil esta página? Enviar comentarios: