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:

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

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

5.2. Arquitetura da aplicação
A aplicação web [personne1] terá a seguinte arquitetura:

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:
A linha 1 especifica o URL solicitado, por exemplo:
É possível utilizar esta URL para especificar a ação a realizar. Podem ser utilizados vários métodos:
- 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.
- 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:
A linha 1 especifica o URL solicitado, por exemplo:
É 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:
Mas o parâmetro [action] também pode estar incluído nos parâmetros enviados (linha 15 acima), tal como em:
A seguir, utilizaremos estas diferentes técnicas para indicar ao controlador o que deve fazer:
- integrar o parâmetro action no URL solicitado:
- enviar o parâmetro action:
- utilizar o último elemento do URL como nome da ação:
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.

Não se manterá o contexto [mvc-personne-01] proposto por predefinição. Escolher-se-á [personne1], conforme indicado abaixo:

O resultado obtido é o seguinte:

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

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:

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

- 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:

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]:

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:
- 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:

tipo HTML | nome | função | |
<input type="text"> | txtNom | introdução do nome | |
<input type="text"> | txtAge | introdução da idade | |
<input type="submit"> | envio dos valores introduzidos para o servidor na URL /pessoa1/main | ||
<input type= "reset "> | para repor a página no estado em que foi inicialmente recebida pelo navegador | ||
<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:

É 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:

É 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:

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:
- 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:
- 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:
- 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:
- 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:
- 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:

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:





