Recebendo dados de um formulário HTML com Servlets

(Last Updated On: 11 de janeiro de 2017)

No post sobre como criar uma aplicação Java Web utilizando Servlets, fizemos uma aplicação bem básica que imprimia apenas uma mensagem no navegador, porém, eu havia dito que eu queria criar uma aplicação que permitisse o cadastro dos meus livros, e então, listá-los!

Na Web, como fazemos para mandar informações para a aplicação? Utilizamos um formulário em HTML, certo? Para a nossa felicidade, Já temos um modelo de formulário em HTML para cadastro de livro que é explicado com mais detalhes nesse post que escrevi! Então vamos reutilizá-lo:

Formulário de cadastro de livros












Precisamos adicionar esse formulário e uma página HTML, portanto, vamos criar uma página HTML no nosso projeto, podemos inserir esse arquivo na nossa pasta “WebContent/WEB-INF” com o seguinte conteúdo:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cadastro de livro</title>
</head>
<body>

<fieldset>
     <legend>Formulário de cadastro de livros</legend>
	<form>
	<label>Livro</label> 
        <input type="text" /> 
        <label>Autor</label> 
        <input type="text" /> 
        <label>ISBN</label> 
        <input type="text" /> 
        <label>Valor</label>
	<input type="number" step="0.01"/> 
        <label>Data da compra</label> 
        <input type="date" />
	<button>Cadastrar</button>
	</form>
</fieldset>

</body>
</html>

Ótimo, mas como podemos acessar o nosso formulário? Precisamos de uma Servlet que represente esse formulário, então vamos criar a FormularioServlet:

public class FormularioServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
                  throws ServletException, IOException {
	}

}

E como fazemos para exibir HTML usando Servlet? Pelo método println() do tipo PrintWriter, certo? Porém, dessa vez, não queremos escrever o HTML, pois já temos um arquivo pronto!

O que queremos fazer é, no momento em fizermos uma requisição para essa Servlet, exibir esse nosso arquivo! Para isso, precisamos indicar qual o local que está esse arquivo por meio do método getRequestDispatcher() do objeto HttpServletRequest req que representa a requisição dessa Servlet:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
          throws ServletException, IOException {
     req.getRequestDispatcher("WEB-INF/formulario.html");
}

Por fim, precisamos dizer para ele avançar com essa nossa requisição, ou seja, direcionar para essa página chamando o método forward():

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
          throws ServletException, IOException {
     req.getRequestDispatcher("WEB-INF/formulario.html").forward(req, resp);
}

E como podemos acessar agora essa nossa Servlet? Lembra que precisamos adicionar no nosso arquivo web.xml? Então vamos adicioná-la:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<display-name>minha-biblioteca</display-name>

	<servlet>
		<servlet-name>Main Servlet</servlet-name>
		<servlet-class>br.com.caelum.alura.biblioteca.servlet.MainServlet</servlet-class>
	</servlet>
	
	<servlet>
		<servlet-name>Formulario Servlet</servlet-name>
		<servlet-class>br.com.caelum.alura.biblioteca.servlet.FormularioServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>Main Servlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>Formulario Servlet</servlet-name>
		<url-pattern>/formulario</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>

</web-app>

Vamos testar nossa aplicação? Clique com o botão direito no projeto “Run as > Run on Server”, escolha o seu Tomcat conforme havíamos configurado e clique em “Finish”:

tela-inicial

Aparentemente a nossa aplicação está funcionando como o esperado, então agora vamos acessar o nosso formulário com a URL http://localhost:8080/minha-biblioteca/formulario:

url-form-req-barra

Ué, o mesmo conteúdo que o nosso MainServlet? Por que será que está acontecendo isso? Vejamos novamente a URL que ele está atendendo:

<servlet-mapping>
     <servlet-name>Main Servlet</servlet-name>
     <url-pattern>/</url-pattern>
</servlet-mapping>

