Skip to content

5. Aplicativo web MVC [personne] – versão 1

5.1. As visualizações da aplicação

A aplicação utiliza o formulário empregado nos exemplos anteriores. A primeira página da aplicação é a seguinte:

Image

Chamaremos essa visualização de [formulaire]. Se forem feitas entradas corretas, elas serão exibidas em uma visualização que será chamada de [réponse]:

Image

Se as entradas estiverem incorretas, os erros serão sinalizados em uma visualização chamada [erreurs]:

Image

5.2. Arquitetura do aplicativo

A aplicação web [personne1] terá a seguinte arquitetura:

Image

Essa arquitetura é de camada única: não há camadas [métier] ou [dao], apenas uma camada [web]. [ServletPersonne] é o controlador da aplicação que processa todas as solicitações dos clientes. Para responder a elas, ele utiliza uma das três visualizações [formulaire, réponse, erreurs].

Precisamos determinar como o controlador [ServletPersonne] decide qual ação deve realizar ao receber uma solicitação de um usuário. Uma solicitação do cliente é um fluxo HTTP que varia dependendo se é feita com um comando GET ou POST.

Solicitação GET

Nesse caso, o fluxo HTTP tem a seguinte aparência:

GET /URL HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
[ligne vide]

A linha 1 especifica a URL solicitada, por exemplo:

GET /personne1/ HTTP/1.1

É possível usar essa URL para especificar a ação a ser realizada. Podem ser utilizados diversos métodos:

  1. um parâmetro da URL especifica a ação, por exemplo, [/appli?action=ajouter&id=4]. Aqui, o parâmetro [action] indica ao controlador a ação que lhe é solicitada.
  2. o último elemento da URL especifica a ação, por exemplo, [/appli/ajouter?id=4]. Aqui, o último elemento da URL [/ajouter] é usado pelo controlador para determinar a ação que ele deve realizar.

Outras soluções são possíveis. As duas anteriores são comuns.

Solicitação POST

Nesse caso, o fluxo HTTP fica assim:

POST /URL HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/pessoa1/main
Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
[ligne vide]
txtNom=&txtAge=&action=validationFormulaire

A linha 1 especifica a URL solicitada, por exemplo:

POST /personne1/main HTTP/1.1

É possível usar essa URL para especificar a ação a ser realizada, como no caso do GET. No caso do GET, o parâmetro [action] estava integrado no URL. Isso também pode ocorrer aqui, como em:

POST /appli?action=ajouter&id=4 HTTP/1.1

Mas o parâmetro [action] também pode estar incluído nos parâmetros enviados (linha 15 acima), como em:

POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4

A seguir, utilizaremos essas diferentes técnicas para indicar ao controlador o que ele deve fazer:

  • incluir o parâmetro action na URL solicitada:
POST /appli?action=ajouter&id=4 HTTP/1.1
  • enviar o parâmetro action:
POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4
  • utilizar o último elemento da URL como nome da ação:
POST /appli/ajouter?id=4 HTTP/1.1

5.3. O projeto Eclipse

Para criar o projeto Eclipse [mvc-personne-01] da aplicação web [personne1], siga os passos descritos no parágrafo 3.1.

Image

Não manteremos o contexto [mvc-personne-01] proposto por padrão. Escolheremos [personne1], conforme indicado abaixo:

Image

O resultado obtido é o seguinte:

Image

Caso, por acaso, queiramos alterar o contexto do aplicativo web, utilizaremos a opção [clic droit sur projet -> Properties -> J2EE]:

Image

O novo contexto será indicado em [1].

Vamos criar uma subpasta [vues] na pasta [WEB-INF]: [clic droit sur WEB-INF -> New -> Folder]:

O novo projeto agora é este:

Image

Quando estiver concluído, o projeto ficará assim:

Image

  • O controlador [ServletPersonne] está na pasta [src]
  • as páginas JSP das visualizações [formulaire, réponse, erreurs] estão na pasta [WEB-INF/vues], o que impede que o usuário as acesse diretamente, conforme mostra o exemplo abaixo:

Image

Descreveremos agora os diferentes componentes do aplicativo web [/personne1]. O leitor é convidado a criá-los à medida que avança na leitura.

5.4. Configuração da aplicação web [personne1]

