Skip to content

5. Aplicação Web MVC [pessoa] – Versão 1

5.1. As vistas da aplicação

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

Image

Chamaremos a esta vista a vista [form]. Se as entradas estiverem corretas, são apresentadas numa vista que será chamada [response]:

Image

Se as entradas estiverem incorretas, os erros são apresentados numa vista chamada [erros]:

Image

5.2. Arquitetura da aplicação

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

Image

Trata-se de uma arquitetura de camada única: não existem camadas [business] ou [DAO], apenas uma camada [web]. [ServletPersonne] é o controlador da aplicação que trata de todos os pedidos dos clientes. Para responder a esses pedidos, utiliza uma das três vistas [form, response, errors].

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

Pedido 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

Esta URL pode ser utilizada para especificar a ação a ser executada. Podem ser utilizados vários métodos:

  1. Um parâmetro de URL especifica a ação, por exemplo [/app?action=add&id=4]. Aqui, o parâmetro [action] indica ao controlador qual a ação que está a ser solicitada.
  2. O último elemento da URL especifica a ação, por exemplo [/app/add?id=4]. Aqui, o último elemento da URL [/add] é utilizado pelo controlador para determinar a ação que deve executar.

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

Pedido POST

Neste caso, o fluxo HTTP é o seguinte:

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

Esta URL pode ser utilizada para especificar a ação a ser executada, tal como acontece com o GET. No caso do GET, o parâmetro [action] era incluído na URL. O mesmo pode acontecer aqui, como em:

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

No entanto, o parâmetro [action] também pode ser 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 estas diferentes técnicas para indicar ao controlador o que fazer:

  • incluir o parâmetro de ação no URL solicitado:
POST /appli?action=ajouter&id=4 HTTP/1.1
  • Envie o parâmetro de ação:
POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4
  • Utilize 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] para a aplicação web [personne1], siga o procedimento descrito na secção 3.1.

Image

Não vamos manter o contexto predefinido [mvc-personne-01]. Vamos escolher [personne1], conforme mostrado abaixo:

Image

O resultado é o seguinte:

Image

Se pretender alterar o contexto da aplicação web, utilize a opção [clique com o botão direito do rato no projeto -> Propriedades -> J2EE]:

Image

Introduza o novo contexto em [1].

Vamos criar uma subpasta [vues] na pasta [WEB-INF]: [clique com o botão direito do rato em WEB-INF -> Novo -> Pasta]:

O novo projeto tem agora o seguinte aspeto:

Image

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

Image

  • O controlador [ServletPersonne] encontra-se na pasta [src]
  • As páginas JSP para as visualizações [form, response, errors] encontram-se na pasta [WEB-INF/vues], o que impede o utilizador de aceder diretamente a elas, como se pode ver no exemplo abaixo:

Image

Vamos agora descrever os vários componentes da aplicação web [/personne1]. O leitor é convidado a criá-los à medida que lê.

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

O ficheiro web.xml para a aplicação /person1 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>
    <!--  Mapping ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  welcome files -->
    <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: a URL /main é tratada pelo servlet chamado person
  • linhas 10-13: o servlet chamado «person» é uma instância da classe [ServletPersonne]
  • linhas 14–19: definem um parâmetro de configuração chamado [urlResponse]. Esta é a URL da vista [response].
  • Linhas 20–25: definem um parâmetro de configuração chamado [urlErrors]. Esta é a URL da vista [errors].
  • Linhas 26–31: definem um parâmetro de configuração chamado [urlForm]. Esta é a URL da vista [form].
  • Linha 40: [index.jsp] será a página inicial da aplicação.

As URLs das páginas JSP para as vistas [form, response, errors] são definidas individualmente por um parâmetro de configuração. Isto permite que sejam movidas sem necessidade de recompilar a aplicação.

Quando o utilizador aceder ao URL [/person1], o ficheiro [index.jsp] enviará a resposta (ficheiro da página 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] redireciona simplesmente o cliente para o URL [/person1/main]. Assim, quando o navegador solicita o URL [/person1], [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/personne1/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 instruir o servidor a redirecionar para outro URL
  • Linha 4: O URL para o qual o navegador deve redirecionar

Após esta resposta, o navegador irá solicitar a URL [/person1/main] conforme indicado (linha 4). O ficheiro [web.xml] da aplicação [/person1] especifica que este pedido será tratado pelo controlador [ServletPersonne] (linhas 35–36).

5.5. O código da vista

Começamos a escrever a aplicação web criando as suas vistas. Estas ajudam a definir as necessidades do utilizador em termos de interface gráfica e podem ser testadas sem o controlador.

5.5.1. A vista [form]

Esta vista destina-se ao formulário utilizado para introduzir o nome e a idade:

Image

HTML
Tipo de HTML
nome
função
1
<input type="text">
txtName
Introduza o nome
2
<input type="text">
txtIdade
Introduza a idade
3
<input type="submit">
 
Envie os valores introduzidos para o servidor na URL /person1/main
4
<input type="reset">
 
para restaurar a página ao estado em que foi inicialmente recebida pelo navegador
5
<input type="button">
 
para limpar o conteúdo dos campos de entrada [1] e [2]

É gerado pela página JSP [formulaire.jsp]. O seu modelo é composto pelos seguintes elementos:

  • [name]: um nome (String) encontrado nos atributos da sessão associados à chave "name"
  • [age]: uma idade (String) encontrada nos atributos da sessão associados à chave "age"

A vista [form] é obtida quando o utilizador solicita o URL [/person1/main], ou seja, o URL do controlador [ServletPersonne]. O código da página JSP [formulaire.jsp] que gera a vista [form] é 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">
<%
    // on récupère les données du modèle
  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 os elementos [nome, idade] do seu modelo a partir do pedido. No funcionamento normal da aplicação, o controlador [ServletPersonne] irá construir este modelo.
  • linhas 18-38: a página JSP gera um formulário HTML (tag <form>)
  • linha 18: a tag <form> não possui o atributo action para especificar o URL que irá processar os valores enviados pelo botão [Submit] (linha 32). Os valores do formulário serão então enviados para a URL de onde o formulário foi obtido, ou seja, a URL do controlador [ServletPersonne]. Assim, este controlador é utilizado tanto para gerar o formulário vazio inicialmente solicitado por uma solicitação GET como para processar os dados introduzidos que lhe serão enviados através do botão [Submit].
  • Os valores enviados são os dos campos HTML [txtName] (linha 22), [txtAge] (linha 26) e [action] (linha 37). Este último parâmetro permitirá ao controlador saber o que precisa de fazer.
  • Quando o formulário é exibido pela primeira vez, os campos de entrada [txtName] e [txtAge] são inicializados com as variáveis [name] (linha 22) e [age] (linha 26), respetivamente. Estas variáveis obtêm os seus valores a partir dos atributos do pedido (linhas 6–7), que se sabe serem inicializados pelo servlet. É, portanto, o servlet que define o conteúdo inicial dos campos de entrada do formulário.
  • Linha 33: O botão [Reset] do tipo [reset] restaura o formulário para o estado em que se encontrava quando o navegador o recebeu.
  • linha 34: o botão [Limpar] do tipo [reset] não tem atualmente nenhuma função.

Daqui em diante, referir-nos-emos a esta vista como a vista [form(name, age)] quando quisermos especificar tanto o nome da vista como o seu modelo. Além disso, note que quando o utilizador clica no botão [Submit], os parâmetros [txtName, txtAge] são enviados para o URL [/person1/main].

5.5.2. A vista [response]

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 é composto pelos seguintes elementos:

  • [name]: um nome (String) encontrado nos atributos da sessão, associado à chave "name"
  • [age]: uma idade (String) que se encontra nos atributos da sessão, associada à chave "age"

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">
<%
    // on récupère les données du modèle
  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 os elementos [name, age] do seu modelo a partir do pedido. Durante o funcionamento normal da aplicação, o controlador [ServletPersonne] irá construir este modelo.
  • Os elementos do modelo [name, age] são então exibidos nas linhas 20 e 24

Posteriormente, referimo-nos a esta vista como a vista [response(name, age)].

5.5.3. A vista [errors]

Esta vista reporta erros de entrada no seguinte formato:

Image

É gerada pela página JSP [errors.jsp]. O seu modelo é composto pelos seguintes elementos:

  • [errors]: uma lista (ArrayList) de mensagens de erro que serão encontradas nos atributos da solicitação, associadas à chave "errors"

O código da página JSP [errors.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" %>
 
<%
// on récupère les données du modèle
  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");
        }//for
      %>
    </ul>
  </body>
</html>
 
  • linha 8: a página JSP começa por recuperar o elemento [errors] do seu modelo na solicitação. Este elemento representa um objeto ArrayList contendo elementos String. Estes elementos são mensagens de erro. Durante o funcionamento normal da aplicação, o controlador [ServletPersonne] irá construir este modelo.
  • Linhas 18–22: exibem a lista de mensagens de erro. Para tal, precisamos de escrever código Java no corpo HTML da página. Devemos sempre procurar manter isto ao mínimo para evitar sobrecarregar o código HTML. Veremos mais tarde que existem soluções para reduzir a quantidade de código Java nas páginas JSP.
  • Linha 4: Repare na tag de importação para os pacotes necessários à página JSP

Iremos referir-nos a esta vista como a vista [errors(errors)].

5.6. Testar vistas

É possível testar a validade das páginas JSP sem ter escrito o controlador. Para isso, duas condições devem ser cumpridas:

  • Deve ser possível solicitá-las diretamente a partir da aplicação, sem passar pelo controlador
  • a página JSP deve inicializar o próprio 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 modificadas da seguinte forma:

[form.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  request.setAttribute("nom","tintin");
  request.setAttribute("age","30");
%>
 
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
...

As linhas 3–7 foram adicionadas para criar o modelo exigido pelas linhas 11–12.

[reponse.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
%>
 
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
 
    
<html>
    <head>
...

As linhas 3–7 foram adicionadas para criar o modelo exigido pela página nas linhas 11–12.

[errors.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
%>
 
<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
 
    
<html>
    <head>
...

As linhas 3–9 foram adicionadas para criar o modelo exigido pela linha 13.

Inicie o Tomcat, se ainda não o fez, e, em seguida, solicite os seguintes URLs:

 

Obtemos 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 apenas escrever o núcleo da nossa aplicação web: o controlador. A sua função é:

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

O controlador [ServletPersonne] irá tratar das seguintes ações:

solicitar
solicitação
origem
processamento
1
[GET /pessoa1/mão]
URL introduzida pelo utilizador
- enviar a vista [form] vazia
2
[POST /person1/hand]
com os parâmetros [txtName,
txtAge, action]
clique no
[Submit] no
[formulário]
- verifique os valores dos parâmetros [txtName, txtAge]
- se estiverem incorretos, enviar a vista [errors(errors)]
- se estiverem corretos, envie a visualização [response(name,age)]

A aplicação inicia quando o utilizador solicita o URL [/person1/main]. De acordo com o ficheiro [web.xml] da aplicação (ver Secção 5.4), este pedido é tratado por uma instância da classe ServletPersonne, que iremos agora descrever.

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

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
    }

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

    // initial view display
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

    // form validation
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
...
    }

    // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        // we hand over to GET
        doGet(request, response);
    }
}
  • linhas 20–22: o método [init] executado quando o servlet é carregado pela primeira vez
  • linhas 25-28: o método [doGet] chamado pelo servidor web quando é feita uma solicitação GET à aplicação
  • linhas 42-46: o método [doPost] chamado pelo servidor web quando é feita uma solicitação POST à aplicação. Conforme mostrado, isto também será tratado pelo método [doGet] (linha 45).
  • linhas 31-33: o método [doInit] trata da ação n.º 1 [GET /person1/main]
  • Linhas 36–39: o método [doValidationFormulaire] trata da ação n.º 2 [POST /person1/main] com os parâmetros enviados [txtName, txtAge, action].

