Iniciando com Servets

Posted by Luciano Cunha on November 18, 2023
Tags: web java

O desenvolvimento web utilizando Java envolve a edição Enterprise (Java EE). Essa implementação, construída sobre a plataforma SE, oferece recursos que viabilizam a criação de aplicações em rede, possibilitando, por conseguinte, o desenvolvimento de aplicativos web.

Uma tecnologia fundamental no desenvolvimento Web com Java é o Servlet.

Os Servlets são componentes, que quando instalados em um servidor que implemente um Servlet Container, têm a capacidade de processar requisições e gerar respostas.

Dentre suas características estão:

  • Ciclo de vida bem definido
  • Tratamento de requisições
  • Gerenciamento de Sessão
  • Aspectos Segurança

A API de Servlet do Java

Para desenvolver um servlet simples, é necessário compreender a hierarquia envolvida nas classes dessa API, implementar suas funcionalidades e realizar o deploy em conjunto com um Servlet Container.

Para isso, recorreremos à documentação.

Já no overview, observamos que, nesta edição da API, os pacotes são organizados sob o pacote principal javax.

Um pacote relevante é o javax.servlet, que, conforme a própria documentação afirma:

The javax.servlet package contains a number of classes and interfaces that
describe and define the contracts between a servlet class and the runtime
environment provided for an instance of such a class by a conforming servlet
container.

Em outras palavras, é nesse ponti que se "inicia" a especificação de servlets. Existem outros pacotes mais especializados, mas, por enquanto, adicionaremos somente o pacote javax.servet.http:

The javax.servlet.http package contains a number of classes and interfaces that
describe and define the contracts between a servlet class running under the
HTTP protocol and the runtime environment provided for an instance of such a
class by a conforming servlet container.

Isso é exatamente o que desejamos: criar um componente capaz de processar requisições feitas com o protocolo HTTP.

Criando um Sevlet de exemplo

Assumindo a existência de um ambiente com Java 8 e Maven configurado, vamos criar um projeto web utilizando Maven.

$ mkdir simple-servlet
$ cd simple-servlet
$ mvn archetype:generate -DgroupId=io.github.lucianodacunha -DartifactId=simple-servlet -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

Utilizando esse archetype, criaremos um projeto web, seguindo a estrutura exigida pela especificação do Servlet.

├── pom.xml
└── src
    └── main
        └── webapp
            ├── index.jsp
            └── WEB-INF
                └── web.xml

Essa é a estrutura criada com o comando acima ao especificarmos o archetype mave-archetype-webapp.

  • pom.xml: Esse é o arquivo que descreve todas as configurações do projeto
  • src/main: Diretório dos códigos-fonte Java.
  • src/main/webapp:
  • index.jsp: página Java Server Page, outra tecnologia JEE.
  • WEB-INF: Diretório destinada à páginas web e ao descritor dos componentes.
    • web.xml: Descreve informações das configurações dos componentes Web (Servlets). A partir da versão 3, dos Servlet, esse xml já não é mais tão necessário, possibilitando a publicação de componentes utilizando annotations.

Com base nessa estrutura, desenvolvemos uma classe que implementará um método capaz de processar requisições GET.

$ mkdir -p src/main/java/servlet
$ touch src/main/java/servlet/HelloServlet.java

Nessa classe, inserimos o seguinte código:

package servlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet{
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
            PrintWriter out = resp.getWriter();
            out.println("Hello, world!");
    }
}

No código acima, estamos utilizando uma extensão da classe HttpServlet para implementar um método que responde a uma requisição do tipo GET.

Para isso, importamos os recursos do pacote java.io.*, que proporciona funcionalidades para impressão e envio de mensagens ao navegador.

Fazemos uso de classes dos pacotes javax.servlet, que inclui a classe ServletException.

Alé disso, utilizamos classes do pacote javax.servlet.http, que oferece recursos como a classe HttpServlet. Esta classe abstrata que dever ter pelo menos um de seus métodos sobrecarregados para disponibilizar funcionalidades de requests/responses com HTTP.

Por fim, empregamos recursos do pacote javax.servlet.annotation, que disponibiliza anotações existentes desde a versão 3 da API. As annotations forma introduzidas para facilitar o desenvolvimento, reduzindo a necessidade do uso de descritores xml.

Ao acessar o recurso, o usuário receberá uma resposta contendo a expressão Hello, world!.

Nesse exemplo, implementamos somente o método doGet, que responde às chamadas GET, feitas à aplicação.

O arquivo web.xml

Localizado na pasta WEB-INF, esse arquivo já não é mais tão essencial. A partir da versão 3 da API de Servlet, podemos empregar annotations para realizar configurações, reduzindo consideravelmente o uso de XML no projeto.

Entretanto, se necessário, ainda podemos configurá-lo para realizar o mapeamento dos Servlets. Na prática, optamos por utilizar annotations ou recorremos ao uso do web.xml.

Segue abaixo um exemplo de como o arquivo apresentaria, caso não estivessemos utilizando annotations:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!-- Opcional a partir da Servlet 3-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>servlet.HelloServlet</servlet-class>
    </servlet>  
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>    
</web-app>

O arquivo POM.xml

Esse arquivo descreve todas as configurações do projeto, incluindo dependências e plugins utilizados no Maven.

Para este projeto, utilizaremos uma dependência do Servlet e um plugin do Jetty.

Veja abaixo como ficou o arquivo:

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>io.github.lucianodacunha</groupId>
  <artifactId>simple-servlet</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>simple-servlet Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>    
  </dependencies>
  <build>
    <finalName>simple-servlet</finalName>
    <plugins>
			<plugin>
				<groupId>org.eclipse.jetty</groupId>
				<artifactId>jetty-maven-plugin</artifactId>
				<version>9.4.28.v20200408</version>
				<configuration>
					<scanIntervalSeconds>10</scanIntervalSeconds>
					<webApp>
						<contextPath>/</contextPath>
					</webApp>
				</configuration>
			</plugin>
		</plugins>    
  </build>
</project>

O plugin do Jetty é o responsável por publicar o projeto utilizando apenas o goal jetty:run do Maven. Do contrário, seria necessário instalarmos e configurarmos um Servidor Web.

Deploy do projeto

Nessa etapa, vamos compilar o projeto para o deploy no servidor:

Na pasta raiz do projeto, execute o comando:

$ mvn clean package jetty:run

Essa sequência de goals irá:
- limpar a pasta do projeto, caso tenha algo compilado,
- fazer um novo empacotamento,
- subir o servidor Jetty e publicar o projeto.

Para verificar a saída gerada, no navegador, acesse http://localhost:8080.

Para saber mais: