Skip to content

7. Aplicativo web MVC [personne] – versão 3


Leituras recomendadas em [ref1]: capítulo 9


7.1. Introduction

Propomos adicionar código JavaScript às páginas HTML enviadas ao navegador. É o próprio navegador que executa o código JavaScript incorporado na página que ele exibe. Essa tecnologia é independente daquela utilizada pelo servidor web para gerar o documento HTML (Java/servlets/JSP, ASP.NET, ASP, PHP, Perl, Python, ...).

[formulaire.jsp]

A visualização resultante desta página terá a seguinte aparência:

Image

Os botões cujo texto está emoldurado utilizam código JavaScript incorporado na página HTML:

Texto
Tipo HTML
Função
Submit
<submit>
desempenha a função do botão [Envoyer] das versões anteriores: envia os valores inseridos ao controlador
[Envoyer]
<button>
novo botão – verifica localmente a validade dos dados inseridos antes de enviá-los ao controlador
Rétablir
<reset>
restaura o formulário ao estado em que foi recebido inicialmente pelo navegador
[Effacer]
<button>
apaga o conteúdo dos dois campos de preenchimento

Aqui está um exemplo de uso dos botões [Envoyer] e [Effacer]:

Também utilizaremos código JavaScript para gerenciar o link [Retour au formulaire] das visualizações [erreurs] e [réponse]. Tomemos como exemplo a visualização [réponse]:

1

A diferença está na URL exibida em [1]. Na versão anterior, ela era:

[http://localhost:8080/pessoa2/main?action=retourFormulaire]

Aqui, a ação não faz mais parte da URL, pois será enviada por um POST em vez de um GET. Essa modificação fará com que a única URL exibida pelo navegador seja [http://localhost:8080/personne3/main], independentemente da ação solicitada.

7.2. O projeto Eclipse

Para criar o projeto Eclipse [mvc-personne-03] do aplicativo web [/personne3], duplicaremos o projeto [mvc-personne-02] seguindo o procedimento descrito no parágrafo 6.2, página 78.

7.3. Configuração da aplicação web [personne3]

O arquivo web.xml do aplicativo /personne3 é 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-03</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>
        <init-param>
            <param-name>lienRetourFormulaire</param-name>
            <param-value>
                Retour au formulaire
            </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>

Este arquivo é idêntico ao da versão anterior, exceto por alguns detalhes:

  • linha 6: o nome de exibição da aplicação web mudou para [mvc-personne-03]

O parâmetro [urlControleur] foi removido. Na versão anterior, ele servia para definir o destino do POST da visualização [formulaire]. Nesta nova versão, o destino será a string vazia, c.a.d. A URL exibida pelo navegador. Explicamos que ela continuaria sendo [http://localhost:8080/personne3/main], que é a que precisamos para o POST da visualização [formulaire].

A página inicial [index.jsp] muda:


<%@ 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("/personne3/main");
%>
  • linha 5: a página [index.jsp] redireciona o cliente para a URL do controlador [ServletPersonne] do aplicativo [/personne3].

7.4. O código das visualizações

7.4.1. A visualização [formulaire]

Essa visualização ficou da seguinte forma:

Image

Ela é gerada pela página JSP [formulaire.jsp] a seguir:


<%@ 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) session.getAttribute("nom");
            String age = (String) session.getAttribute("age");
%>


<html>
  <head>
    <title>Personne - formulaire</title>
    <script language="javascript">
        // -------------------------------
        function effacer(){
          // limpa-se os campos de preenchimento
          with(document.frmPersonne){
            txtNom.value="";
            txtAge.value="";
          }//com
        }//apagar
        // -------------------------------      
        function envoyer(){
          // verificação dos parâmetros antes do envio
          with(document.frmPersonne){
            // o nome não deve estar vazio
            champs=/^\s*$/.exec(txtNom.value);
            if(champs!=null){
              // o nome está vazio
              alert("Vous devez indiquer un nom");
              txtNom.value="";
              txtNom.focus();
              // retorno à interface visual
              return;
            }//if
             // a idade deve ser um número inteiro positivo
            champs=/^\s*\d+\s*$/.exec(txtAge.value);
            if(champs==null){
              // a idade está incorreta
              alert("Age incorrect");
              txtAge.focus();
              // voltar à interface visual
              return;
            }//if
             // os parâmetros estão corretos — eles são enviados ao servidor
            submit();
          }//com
        }//enviar
      </script>
  </head>
  <body>
    <center>
      <h2>Personne - formulaire</h2>
      <hr>
      <form name="frmPersonne" 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="Submit"></td>
            <td><input type="button" value="[Envoyer]" onclick="envoyer()"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" value="[Effacer]" onclick="effacer()"></td>
          </tr>
        </table>
        <input type="hidden" name="action" value="validationFormulaire">
      </form>
    </center>
  </body>
</html>


Novidades:

  • linha 56: o formulário tem o nome [frmPersonne]. Esse nome será utilizado no código JavaScript. Observe-se a ausência do atributo [action], o que faz com que o formulário [frmPersonne] seja enviado para a URL exibida pelo navegador.
  • linha 70: o botão [Submit] desempenha a função do botão [Envoyer] das versões anteriores
  • linha 71: um clique no botão [Envoyer], do tipo [Button], executa a função JavaScript [envoyer] definida na linha 24
  • linha 72: o botão [Rétablir] não mudou de função
  • linha 73: ao clicar no botão [Effacer], do tipo [Button], é executada a função JavaScript [effacer], definida na linha 16

Antes de comentar o código JavaScript, vamos relembrar algumas noções:

O JavaScript gerencia a página exibida e seu conteúdo como uma árvore de objetos cuja raiz é o objeto [document]. Neste documento, pode haver um ou mais formulários. [document.frmPersonne] designa o formulário de nome [frmPersonne], definido na linha 56. Esse formulário também contém objetos. Os campos de entrada fazem parte dele. Assim, [document.frmPersonne.txtNom] designa o objeto imagem do campo de entrada HTML, definido na linha 60. O objeto [txtNom] possui diversas propriedades, entre as quais a propriedade [value], que designa o conteúdo do campo de entrada. Assim, [document.frmPersonne.txtNom.value] designa o conteúdo do campo de entrada [txtNom].

  • linhas 16-22: a função JavaScript [effacer] insere uma string vazia nos campos de entrada [txtNom, txtAge].
  • linhas 24-49: a função JavaScript [envoyer] verifica a validade dos valores dos campos de entrada [txtNom, txtAge] antes de enviá-los. Para isso, ela utiliza expressões regulares.
  • linha 28: verifica se o valor do campo de entrada [txtNom] corresponde ao padrão /s*, que significa 0 ou mais espaços. Se a resposta for sim, isso significa que o usuário não informou um nome. Se houver correspondência com o padrão, a variável champs terá um valor diferente do ponteiro null; caso contrário, ela terá o valor null.
  • linha 29: se houver correspondência com o modelo
  • linha 30: exibe-se uma mensagem para o usuário
  • linha 32: insere-se a string vazia no campo [txtNom] (poderia haver uma sequência de espaços)
  • linha 33: posiciona-se o cursor piscando no campo [txtNom]
  • linha 34: a função é interrompida. Assim, não há envio dos valores inseridos para o servidor no campo POST.
  • linhas 38-45: segue-se um procedimento semelhante com o campo [txtAge]
  • linha 47: se chegarmos até aqui, significa que os valores inseridos estão corretos. Enviamos (submit) então o formulário [frmPersonne] para o servidor web. Tudo ocorre então como se tivéssemos clicado no botão com a legenda [Submit].

7.4.2. A visualização [reponse]

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

Em comparação com a versão anterior, a novidade só aparece quando se utiliza o link [Retour au formulaire] da visualização [réponse]:

A diferença está na URL exibida em [1]. Na versão anterior, ela era:

[http://localhost:8080/pessoa2/main?action=retourFormulaire]

Aqui, a ação não faz mais parte da URL, pois será enviada por um POST em vez de um GET. A nova página JSP [reponse.jsp] é lqqqaaaaaaaaaqqAAAaaa

a seguir:


<%@ 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");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>


<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>      
    <br>
    <form name="frmPersonne" method="post">
      <input type="hidden" name="action" value="retourFormulaire">
    </form>
    <a href="javascript:document.frmPersonne.submit();">
      <%= lienRetourFormulaire %>
    </a>
  </body>
</html>

Novidades:

  • linhas 35-37: o link [Retour au formulaire] contém JavaScript. Ao clicar nesse link, o código JavaScript do atributo [href] é executado. Como vimos na análise de [formulaire.jsp], sabemos que esse código envia os valores dos campos do tipo <input>, <select>, ... do formulário [frmPersonne].
  • linhas 32-34: definem o formulário [frmPersonne]. Este possui apenas um campo do tipo <input type="hidden" ...>, ou seja, um campo oculto. Esse campo [action] serve para transmitir ao controlador o nome da ação a ser executada, neste caso, [retourFormulaire].

7.4.3. A visualização [erreurs]

Essa visualização sinaliza os erros de preenchimento no formulário. A modificação feita é a mesma da visualização [réponse]:

A diferença está na URL exibida em [1]. Na versão anterior, ela era:

[http://localhost:8080/pessoa2/main?action=retourFormulaire]

Aqui, a ação não faz mais parte da URL, pois será enviada por um POST em vez de um GET. A nova página JSP [reponse.jsp] a seguir:


<%@ 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" %>

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


<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>
    <br>
    <form name="frmPersonne" method="post">
      <input type="hidden" name="action" value="retourFormulaire">
    </form>
    <a href="javascript:document.frmPersonne.submit();">
      <%= lienRetourFormulaire %>
    </a>
  </body>
</html>

Novidades:

  • linhas 30-32: o novo tratamento do clique no link. As explicações fornecidas a esse respeito no estudo de [réponse.jsp] também se aplicam aqui.

7.5. Testes das visualizações

Para realizar os testes das visualizações anteriores, duplicamos suas páginas JSP 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
  session.setAttribute("nom","tintin");
  session.setAttribute("age","30");
%>

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

As linhas 4-5 foram adicionadas para criar o modelo necessário para a página das linhas 9-10.

[reponse.jsp]:


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

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

As linhas 4 a 6 foram adicionadas para criar o modelo necessário para a página das linhas 11 a 13.

[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);
  request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>

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

As linhas 4 a 8 foram adicionadas para criar o modelo necessário para a página das linhas 13 a 14.

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

 

Estamos obtendo as visualizações esperadas.

7.6. O controlador [ServletPersonne]

O controlador [ServletPersonne] do aplicativo web [/personne3] processará as seguintes ações:

n.º
solicitação
origem
processamento
1
[GET /personne3/main]
URL digitada pelo usuário
- enviar a visualização [formulaire] vazia
2
[POST /personne3/main]
com parâmetros [txtNom,
txtAge, action=validationFormulaire]
enviados
ao clicar no botão
[Envoyer] da visualização
[formulaire]
- verifique 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)]
3
[POST /personne3/main]
com parâmetros
[action=retourFormulaire]
hospedados
clique no link [Voltar ao
formulário] nas visualizações
[réponse] e [erreurs].
- enviar a visualização [formulaire] pré-preenchida com os últimos valores inseridos

Portanto, temos uma nova ação a ser processada: [POST /personne3/main] com o parâmetro enviado [action=retourFormulaire], em substituição à antiga ação [GET /personne3/main?action=retourFormulaire].

7.6.1. Estrutura do controlador

A estrutura do controlador [ServletPersonne] é idêntica à da versão anterior.

package istia.st.servlets.personne;

...
import javax.servlet.http.HttpSession;

@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","lienRetourFormulaire"};
    private Map params=new HashMap<String,String>();
    ...

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

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

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

     // exibição do formulário pré-preenchido
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        ...
    }

     // validação do formulário
    void doValidationFormulaire(HttpServletRequest request,
    ...
    }

     // envio
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    ...
    }
}