O arquivo web.xml da aplicação /pessoa1 será o seguinte:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <display-name>mvc-personne-01</display-name>
    <!--  ServletPersonne -->
    <servlet>
        <servlet-name>personne</servlet-name>
        <servlet-class>
            istia.st.servlets.personne.ServletPersonne
        </servlet-class>
        <init-param>
            <param-name>urlReponse</param-name>
            <param-value>
                /WEB-INF/vues/reponse.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlErreurs</param-name>
            <param-value>
                /WEB-INF/vues/erreurs.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlFormulaire</param-name>
            <param-value>
                /WEB-INF/vues/formulaire.jsp
            </param-value>
        </init-param>
    </servlet>
    <!--  Mapeamento ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  arquivos de página inicial -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

O que diz esse arquivo de configuração?

  • linhas 34-37: o URL /main é processado pelo servlet chamado pessoa
  • linhas 10-13: o servlet chamado “pessoa” é uma instância da classe [ServletPersonne]
  • linhas 14-19: definem um parâmetro de configuração chamado [urlReponse]. Trata-se da URL da visualização [réponse].
  • linhas 20-25: definem um parâmetro de configuração chamado [urlErreurs]. Trata-se da URL da visualização [erreurs].
  • linhas 26-31: definem um parâmetro de configuração chamado [urlFormulaire]. Essa é a URL da visualização [formulaire].
  • linha 40: [index.jsp] será a página inicial do aplicativo.

As URLs das páginas JSP das visualizações [formulaire, réponse, erreurs] são definidas, cada uma, por um parâmetro de configuração. Isso permite movê-las sem precisar recompilar o aplicativo.

Quando o usuário acessar a URL [/personne1], será o arquivo [index.jsp] que enviará a resposta (arquivo inicial, linha 40). Esse arquivo está na raiz da pasta [WebContent]:

Image

Seu conteúdo é o seguinte:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
  response.sendRedirect("/personne1/main");
%>

A página [index.jsp] limita-se a redirecionar o cliente para a URL [/personne1/main]. Assim, quando o navegador solicita a URL [/personne1], [index.jsp] envia a seguinte resposta:

1
2
3
4
5
6
7
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9; Path=/personne1
Location: http://localhost:8080/pessoa1/main
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Thu, 18 May 2006 15:45:23 GMT
  • linha 1: resposta HTTP/1.1 para indicar ao servidor que se redirecione para outro URL
  • linha 4: o URL para o qual o navegador deve ser redirecionado

Após essa resposta, o navegador solicitará, portanto, a URL [/personne1/main], conforme solicitado (linha 4). O arquivo [web.xml] do aplicativo [/personne1] indica que essa solicitação será processada pelo controlador [ServletPersonne] (linhas 35-36).

5.5. O código das visualizações

Começamos a desenvolvimento da aplicação web pela criação de suas visualizações. Elas permitem identificar as necessidades do usuário em termos de interface gráfica e podem ser testadas sem a presença do controlador.

5.5.1. A visualização [formulaire]

Esta vista corresponde ao formulário de preenchimento do nome e da idade:

Image

tipo HTML
nome
função
1
<input type="text">
txtNom
inserção do nome
2
<input type="text">
txtAge
inserção da idade
3
<input type="submit">
 
envio dos valores inseridos ao servidor na URL /pessoa1/main
4
<input type="reset">
 
para restaurar a página ao estado em que foi recebida inicialmente pelo navegador
5
<input type="button">
 
para limpar o conteúdo dos campos de entrada [1] e [2]

Ela é gerada pela página JSP [formulaire.jsp]. Seu modelo é composto pelos seguintes elementos:

  • [nom]: um nome (String) encontrado nos atributos de sessão associados à chave “nom”
  • [age]: uma idade (String) encontrada nos atributos de sessão associados à chave “idade”

A visualização [formulaire] é obtida quando o usuário solicita a URL [/personne1/main], c.a.d. A URL do controlador [ServletPersonne]. O código da página JSP [formulaire.jsp], que gera a visualização [formulaire], é o seguinte:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // recuperamos os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
      <title>Personne - formulaire</title>
  </head>
  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <form method="post">
          <table>
            <tr>
              <td>Nom</td>
            <td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
          </tr>
          <tr>
              <td>Age</td>
            <td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>
              <td><input type="submit" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" value="Effacer"></td>
          </tr>
        </table>
        <input type="hidden" name="action" value="validationFormulaire"> 
      </form>
    </center>
  </body>
