Skip to content

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

5.1. As vistas da aplicação

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

Image

Chamaremos a esta vista a vista [formulaire]. Se forem introduzidos dados corretos, estes são apresentados numa vista que será designada por [réponse]:

Image

Se as entradas estiverem incorretas, os erros são assinalados numa vista denominada [erreurs]:

Image

5.2. Arquitetura da aplicação

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

Image

Esta arquitetura é de camada única: não existem camadas [métier] ou [dao], apenas uma camada [web]. [ServletPersonne] é o controlador da aplicação que processa todos os pedidos dos clientes. Para responder a esses pedidos, utiliza uma das três vistas [formulaire, réponse, erreurs].

Temos de determinar como é que o controlador [ServletPersonne] determina a ação que deve realizar ao receber uma solicitação de um utilizador. Uma solicitação do cliente é um fluxo HTTP que varia consoante seja efetuada com um comando GET ou POST.

Solicitação GET

Neste caso, o fluxo HTTP tem o seguinte aspeto:

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 o URL solicitado, por exemplo:

GET /personne1/ HTTP/1.1

É possível utilizar esta URL para especificar a ação a realizar. Podem ser utilizados vários 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] é utilizado pelo controlador para determinar a ação que deve realizar.

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

Pedido POST

Neste caso, o fluxo HTTP tem o seguinte aspeto:

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 o URL solicitado, por exemplo:

POST /personne1/main HTTP/1.1

É possível utilizar esta URL para especificar a ação a realizar, tal como no caso do GET. No caso do GET, o parâmetro [action] estava integrado no URL. Isso também pode ser o caso 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), tal como em:

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

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

  • integrar o parâmetro action no URL solicitado:
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 do 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 se manterá o contexto [mvc-personne-01] proposto por predefinição. Escolher-se-á [personne1], conforme indicado abaixo:

Image

O resultado obtido é o seguinte:

Image

Se, por acaso, se pretender alterar o contexto da aplicação web, utilizar-se-á a opção [clic droit sur projet -> Properties -> J2EE]:

Image

Indicaremos o novo contexto 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] encontra-se na pasta [src]
  • As páginas JSP das vistas [formulaire, réponse, erreurs] encontram-se na pasta [WEB-INF/vues], o que impede o utilizador de as aceder diretamente, como mostra o exemplo abaixo:

Image

Passamos agora a descrever os diferentes componentes da aplicação web [/personne1]. O leitor é convidado a criá-los à medida que avança na leitura.

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

O ficheiro 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>
    <!--  ficheiros de boas-vindas -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

O que diz este ficheiro de configuração?

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

As URLs das páginas JSP das vistas [formulaire, réponse, erreurs] são, cada uma, objeto de um parâmetro de configuração. Isto permite movê-las sem ter de recompilar a aplicação.

Quando o utilizador solicitar a URL [/personne1], será o ficheiro [index.jsp] que enviará a resposta (ficheiro inicial, linha 40). Este ficheiro encontra-se na raiz da pasta [WebContent]:

Image

O 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 o URL [/personne1/main]. Assim, quando o navegador solicita a URL [/personne1], a [index.jsp] envia-lhe a seguinte resposta HTTP:

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 esta resposta, o navegador irá, portanto, solicitar o URL [/personne1/main], tal como lhe foi solicitado (linha 4). O ficheiro [web.xml] da aplicação [/personne1] indica que este pedido será tratado pelo controlador [ServletPersonne] (linhas 35-36).

5.5. O código das vistas

Começamos a programação da aplicação web pela criação das suas vistas. Estas permitem identificar as necessidades do utilizador em termos de interface gráfica e podem ser testadas sem a presença do controlador.

5.5.1. A vista [formulaire]

Esta vista corresponde ao formulário de introdução do nome e da idade:

Image

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

É gerada pela página JSP [formulaire.jsp]. O seu modelo é constituído pelos seguintes elementos:

  • [nom]: um nome (String) encontrado nos atributos da sessão associados à chave «nom»
  • [age]: uma idade (String) encontrada nos atributos da sessão associada à chave «idade»