Novidades:

  • na linha 11, a tabela [paramètres] não contém mais o parâmetro [urlControleur], que foi removido do arquivo [web.xml].

Os métodos [init, doValidationFormulaire] permanecem inalterados. Os métodos [doGet, doInit, doRetourFormulaire] sofrem pequenas alterações.

7.6.2. O método [doGet]

O método [doGet] deve processar a ação [POST /personne3/main] com o parâmetro enviado [action=retourFormulaire]:

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

...
        if(méthode.equals("post") && action.equals("retourFormulaire")){
             // retorno ao formulário de preenchimento
            doRetourFormulaire(request,response);
            return;
        }
         // outros casos
        doInit(request,response);
    }
  • linhas 6-9: processamento da ação [POST /personne3/main] com o parâmetro enviado [action=retourFormulaire]

7.6.3. O método [doInit]

Este método processa a solicitação nº 1 [GET /personne3/main]. Seu código é o seguinte:

             // exibição do formulário vazio
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // recuperação da sessão do usuário
        HttpSession session = request.getSession(true);        
         // envio do formulário vazio
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

A novidade é que a visualização [formulaire] exibida na linha 8 não possui mais o elemento [action] em seu modelo.

7.6.4. O método [doRetourFormulaire]

Este método processa a solicitação nº 1 [POST /personne3/main] com [action=retourFormulaire] nos elementos postados. Seu código é o seguinte:

     // exibição do formulário pré-preenchido
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // recuperação da sessão do usuário
        HttpSession session = request.getSession(true);        
         // o nome está presente na sessão?
        String nom = (String) session.getAttribute("nom");
        if (nom == null)
            session.setAttribute("nom", "");
         // A idade está na sessão?
        String age = (String) session.getAttribute("age");
        if (age == null)
            session.setAttribute("age", "");
         // exibição do formulário
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

A novidade é que a visualização [formulaire] exibida na linha 14 não contém mais o elemento [action] em seu modelo.

7.7. Tests

Inicie ou reinicie o Tomcat após ter integrado o projeto Eclipse [personne-mvc-03] nele. Acesse a URL [http://localhost:8080/personne3] e, em seguida, retome os testes apresentados como exemplo no parágrafo 7.1.