</html>

  • linhas 6-7: a página JSP começa recuperando, na solicitação [request], os elementos [nom, age] de seu modelo. No funcionamento normal do aplicativo, será o controlador [ServletPersonne] que construirá esse modelo.
  • linhas 18-38: a página JSP irá gerar um formulário HTML (tag <form>)
  • linha 18: a tag <form> não possui o atributo action para indicar a URL que deverá processar os valores enviados pelo botão [Envoyer] do tipo submit (linha 32). Os valores do formulário serão, então, enviados para a URL a partir da qual o formulário foi obtido, ou seja, a URL do controlador [ServletPersonne]. Assim, ele é utilizado tanto para gerar o formulário vazio solicitado inicialmente por um GET quanto para processar os dados inseridos que serão enviados a ele por meio do botão [Envoyer].
  • Os valores enviados são os dos campos HTML, [txtNom] (linha 22), [txtAge] (linha 26) e [action] (linha 37). Esse último parâmetro permitirá que o controlador saiba o que deve fazer.
  • Na exibição inicial do formulário, os campos de entrada [txtNom, txtAge] são inicializados, respectivamente, com as variáveis [nom] (linha 22) e [age] (linha 26). Essas variáveis obtêm os valores de seus atributos da consulta (linhas 6-7), atributos que sabemos serem inicializados pelo servlet. Portanto, é este último que define o conteúdo inicial dos campos de entrada do formulário.
  • linha 33: o botão [Rétablir], do tipo [reset], permite restaurar o formulário ao estado em que se encontrava quando foi recebido pelo navegador.
  • linha 34: o botão [Effacer], do tipo [reset], não tem, por enquanto, nenhuma função.

Posteriormente, chamaremos essa visualização de visualização [formulaire(nom, age)] quando quisermos especificar tanto o nome da visualização quanto seu modelo. Além disso, vale lembrar que, quando o usuário clica no botão [Envoyer], os parâmetros [txtNom, txtAge] são enviados para a URL [/personne1/main].

5.5.2. A visualização [reponse]

Essa visualização exibe os valores inseridos no formulário quando estes são válidos:

Image

Ela é gerada pela página JSP [reponse.jsp]. Seu modelo é composto pelos seguintes elementos:

  • [nom]: um nome (String) que será encontrado nos atributos da sessão, associado à chave “nom”
  • [age]: uma idade (String) que será encontrada nos atributos da sessão, associada à chave “idade”

O código da página JSP [reponse.jsp] é o seguinte:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // recuperando os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
  </body>
</html>

  • linhas 6-7: a página JSP começa recuperando, na solicitação [request], os elementos [nom, age] de seu modelo. No funcionamento normal do aplicativo, será o controlador [ServletPersonne] que construirá esse modelo.
  • Os elementos [nom, age] do modelo são, em seguida, exibidos nas linhas 20 e 24

Posteriormente, chamamos essa visualização de visualização [réponse(nom, age)].

5.5.3. A visualização [erreurs]

Essa visualização sinaliza os erros de preenchimento no formulário:

Image

Ela é gerada pela página JSP [erreurs.jsp]. Seu modelo é composto pelos seguintes elementos:

  • [erreurs]: uma lista (ArrayList) de mensagens de erro que será encontrada nos atributos da consulta, associada à chave “erros”

O código da página JSP [erreurs.jsp] é o seguinte:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page import="java.util.ArrayList" %>

<%
// recuperando os dados do modelo
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
        <%
          for(int i=0;i<erreurs.size();i++){
            out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
        }//para
      %>
    </ul>
  </body>
</html>

  • linha 8: a página JSP começa recuperando, na solicitação [request], o elemento [erreurs] de seu modelo. Esse elemento representa um objeto do tipo ArrayList, composto por elementos do tipo String. Esses elementos são mensagens de erro. No funcionamento normal do aplicativo, será o controlador [ServletPersonne] que construirá esse modelo.
  • linhas 18-22: exibem a lista de mensagens de erro. Para isso, é necessário escrever código Java no corpo HTML da página. Deve-se sempre procurar reduzir esse código ao mínimo para não sobrecarregar o código HTML. Veremos posteriormente que existem soluções que permitem reduzir a quantidade de código Java nas páginas JSP.
  • linha 4: observe a tag de importação dos pacotes necessários para a página JSP