Ele está atendendo a URL /, ou seja, todas as URL que tiver ao menos uma barra, será atendida pelo MainServlet! E com certeza não é isso que queremos!

Mas como podemos resolver esse problema? Existem duas formas:

  • Configurar para que ele atenda uma URL diferente, por exemplo /index:
  • Deixar a tag url-pattern vazia para que ele atenda a mesma requisição que o barra, porém apenas ela!

Faremos a segunda abordagem! Então vamos alterar a tag do MainServlet:

<servlet-mapping>
     <servlet-name>Main Servlet</servlet-name>
     <url-pattern></url-pattern>
</servlet-mapping>

Reinicie o Tomcat e teste novamente as requisições da aplicação:

Com URL http://localhost:8080/minha-biblioteca/:

tela-inicial

Se testarmos agora com a URL do formulário http://localhost:8080/minha-biblioteca/formulario:

aparecendo-formulario

O nosso formulário aparece! E agora? Precisamos, de alguma forma, preencher os dados desse formulário e enviar para a nossa aplicação.

Para fazer uma requisição a partir de um formulário em HTML, podemos utilizar o atributo action da tag form enviando a URL que receberá os nossos dados:

<fieldset>
    <legend>Formulário de cadastro de livros</legend>
    <form action="url da Servlet">
        <label>Livro</label>
    <!-- restante do código -->

Perceba que, atualmente, não temos uma Servlet responsável em receber esses dados! Então vamos criar a CadastroServlet.

public class CadastroServlet extends HttpServlet {

     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
	       throws ServletException, IOException {
     }

}

E agora? Precisamos registrá-la no web.xml, certo? Novamente aquele mesmo processo cansativo… Será que não existe alguma forma mais fácil? Para a nossa felicidade, existe sim! 😀

A partir da API de Servlet 3.0, temos algumas facilidades que nas versões mais antigas não existiam, como por exemplo, registrar uma Servlet sem a necessidade do arquivo web.xml! Mas como podemos fazer isso? Por meio de anotações!

Para registrarmos uma Servlet sem a necessidade do web.xml, utilizamos a anotação @WebServlet enviando pelo parâmetro name o nome da Servlet:

package br.com.caelum.alura.biblioteca.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="/cadastro")
public class CadastroServlet extends HttpServlet {

     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
	  throws ServletException, IOException {
     }

}

Repare que enviamos apenas o nome da nossa Servlet, e a URL que ela vai atender? Como mandamos? Adicionamos o parâmetro urlMapping e a URL que será atendida:

@WebServlet(name="Cadastro Servlet", urlPatterns="/cadastro")
public class CadastroServlet extends HttpServlet {

     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
	  throws ServletException, IOException {

     }

}

Agora podemos verificar se está funcionando! Mas, antes de testar, vamos adicionar uma mensagem na para sabermos se realmente a CadastroServlet foi acessada:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
	  throws ServletException, IOException {
     writer.println("página de cadastro acessada");
}

Então vamos adicionar a URL dessa Servlet no nosso formulário:

<fieldset>
    <legend>Formulário de cadastro de livros</legend>
    <form action="http://localhost:8080/minha-biblioteca/cadastro">
        <label>Livro</label>
    <!-- restante do código -->

Reinicie o Tomcat e acesse a URL do formulário:

form-preenchido-com-livro

Preencha as informações e clique no botão cadastrar:

get-no-cadastro

Está funcionando conforme o esperado! Porém, o que queremos de verdade? Pegar as informações desse formulário dentro da nossa Servlet, certo? Para isso, precisamos nomear cada input que está sendo enviado no nosso formulário por meio da tag name. Então vamos nomear todos os inputs:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cadastro de livro</title>
</head>
<body>

     <fieldset>
         <legend>Formulário de cadastro de livros</legend>
         <form action="http://localhost:8080/minha-biblioteca/cadastro">
	 <label>Livro</label> 
         <input type="text" name="nome" /> 
	 <label>Autor</label>
	 <input type="text" name="autor" /> 
	 <label>ISBN</label> 
	 <input type="text" name="isbn" /> 
	 <label>Valor</label> 
	 <input type="number" step="0.01" name="valor" /> 
	 <label>Data da compra</label> 
         <input type="date" name="data" />
	 <button>Cadastrar</button>
	 </form>
     </fieldset>