A vista [formulaire] é obtida quando o utilizador 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 vista [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">
<%
    // recuperam-se 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 por recuperar, na solicitação [request], os elementos [nom, age] do seu modelo. No funcionamento normal da aplicação, será o controlador [ServletPersonne] que irá construir este modelo.
  • linhas 18-38: a página JSP irá gerar um formulário HTML (tag <form>)
  • linha 18: a baliza <form> não possui o atributo action para indicar o 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, este é utilizado tanto para gerar o formulário vazio solicitado inicialmente por um GET como para processar os dados introduzidos que lhe serão enviados através do botão [Envoyer].
  • Os valores enviados são os dos campos HTML, [txtNom] (linha 22), [txtAge] (linha 26) e [action] (linha 37). Este último parâmetro permitirá ao controlador saber o que deve fazer.
  • Na exibição inicial do formulário, os campos de introdução de dados [txtNom, txtAge] são inicializados, respetivamente, com as variáveis [nom] (linha 22) e [age] (linha 26). Estas variáveis obtêm os valores dos seus atributos a partir da consulta (linhas 6-7), atributos que sabemos serem inicializados pelo servlet. É, portanto, este último que define o conteúdo inicial dos campos de introdução de dados do formulário.
  • linha 33: o botão [Rétablir], do tipo [reset], permite repor o formulário no estado em que se encontrava quando o navegador o recebeu.
  • linha 34: o botão [Effacer], do tipo [reset], não tem, por enquanto, qualquer função.

Posteriormente, iremos referir-nos a esta vista como a vista [formulaire(nom, age)] quando quisermos especificar tanto o nome da vista como o seu modelo. Além disso, recorde-se que, quando o utilizador clica no botão [Envoyer], os parâmetros [txtNom, txtAge] são enviados para o URL [/personne1/main].

5.5.2. A vista [reponse]

Esta vista apresenta os valores introduzidos no formulário quando estes são válidos:

Image

É gerada pela página JSP [reponse.jsp]. O seu modelo é constituído pelos seguintes elementos:

  • [nom]: um nome (String) que se encontra 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">
<%
    // recuperam-se 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 por recuperar, na solicitação [request], os elementos [nom, age] do seu modelo. No funcionamento normal da aplicação, será o controlador [ServletPersonne] que irá construir este modelo.
  • Os elementos [nom, age] do modelo são, em seguida, apresentados nas linhas 20 e 24

Posteriormente, designamos esta vista como a vista [réponse(nom, age)].

5.5.3. A vista [erreurs]

Esta vista assinala os erros de introdução de dados no formulário:

Image

É gerada pela página JSP [erreurs.jsp]. O seu modelo é constituído pelos seguintes elementos:

  • [erreurs]: uma lista (ArrayList) de mensagens de erro que se encontra 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" %>

<%
// recuperam-se 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 por recuperar, na solicitação [request], o elemento [erreurs] do seu modelo. Este elemento representa um objeto do tipo ArrayList composto por elementos do tipo String. Estes elementos são mensagens de erro. No funcionamento normal da aplicação, será o controlador [ServletPersonne] que construirá este modelo.
  • linhas 18-22: apresentam a lista de mensagens de erro. Para tal, é necessário escrever código Java no corpo HTML da página. Deve-se procurar sempre reduzir este código ao mínimo, para não sobrecarregar o código HTML. Veremos mais adiante que existem soluções que permitem reduzir a quantidade de código Java nas páginas JSP.
  • linha 4: note-se a tag de importação dos pacotes necessários para a página JSP

Posteriormente, chamamos a esta vista a vista [erreurs(erreurs)].

5.6. Testes das vistas

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

  • é necessário poder aceder às mesmas diretamente na aplicação, sem passar pelo controlador
  • a página JSP tem de inicializar ela própria o modelo que, normalmente, seria construído pelo controlador

Para realizar estes testes, duplicamos as páginas JSP das vistas na pasta [/WebContent/JSP] do projeto Eclipse:

Image

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

[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-7 foram adicionadas para criar o modelo necessário à página das linhas 11-12.

[reponse.jsp]:


...

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

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

    
<html>
    <head>
...

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

[erreurs.jsp]:


...

<%
  // -- teste: cria-se 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, se ainda não o tiver feito, e, em seguida, solicite os seguintes URLs:

 

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

5.7. O controlador [ServletPersonne]

Resta escrever o núcleo da nossa aplicação web: o controlador. A sua função consiste em:

  • recuperar o pedido do cliente,
  • processar a ação solicitada pelo cliente,
  • enviar, em resposta, a vista adequada.

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

n.º
pedido
origem
processamento
1
[GET /personne1/main]
URL introduzida pelo utilizador
- enviar a vista [formulaire] vazia
2
[POST /personne1/main]
com os parâmetros [txtNom,
txtAge, ação] publicados
clicando no botão
[Envoyer] da vista
[formulaire]
- verificar os valores dos parâmetros [txtNom, txtAge]
- se estiverem incorretos, enviar a vista [erreurs(erreurs)]
- se estiverem corretos, enviar a vista [reponse(nom,age)]

A aplicação inicia quando o utilizador solicita o URL [/personne1/main]. De acordo com o ficheiro [web.xml] da aplicação (ver parágrafo 5.4), este pedido é processado por uma instância do tipo ServletPersonne, que descrevemos 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 vista 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 controlo 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 é feita uma solicitação do tipo GET à aplicação
  • linhas 42-46: o método [doPost] chamado pelo servidor web quando é feita uma solicitação do tipo POST à aplicação. Como se pode ver, esta será também 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 [txtNom, txtAge, action].

Passamos agora a descrever os diferentes métodos do controlador

5.7.2. Inicialização do controlador

Quando a classe do controlador é carregada pelo contentor de servlets, o seu método [init] é executado. Esta será a única vez. Uma vez carregado na memória, o controlador permanecerá lá e processará os pedidos dos diferentes clientes. Cada cliente é alvo de um thread de execução e, assim, os métodos do controlador são executados simultaneamente por diferentes threads. Recorde-se que, por esta razão, o controlador não deve ter campos que os seus métodos possam alterar. Os seus campos devem ser de leitura única. São inicializados pelo método [init], cuja função principal é precisamente essa. Este método tem, de facto, a particularidade de ser executado uma única vez por um único thread. Não há, portanto, problemas de acesso concorrente aos campos do controlador neste método. O método [init] tem como objetivo inicializar os objetos necessários à aplicação web e que serão partilhados em modo de leitura apenas por todas as threads de cliente. Estes objetos partilhados 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 {
         // recuperam-se os parâmetros de inicialização do servlet
        ServletConfig config = getServletConfig();
         // processamos os restantes 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 existe?
            if(valeur==null){
                 // regista-se o erro
                erreursInitialisation.add("Le paramètre ["+paramètres[i]+"] n'a pas été initialisé");
            }else{
                 // armazena-se o valor do parâmetro
                params.put(paramètres[i],valeur);
            }
             // a URL da vista [erreurs] tem um tratamento específico
            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 ficheiro [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, é armazenado com o seu valor no dicionário [params], inicialmente vazio (linha 10).
  • linhas 31-35: o parâmetro [urlErreurs] deve estar obrigatoriamente presente, pois indica o URL da vista [erreurs] capaz de apresentar eventuais erros de inicialização. Se não existir, a aplicação é interrompida através do lançamento de um [ServletException] (linha 33).

5.7.3. O método [doGet]

O método [doGet] processa tanto os pedidos GET como os POST no servlet, uma vez que o método [doPost] remete para o método [doGet]. O 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 decorreu a inicialização do servlet
        if (erreursInitialisation.size() != 0) {
             // passa-se o controlo 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 executar
        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")){
             // início da aplicação
            doInit(request,response);
            return;
        }
        if(méthode.equals("post") && action.equals("validationFormulaire")){
             // validação do formulário de introdução de dados
            doValidationFormulaire(request,response);
            return;
        }
         // outros casos
        doInit(request,response);
    }

     // envio
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
         // passa o controlo para o GET
        doGet(request, response);
    }
}
  • linhas 18-25: verifica-se se a lista de erros de inicialização está vazia. Se não for esse o caso, é apresentada a vista [erreurs(erreursInitialisation)], que irá sinalizar o(s) erro(s).

Para compreender este código, é necessário recordar o modelo da vista [erreurs]:

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

A vista [erreurs] espera um elemento-chave «erros» na consulta. O controlador cria esse elemento na linha 20.

  • linha 28: recupera-se o método [get] ou [post] que o cliente utilizou para efetuar a sua consulta
  • linha 30: recupera-se o valor do parâmetro [action] da consulta. Recorde-se que, na nossa aplicação, apenas a consulta n.º 2, [POST /personne1/main], possui o parâmetro [action]. Nesta consulta, este tem o valor [validationFormulaire].
  • linhas 31-34: se o parâmetro [action] não estiver presente, atribui-se-lhe o valor «init». Será este o caso na consulta 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 num 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 consulta n.º 1 [GET /personne1/main]. Nesta consulta, deve enviar a vista [formulaire(nom,age)] vazia. O 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 vista inicial
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // envia-se o formulário em branco
        request.setAttribute("nom", "");
        request.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
...
}
  • linhas 18-19: a vista [formulaire] é apresentada. Recorde-se o modelo esperado por esta vista:

<%
    // 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 vista [formulaire] é inicializado com cadeias de caracteres 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]. O 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{
         // recuperam-se os 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é");
         // Existem erros nos parâmetros?
        if (erreursAppel.size() != 0) {
             // envia-se 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 destes dois parâmetros
  • linhas 28-33: se algum dos parâmetros estiver incorreto, é apresentada a vista [erreurs(erreursAppel)]. Recorde-se o modelo desta vista:

<%
// recuperam-se 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, é apresentada a vista [reponse(nom,age)]. É necessário recordar o modelo da vista [reponse]:

<%
    // recuperam-se 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 isto, poderemos retomar os testes apresentados como exemplo no parágrafo 5.1. Poderemos adicionar mais testes. Por exemplo, podemos eliminar um dos parâmetros de configuração urlXXX em web.xml e observar o resultado. Assim, como se pode ver abaixo, um dos parâmetros foi colocado entre comentários em [web.xml]:


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

Iniciamos/reiniciamos o Tomcat e acedemos à URL [http://localhost:8080/personne1/main]. Obtemos a seguinte resposta:

Image