Posteriormente, chamamos essa visualização de visualização [erreurs(erreurs)].

5.6. Testes das visualizações

É possível testar a validade das páginas JSP sem ter escrito o controlador. Para isso, são necessárias duas condições:

  • é preciso poder solicitá-las diretamente à aplicação, sem passar pelo controlador
  • é necessário que a página JSP inicialize por conta própria o modelo que, normalmente, seria construído pelo controlador

Para realizar esses testes, duplicamos as páginas JSP das visualizações na pasta [/WebContent/JSP] do projeto Eclipse:

Image

Em seguida, na pasta JSP, as páginas são modificadas da seguinte maneira:

[formulaire.jsp]:


...

<%
  // -- teste: cria-se o modelo da página
  request.setAttribute("nom","tintin");
  request.setAttribute("age","30");
%>

<%
    // recuperam-se os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
...

As linhas 3 a 7 foram adicionadas para criar o modelo necessário para a página nas linhas 11 e 12.

[reponse.jsp]:


...

<%
  // -- teste: cria-se o modelo da página
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
%>

<%
    // recuperamos os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

    
<html>
    <head>
...

As linhas 3 a 7 foram adicionadas para criar o modelo necessário para a página das linhas 11 e 12.

[erreurs.jsp]:


...

<%
  // -- teste: criamos o modelo da página
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
%>

<%
// recuperam-se os dados do modelo
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

    
<html>
    <head>
...

As linhas 3 a 9 foram adicionadas para criar o modelo necessário para a página da linha 13.

Inicie o Tomcat, caso ainda não tenha feito isso, e, em seguida, acesse as seguintes URLs:

 

Recebemos as visualizações esperadas. Agora que temos uma confiança razoável nas páginas JSP do aplicativo, podemos passar à criação de seu controlador [ServletPersonne].

5.7. O controlador [ServletPersonne]

Resta escrever o núcleo do nosso aplicativo web: o controlador. Sua função consiste em:

  • receber a solicitação do cliente,
  • processar a ação solicitada pelo cliente,
  • enviar a visualização apropriada como resposta.

O controlador [ServletPersonne] processará as seguintes ações:

n.º
solicitação
origem
processamento
1
[GET /personne1/main]
URL digitada pelo usuário
- enviar a visualização [formulaire] vazia
2
[POST /personne1/main]
com parâmetros [txtNom,
txtAge, ação] publicados
ao clicar no botão
[Envoyer] da visualização
[formulaire]
- verificar os valores dos parâmetros [txtNom, txtAge]
- se estiverem incorretos, enviar a visualização [erreurs(erreurs)]
- se estiverem corretos, enviar a visualização [reponse(nom,age)]

O aplicativo é iniciado quando o usuário solicita a URL [/personne1/main]. De acordo com o arquivo [web.xml] do aplicativo (ver parágrafo 5.4), essa solicitação é processada por uma instância do tipo ServletPersonne, que descreveremos a seguir.

5.7.1. Estrutura do controlador

O código do controlador [ServletPersonne] é o seguinte:

package istia.st.servlets.personne;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
...

     // inicialização
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
    }

    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
...
    }

     // exibição da visualização inicial
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

     // validação do formulário
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
...
    }

     // envio
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
         // passa o controle para o GET
        doGet(request, response);
    }
}
  • linhas 20-22: o método [init] executado no carregamento inicial do servlet
  • linhas 25-28: o método [doGet] chamado pelo servidor web quando uma solicitação do tipo GET é feita ao aplicativo
  • linhas 42-46: o método [doPost] chamado pelo servidor web quando uma solicitação do tipo POST é feita à aplicação. Conforme mostrado, essa solicitação também será processada pelo método [doGet] (linha 45).
  • linhas 31-33: o método [doInit] processa a ação nº 1 [GET /personne1/main]
  • linhas 36-39: o método [doValidationFormulaire] processa a ação nº 2 [POST /personne1/main] com os parâmetros enviados por [txtNom, txtAge, action].