</body>
</html>

E na nossa Servlet? Como fazemos para pegar esses inputs? Lembra que o parâmetro HttpServletRequest req refere-se à própria requisição? Em outras palavras, podemos utilizar o método getParameter() desse parâmetro e retornar o valor do input por meio do nome dele!

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
          throws ServletException, IOException {
     PrintWriter writer = resp.getWriter();
     writer.println("página de cadastro acessada");

     String nome = req.getParameter("nome");
     String autor = req.getParameter("autor");
     String isbn = req.getParameter("isbn");
     String valor = req.getParameter("valor");
     String data = req.getParameter("data");

}

Agora que temos as informações do livro, que tal mostrá-las na página de cadastro? Dessa forma verificamos todas as informações do livro enviado! Primeiro, vamos indicar que a nossa resposta será em HTML ao invés de texto:

resp.setContentType("text/html");

Modificaremos o primeiro texto também:

PrintWriter writer = resp.getWriter();
writer.println("<h1>Livro enviado com sucesso</h1>");

Por fim, vamos imprimir as informações do livro:

String nome = req.getParameter("nome");
String autor = req.getParameter("autor");
String isbn = req.getParameter("isbn");
String valor = req.getParameter("valor");
String data = req.getParameter("data");

writer.println("<ul>");
writer.println("<li>nome: " + nome + "</li>");
writer.println("<li>autor: " + autor + "</li>");
writer.println("<li>isbn: " + isbn + "</li>");
writer.println("<li>valor: " + valor + "</li>");
writer.println("<li>data: " + data + "</li>");
writer.println("</ul>");

Reiniciando o Tomcat e enviando o mesmo formulário de antes:

livro-enviado

Excelente! Agora sim nós conseguimos enviar uma informação desse livro para o nosso servidor!

Nesse post, aprendemos como podemos direcionar uma requisição para uma página HTML que está contida no nosso projeto. Além disso, vimos também que, a partir da API de Servlet 3.0, podemos registrar uma Servlet utilizando a anotação @Webervlet. Por fim, vimos que, para mandar as informações para o servidor a partir de um formulário em HTML, precisamos informar a URL por meio do atributo action da tag form.

E aí? Curtiu a API de Servlets? Quer aprender mais a fundo sobre Servlets? Pensando nisso, o instrutor Guilherme Silveira, criou o curso de Servlets e fundamento de Java web, onde ele aborda toda a base para desenvolvermos uma aplicação de Java Web!

Fique por dentro

Content Editor at Alura and Software Developer

  • Diego

    Ótima serie de artigos, é bom entender como java funciona por traz dos frameworks.

    • Fico contente que tenha gostado Diego! De fato é super importante entender como as coisas acontecem por de trás dos panos justamente para sabermos com o que estamos lidando 😉

  • Aline Silva

    Gostei do post, gostaria de tirar uma dúvida, caso o usuário não preencher os dados no cadastro e apertar o botão, teria que dar erro e como iria voltar para a página do cadastro

    • Alex Felipe

      Oi Aline, tubo bem? Que bom que tenha gostado do post! 🙂

      Sobre a sua dúvida, a partir do parâmetro HttpServletResponse resp você tem acesso ao método sendRedirect() que permite redirecionar o usuário para uma página desejada, portanto, caso a validação falhe, basta apenas usar esse método enviando como parâmetro a página.

      []s

Próximo ArtigoDesmistificando o protocolo HTTP - parte 2