Vamos agora descrever os vários 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. Isto acontece apenas uma vez. Uma vez carregado na memória, o controlador permanece lá e processa pedidos de diferentes clientes. Cada cliente é tratado por um segmento de execução separado, pelo que os métodos do controlador são executados simultaneamente por diferentes segmentos. Note-se que, por esta razão, o controlador não deve ter quaisquer campos que os seus métodos possam modificar. Os seus campos devem ser de leitura apenas. São inicializados pelo método [init], que é a sua função principal. Este método tem a característica única de ser executado apenas uma vez por uma única thread. Portanto, não há problemas com o acesso simultâneo aos campos do controlador dentro deste método. O objetivo do método [init] é inicializar os objetos necessários à aplicação web, que serão partilhados em modo de leitura apenas por todas as threads do cliente. Estes objetos partilhados podem ser colocados em dois locais:

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

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

package istia.st.servlets.personne;

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

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
        // retrieve servlet initialization parameters
        ServletConfig config = getServletConfig();
        // other initialization parameters are processed
        String valeur=null;
        for(int i=0;i<paramètres.length;i++){
            // parameter value
            valeur=config.getInitParameter(paramètres[i]);
            // present parameter?
            if(valeur==null){
                // we note the error
                erreursInitialisation.add("Le paramètre ["+paramètres[i]+"] n'a pas été initialisé");
            }else{
                // parameter value is stored
                params.put(paramètres[i],valeur);
            }
            // the [errors] view url has a special treatment
            urlErreurs = config.getInitParameter("urlErreurs");
            if (urlErreurs == null)
                throw new ServletException(
                        "Le paramètre [urlErreurs] n'a pas été initialisé");
        }
    }
...
}
  • linha 16: a configuração da aplicação web é recuperada, ou seja, o conteúdo do ficheiro [web.xml]
  • linhas 19–29: recuperam os parâmetros de inicialização do servlet, cujos nomes estão definidos na matriz [parameters] na linha 9
  • linha 21: o valor do parâmetro é recuperado
  • linha 25: se o parâmetro estiver em falta, o erro é adicionado à lista de erros [initializationErrors], inicialmente vazia (linha 8).
  • Linha 28: Se o parâmetro estiver presente, é armazenado juntamente com o seu valor no dicionário [params], inicialmente vazio (linha 10).
  • linhas 31–35: o parâmetro [urlErrors] deve estar presente, pois especifica a URL da vista [errors] capaz de exibir quaisquer erros de inicialização. Se não existir, a aplicação é encerrada através do lançamento de uma [ServletException] (linha 33).