Descreveremos agora os diferentes métodos do controlador

5.7.2. Inicialização do controlador

Quando a classe do controlador é carregada pelo contêiner de servlets, seu método [init] é executado. Isso ocorrerá apenas uma vez. Uma vez carregado na memória, o controlador permanecerá nela e processará as solicitações dos diferentes clientes. Cada cliente é alocado a um thread de execução e, assim, os métodos do controlador são executados simultaneamente por diferentes threads. Vale lembrar que, por esse motivo, o controlador não deve possuir campos que possam ser modificados por seus métodos. Seus campos devem ser somente de leitura. Eles são inicializados pelo método [init], cuja função principal é justamente essa. Esse método tem, de fato, a particularidade de ser executado uma única vez por um único thread. Portanto, não há problemas de acesso simultâneo aos campos do controlador nesse método. O método [init] tem como objetivo inicializar os objetos necessários para a aplicação web, que serão compartilhados em modo somente leitura por todas as threads clientes. Esses objetos compartilhados podem ser colocados em dois locais:

  • nos campos privados do controlador
  • o contexto de execução da aplicação (ServletContext)

O código do método [init] do controlador [ServletPersonne] é o seguinte:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // parâmetros de instância
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

     // inicialização
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
         // recuperamos os parâmetros de inicialização do servlet
        ServletConfig config = getServletConfig();
         // processamos os demais parâmetros de inicialização
        String valeur=null;
        for(int i=0;i<paramètres.length;i++){
             // valor do parâmetro
            valeur=config.getInitParameter(paramètres[i]);
             // o parâmetro está presente?
            if(valeur==null){
                 // registra-se o erro
                erreursInitialisation.add("Le paramètre ["+paramètres[i]+"] n'a pas été initialisé");
            }else{
                 // armazenamos o valor do parâmetro
                params.put(paramètres[i],valeur);
            }
             // a URL da visualização [erreurs] tem um tratamento especial
            urlErreurs = config.getInitParameter("urlErreurs");
            if (urlErreurs == null)
                throw new ServletException(
                        "Le paramètre [urlErreurs] n'a pas été initialisé");
        }
    }
...
}
  • linha 16: recupera-se a configuração da aplicação web, c.a.d. O conteúdo do arquivo [web.xml]
  • linhas 19-29: recuperam-se os parâmetros de inicialização do servlet, cujos nomes estão definidos na tabela [paramètres] da linha 9
  • linha 21: o valor do parâmetro é recuperado
  • linha 25: se o parâmetro estiver ausente, o erro é adicionado à lista de erros [erreursInitialisation], inicialmente vazia (linha 8).
  • linha 28: se o parâmetro estiver presente, ele é armazenado com seu valor no dicionário [params], inicialmente vazio (linha 10).
  • linhas 31-35: o parâmetro [urlErreurs] deve estar obrigatoriamente presente, pois indica a URL da visualização [erreurs] capaz de exibir eventuais erros de inicialização. Se ele não existir, a aplicação é interrompida com a execução de um [ServletException] (linha 33).

5.7.3. O método [doGet]

O método [doGet] processa tanto as solicitações GET quanto as POST no servlet, uma vez que o método [doPost] redireciona para o método [doGet]. Seu código é o seguinte:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // parâmetros de instância
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

...
    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

         // verifica-se como ocorreu a inicialização do servlet
        if (erreursInitialisation.size() != 0) {
             // o controle é passado para a página de erros
            request.setAttribute("erreurs", erreursInitialisation);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
             // fim
            return;
        }

         // recuperamos o método de envio da solicitação
        String méthode=request.getMethod().toLowerCase();
         // recupera-se a ação a ser executada
        String action=request.getParameter("action");
         // ação?
        if(action==null){
            action="init";
        }
         // execução da ação
        if(méthode.equals("get") && action.equals("init")){
             // inicialização do aplicativo
            doInit(request,response);
            return;
        }
        if(méthode.equals("post") && action.equals("validationFormulaire")){
             // validação do formulário de preenchimento
            doValidationFormulaire(request,response);
            return;
        }
         // outros casos
        doInit(request,response);
    }

     // envio
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
         // passa o controle para o GET
        doGet(request, response);
    }
}
  • linhas 18-25: verifica-se se a lista de erros de inicialização está vazia. Caso contrário, exibe-se a vista [erreurs(erreursInitialisation)], que sinalizará o(s) erro(s).

Para entender esse código, é preciso lembrar o modelo da visualização [erreurs]:

<%
// recuperação dos dados do modelo
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

A visualização [erreurs] espera um elemento-chave “erros” na solicitação. O controlador cria esse elemento na linha 20.

  • linha 28: recupera-se o método [get] ou [post] que o cliente utilizou para fazer sua consulta
  • linha 30: recupera-se o valor do parâmetro [action] da solicitação. Vale lembrar que, em nosso aplicativo, apenas a solicitação nº 2, [POST /personne1/main], possui o parâmetro [action]. Nessa solicitação, ele tem o valor [validationFormulaire].
  • linhas 31-34: se o parâmetro [action] não estiver presente, atribui-se a ele o valor “init”. Esse será o caso na solicitação inicial nº 1, [GET /personne1/main].
  • linhas 36-40: processamento da solicitação nº 1 [GET /personne1/main].
  • linhas 41-45: processamento da solicitação nº 2 [POST /personne1/main].
  • linha 47: se não estivermos em nenhum dos dois casos anteriores, procedemos como se estivéssemos no caso nº 1

5.7.4. O método [doInit]

Este método processa a solicitação nº 1 [GET /personne1/main]. Nessa solicitação, ele deve enviar a visualização [formulaire(nom,age)] vazia. Seu código é o seguinte:

package istia.st.servlets.personne;
...

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // parâmetros de instância
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

...    
     // exibição da visualização inicial
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // envia-se o formulário vazio
        request.setAttribute("nom", "");
        request.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
...
}
  • linhas 18-19: a visualização [formulaire] é exibida. Vale lembrar o modelo esperado por essa visualização:

<%
    // recuperam-se os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
  • linhas 16-17: o modelo [nom,age] da visualização [formulaire] é inicializado com strings vazias.

5.7.5. O método [doValidationFormulaire]

Este método processa a solicitação nº 2 [POST /personne1/main], na qual os parâmetros enviados são [action, txtNom, txtAge]. Seu código é o seguinte:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // parâmetros de instância
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();
...
     // validação do formulário
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // recuperação dos parâmetros
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
         // verificação dos parâmetros
        ArrayList<String> erreursAppel = new ArrayList<String>();
         // o nome não pode estar vazio
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
         // a idade deve ser um número inteiro >=0
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
         // há erros nos parâmetros?
        if (erreursAppel.size() != 0) {
             // enviando a página de erros
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(request, response);
            return;
        }
         // os parâmetros estão corretos — enviamos a página de resposta
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
...
}
  • linhas 16-17: recuperam-se da solicitação do cliente os valores dos parâmetros “txtNom” e “txtAge”.
  • linhas 19-26: verifica-se a validade desses dois parâmetros
  • linhas 28-33: se algum dos parâmetros estiver incorreto, exibe-se a visualização [erreurs(erreursAppel)]. Vale lembrar o modelo dessa visualização:

<%
// recuperando os dados do modelo
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
  • linhas 35-38: se os dois parâmetros “txtNom” e “txtAge” recuperados tiverem valores válidos, exibe-se a visualização [reponse(nom,age)]. É preciso lembrar o modelo da visualização [reponse]:

<%
    // recuperando os dados do modelo
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

5.8. Tests

Vamos incluir o projeto [mvc-personne-01] nas aplicações do Tomcat, seguindo o procedimento descrito no parágrafo 3.3:

Image

Inicie o Tomcat. Feito isso, será possível retomar os testes apresentados como exemplo no parágrafo 5.1. Também será possível adicionar outros testes. Por exemplo, podemos remover um dos parâmetros de configuração urlXXX do web.xml e observar o resultado. Assim, conforme mostrado abaixo, um dos parâmetros foi colocado entre comentários no [web.xml]:


        <!-- 
            <init-param>
              <param-name>urlFormulaire</param-name>
              <param-value>
                /WEB-INF/vues/formulaire.jsp
              </param-value>
            </init-param>
        -->

Inicializamos/reinicializamos o Tomcat e acessamos a URL [http://localhost:8080/personne1/main]. Obtemos a seguinte resposta:

Image