5.7.3. O método [doGet]

O método [doGet] trata tanto de pedidos GET como POST para o servlet, uma vez que o método [doPost] redireciona para o método [doGet]. O seu código é o seguinte:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    // instance parameters
    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 {

        // check how the servlet was initialized
        if (erreursInitialisation.size() != 0) {
            // we hand over to the error page
            request.setAttribute("erreurs", erreursInitialisation);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            // end
            return;
        }

        // retrieve the request sending method
        String méthode=request.getMethod().toLowerCase();
        // retrieve the action to be executed
        String action=request.getParameter("action");
        // action?
        if(action==null){
            action="init";
        }
        // execution action
        if(méthode.equals("get") && action.equals("init")){
            // start application
            doInit(request,response);
            return;
        }
        if(méthode.equals("post") && action.equals("validationFormulaire")){
            // validation of input form
            doValidationFormulaire(request,response);
            return;
        }
        // other cases
        doInit(request,response);
    }

    // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        // we hand over to GET
        doGet(request, response);
    }
}
  • Linhas 18–25: Verificamos se a lista de erros de inicialização está vazia. Se não estiver, exibimos a vista [errors(initializationErrors)], que irá relatar o(s) erro(s).

Para compreender este código, é necessário recordar o modelo de visualização [errors]:

<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

A vista [erros] espera uma chave chamada "erros" na solicitação. O controlador cria essa chave na linha 20.

  • Linha 28: Recuperamos o método [get] ou [post] que o cliente utilizou para efetuar a solicitação
  • linha 30: recuperamos o valor do parâmetro [action] da solicitação. Lembre-se de que, na nossa aplicação, apenas a solicitação n.º 2 [POST /person1/main] possui o parâmetro [action]. Nesta solicitação, ele tem o valor [validationFormulaire].
  • Linhas 31–34: Se o parâmetro [action] não estiver presente, atribuímos-lhe o valor "init". Este será o caso da solicitação inicial n.º 1 [GET /person1/main].
  • Linhas 36–40: Processamento da solicitação n.º 1 [GET /person1/main].
  • Linhas 41–45: Processamento da solicitação #2 [POST /person1/main].
  • Linha 47: Se nenhum dos dois casos anteriores se aplicar, procedemos como se estivéssemos no caso n.º 1

5.7.4. O método [doInit]

Este método trata da solicitação n.º 1 [GET /person1/main]. Para esta solicitação, deve retornar a vista vazia [form(name, age)]. O seu código é o seguinte:

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

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

...    
    // initial view display
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // send the empty form
        request.setAttribute("nom", "");
        request.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
...
}
  • linhas 18-19: a vista [form] é apresentada. Recorde o modelo esperado por esta vista:

<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
  • Linhas 16-17: O modelo [name, age] da vista [form] é inicializado com cadeias de caracteres vazias.

5.7.5. O método [doValidationForm]

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

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    // instance parameters
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();
...
    // form validation
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
        // parameters are retrieved
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
        // parameter verification
        ArrayList<String> erreursAppel = new ArrayList<String>();
        // name must be non-empty
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
        // age must be an integer >=0
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
        // errors in the parameters?
        if (erreursAppel.size() != 0) {
            // send error page
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(request, response);
            return;
        }
        // parameters are correct - send response page
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
...
}
  • linhas 16-17: os valores dos parâmetros «txtNom» e «txtAge» são recuperados do pedido do cliente.
  • linhas 19-26: verifica-se a validade destes dois parâmetros
  • linhas 28-33: se algum dos parâmetros estiver incorreto, é apresentada a vista [errors(callErrors)]. Recorde o modelo para esta vista:

<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
  • linhas 35-38: se os dois parâmetros recuperados "txtNom" e "txtAge" tiverem valores válidos, a vista [response(name, age)] é apresentada. Recorde o modelo para a vista [response]:

<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
 

5.8. Testes

Vamos incluir o projeto [mvc-personne-01] nas aplicações do Tomcat, seguindo o procedimento descrito na secção 3.3:

Image

Inicie o Tomcat. Depois de o fazer, podemos retomar os testes apresentados como exemplos na Secção 5.1. Podemos adicionar mais testes. Por exemplo, podemos remover um dos parâmetros de configuração urlXXX do ficheiro web.xml e ver o resultado. Conforme mostrado abaixo, um dos parâmetros está comentado no ficheiro [web.xml]:


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

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

Image