1. Informações gerais
O PDF do documento está disponível |AQUI|.
1.1. Objetivos
Neste artigo, exploraremos uma estrutura de desenvolvimento chamada Struts. O Jakarta Struts é um projeto da Apache Software Foundation (www.apache.org) concebido para fornecer uma estrutura padrão para o desenvolvimento de aplicações web Java baseadas na arquitetura MVC (Model-View-Controller).
1.2. O modelo MVC
O modelo MVC procura separar as camadas de apresentação, processamento e acesso aos dados. Uma aplicação web que siga este modelo será estruturada da seguinte forma:
![]() |
Esta arquitetura é designada por arquitetura de 3 camadas ou 3 níveis:
- a interface do utilizador é o V (a vista)
- a lógica da aplicação é o C (o controlador)
- as fontes de dados são o M (Modelo)
A interface do utilizador é frequentemente um navegador web, mas também pode ser uma aplicação autónoma que envia pedidos HTTP para o serviço web através da rede e formata os resultados que recebe. A lógica da aplicação consiste em scripts que processam os pedidos do utilizador. A fonte de dados é frequentemente uma base de dados, mas também pode ser simples ficheiros planos, um diretório LDAP, um serviço web remoto, etc. É do interesse do programador manter um elevado grau de independência entre estas três entidades, de modo a que, se uma delas mudar, as outras duas não tenham de mudar, ou apenas minimamente.
Ao aplicar este modelo com servlets e páginas JSP, resulta a seguinte arquitetura:
![]() |
No bloco [Lógica da Aplicação], distinguimos
- o servlet, que é o ponto de entrada da aplicação e também é chamado de controlador
- o bloco [Classes de Negócio], que contém as classes Java necessárias para a lógica da aplicação
- o bloco [Classes de Acesso a Dados], que contém as classes Java necessárias para recuperar os dados exigidos pelo servlet, frequentemente dados persistentes (base de dados, ficheiros, serviço web, etc.)
- o bloco de páginas JSP, que constitui as vistas da aplicação.
1.3. Uma abordagem de desenvolvimento MVC utilizando servlets e páginas JSP
Definimos uma abordagem para o desenvolvimento de aplicações web Java que segue o modelo MVC descrito acima. Iremos analisá-la aqui.
- Começaremos por definir todas as vistas da aplicação. Estas são as páginas web apresentadas ao utilizador. Por isso, adotaremos a perspetiva do utilizador ao projetar as vistas. Existem três tipos de vistas:
- o formulário de entrada, que é utilizado para obter informações do utilizador. Este formulário inclui normalmente um botão para enviar as informações introduzidas para o servidor.
- a página de resposta, que serve apenas para fornecer informações ao utilizador. Esta inclui frequentemente um link que permite ao utilizador continuar a utilizar a aplicação noutra página.
- a página mista: o servlet enviou ao cliente uma página contendo informações que gerou. Esta mesma página será utilizada pelo cliente para fornecer informações adicionais ao servlet.
- Cada vista irá gerar uma página JSP. Para cada uma delas:
- vamos projetar o layout da página
- determinaremos quais as partes da mesma que são dinâmicas:
- as informações destinadas ao utilizador, que devem ser fornecidas pelo servlet como parâmetros à página JSP
- os dados de entrada que devem ser transmitidos ao servlet para processamento. Estes dados devem fazer parte de um formulário HTML.
- Podemos esquematizar a E/S para cada vista
![]() |
- As entradas são os dados que o servlet deve fornecer à página JSP, seja na solicitação ou na sessão.
- As saídas são os dados que a página JSP deve fornecer ao servlet. Fazem parte de um formulário HTML, e o servlet irá recuperá-los utilizando uma operação como request.getParameter(...).
- Iremos escrever o código Java/JSP para cada vista. Na maioria das vezes, assumirá a seguinte forma:
<%@ page ... %> // importations de classes le plus souvent
<%!
// variables d'instance de la page JSP (=globales)
// nécessaire que si la page JSP a des méthodes partageant des variables (rare)
...
%>
<%
// récupération des données envoyées par la servlet
// soit dans la requête (request) soit dans la session (session)
...
%>
<html>
...
// on cherchera ici à minimiser le code java
</html>
- Podemos então passar aos testes iniciais. O método de implementação explicado abaixo é específico para o servidor Tomcat:
- O contexto da aplicação deve ser criado no ficheiro server.xml do Tomcat. Podemos começar por testar este contexto. Seja C este contexto e DC a pasta a ele associada. Iremos criar um ficheiro estático denominado test.html e colocá-lo na pasta DC. Após iniciar o Tomcat, iremos solicitar a URL http://localhost:8080/DC/test.html num navegador.
- Todas as páginas JSP podem ser testadas. Se uma página JSP se chamar formulaire.jsp, solicitaremos a URL http://localhost:8080/DC/formulaire.jsp num navegador. A página JSP espera valores do servlet que a chama. Aqui, estamos a chamá-la diretamente, pelo que não receberá os parâmetros esperados. Para garantir que o teste ainda é possível, iremos inicializar manualmente os parâmetros esperados na página JSP utilizando constantes. Estes testes iniciais verificam se as páginas JSP estão sintaticamente corretas.
- Em seguida, escrevemos o código do servlet. Este possui dois métodos distintos:
- o método init, que é utilizado para:
- recuperar os parâmetros de configuração da aplicação a partir do seu ficheiro web.xml
- criar, potencialmente, instâncias de classes de negócio que serão necessárias mais tarde
- tratar qualquer lista de erros de inicialização que serão devolvidos a futuros utilizadores da aplicação. Este tratamento de erros pode até incluir o envio de um e-mail ao administrador da aplicação para o notificar de uma avaria
- o método doGet ou doPost, dependendo de como o servlet recebe parâmetros dos seus clientes. Se o servlet processar vários formulários, é uma boa prática que cada formulário envie informações que o identifiquem de forma única. Isto pode ser feito utilizando um atributo oculto no formulário do tipo <input type="hidden" name="action" value="...">. O servlet pode começar por ler o valor deste parâmetro e, em seguida, delegar o processamento do pedido a um método interno privado responsável por tratar este tipo de pedido.
- Deve evitar, tanto quanto possível, colocar lógica de negócio no servlet. Não é para isso que ele foi concebido. O servlet atua como uma espécie de líder de equipa (controlador) que recebe pedidos dos seus clientes (clientes web) e faz com que sejam executados pelas entidades mais adequadas (as classes de negócio). Ao escrever o servlet, irá definir a interface das classes de negócio a criar (construtores, métodos). Isto aplica-se se estas classes de negócio precisarem de ser criadas. Se já existirem, então o servlet deve adaptar-se à interface existente.
- O código do servlet será compilado.
- Iremos escrever o esqueleto das classes de negócio exigidas pelo servlet. Por exemplo, se o servlet utilizar um objeto do tipo proxyArticles e esta classe tiver de possuir um método getCodes que retorne uma lista (ArrayList) de cadeias de caracteres, podemos inicialmente escrever simplesmente:
public ArrayList getCodes(){
String[] codes= {"code1","code2","code3"};
ArrayList aCodes=new ArrayList();
for(int i=0;i<codes.length;i++){
aCodes.add(codes[i]);
}
return aCodes;
}
- Podemos agora prosseguir com o teste do servlet.
- O ficheiro de configuração web.xml da aplicação deve ser criado. Deve conter todas as informações esperadas pelo método init do servlet (<init-param>). Além disso, definimos a URL através da qual o servlet principal será acedido (<servlet-mapping>).
- Todas as classes necessárias (servlet, classes de negócio) são colocadas em WEB-INF/classes.
- Todas as bibliotecas de classes necessárias (.jar) são colocadas em WEB-INF/lib. Estas bibliotecas podem conter classes de negócio, controladores JDBC, etc.
- As vistas JSP são colocadas na raiz da aplicação ou numa pasta dedicada. O mesmo se aplica a outros recursos (HTML, imagens, áudio, vídeos, etc.).
- Uma vez feito isto, a aplicação é testada e os erros iniciais são corrigidos. No final desta fase, a arquitetura da aplicação está operacional. Esta fase de testes pode ser complicada, uma vez que não existe nenhuma ferramenta de depuração disponível com o Tomcat. Para tal, o Tomcat teria de ser integrado numa ferramenta de desenvolvimento (JBuilder Developer, Sun One Studio, etc.). Pode utilizar instruções System.out.println("...."), que escrevem na consola do Tomcat. A primeira coisa a verificar é se o método init recupera com sucesso todos os dados do ficheiro web.xml. Para tal, podemos escrever os valores destes parâmetros na janela do Tomcat. Verificaremos da mesma forma se os métodos doGet e doPost recuperam corretamente os parâmetros dos vários formulários HTML da aplicação.
Escrevemos as classes de negócio exigidas pelo servlet. Isto envolve geralmente o desenvolvimento padrão de uma classe Java, que é normalmente independente de qualquer aplicação web. Será primeiro testada fora deste ambiente, por exemplo, com uma aplicação de consola. Uma vez escrita uma classe de negócio, podemos integrá-la na arquitetura de implementação da aplicação web e testar a sua integração adequada dentro dela. Este processo é repetido para cada classe de negócio.
1.4. A Abordagem de Desenvolvimento STRUTS
Os criadores da metodologia STRUTS procuraram definir um método de desenvolvimento padrão que seguisse a arquitetura MVC para aplicações web escritas em Java. Existem dois aspetos no projeto STRUTS:
- o método de desenvolvimento. Veremos que é bastante semelhante ao descrito acima para servlets e páginas JSP
- as ferramentas que nos permitem aplicar este método de desenvolvimento. Trata-se de bibliotecas de classes Java disponíveis no site da Apache Foundation (www.apache.org).
1.4.1. O método de desenvolvimento
A arquitetura MVC utilizada pelo STRUTS é a seguinte:
![]() |
- O controlador é o coração da aplicação. Todos os pedidos do cliente passam por ele. Trata-se de um servlet genérico fornecido pelo STRUTS. Em alguns casos, poderá ser necessário estendê-lo. Para casos simples, isso não é necessário. Este servlet genérico recupera as informações de que necessita a partir de um ficheiro, na maioria das vezes chamado struts-config.xml.
- Se a solicitação do cliente contiver parâmetros de formulário, estes são colocados num objeto Bean. Diz-se que uma classe é do tipo Bean se seguir regras de construção que discutiremos mais adiante. Os objetos Bean criados ao longo do tempo são armazenados na sessão ou solicitação do cliente. Esta configuração é configurável. Eles não precisam de ser recriados se já tiverem sido criados.
- No ficheiro de configuração struts-config.html, cada URL a ser processada pelo programa (e, portanto, não correspondente a uma vista JSP que possa ser solicitada diretamente) está associada a determinadas informações:
- o nome da classe do tipo Action responsável pelo processamento da solicitação. Aqui, mais uma vez, o objeto Action instanciado pode ser armazenado na sessão ou na solicitação.
- Se a URL solicitada for parametrizada (como quando um formulário é enviado ao controlador), é especificado o nome do bean responsável por armazenar os dados do formulário.
- Com estas informações fornecidas pelo seu ficheiro de configuração, ao receber uma solicitação de URL de um cliente, o controlador é capaz de determinar se um bean precisa de ser criado e qual. Uma vez instanciado, o bean pode verificar se os dados que armazenou — provenientes do formulário — são válidos ou não. Um método do bean chamado `validate` é chamado automaticamente pelo controlador. O bean é criado pelo programador. O programador, portanto, coloca o código que verifica a validade dos dados do formulário dentro do método validate. Se os dados forem considerados inválidos, o controlador não prosseguirá. Ele passará o controlo para uma vista cujo nome encontra no seu ficheiro de configuração. A interação está então concluída. Note-se que o programador pode optar por não verificar a validade do formulário. Isto também é feito no ficheiro struts-config.html. Neste caso, o controlador não chama o método validate do bean.
- Se os dados do bean estiverem corretos, ou se não houver validação, ou se não houver bean, o controlador passa o controlo para o objeto Action associado à URL. Faz isso chamando o método execute desse objeto, passando-lhe a referência ao bean que ele possa ter construído. É aqui que o programador faz o que precisa de ser feito: pode ser necessário chamar classes de negócio ou classes de acesso a dados. No final do processamento, o objeto Action devolve ao controlador o nome da vista que este deve enviar em resposta ao cliente.
- O controlador envia esta resposta. A interação com o cliente está concluída.
A metodologia de desenvolvimento STRUTS começa a tomar forma:
- Definição de vistas. Distinguimos entre vistas que são formulários e outras vistas.
- Cada vista de formulário gera uma definição no ficheiro struts-config.xml. As seguintes informações são definidas nesse ficheiro:
- o nome da classe Bean que irá conter os dados do formulário, bem como uma indicação sobre se os dados devem ser validados ou não. Se a validação for necessária e os dados forem considerados inválidos, deve ser especificada a vista a ser enviada de volta ao cliente neste caso.
- O nome da classe Action responsável pelo processamento do formulário.
- os nomes de todas as vistas que podem ser enviadas ao cliente assim que o pedido for processado. A classe Action selecionará uma delas com base no resultado do processamento.
- Cada vista corresponde a uma página JSP. Veremos que nas vistas — particularmente nas vistas de formulário — por vezes utilizamos uma biblioteca de tags específicas do Struts.
- Cada vista de formulário gera uma definição no ficheiro struts-config.xml. As seguintes informações são definidas nesse ficheiro:
- Escrever as classes JavaBean correspondentes às vistas de formulário
- Escrever as classes Action responsáveis pelo processamento dos formulários
- Escrever quaisquer classes de lógica de negócio ou de acesso a dados
1.4.2. Ferramentas de desenvolvimento STRUTS
O projeto Struts é um dos projetos da Apache Software Foundation. Vários destes projetos estão agrupados sob o nome Jakarta e estão disponíveis no URL http://jakarta.apache.org:

Recomenda-se que leia esta página. Muitos dos projetos são de interesse para os programadores Java. Se seguirmos o link do Struts acima, chegamos à página inicial do projeto:

Aqui também é recomendável que leia a página inicial. Para descarregar as bibliotecas Java do Struts, siga o link «Binaries» acima:

Para utilizadores do Windows, utilize o link 1.1.zip; para utilizadores do Unix, utilize o link 1.1.tar.gz (novembro de 2003). Depois de descompactar o ficheiro 1.1.zip, irá ver a seguinte estrutura de diretórios:

Esta estrutura de diretórios contém as bibliotecas de classes Java necessárias para o desenvolvimento com Struts. Estas estão armazenadas em ficheiros .jar ou .war, que são semelhantes aos ficheiros .zip. Podem ser abertas utilizando os mesmos utilitários. A maioria das bibliotecas necessárias encontra-se na pasta lib acima:

Para além das bibliotecas de classes .jar, existem ficheiros .dtd (Document Type Definition) que contêm regras de validação para ficheiros XML. Um ficheiro XML pode referenciar um ficheiro DTD deste tipo no seu conteúdo. O programa (denominado analisador) que analisa o conteúdo do ficheiro XML utilizará as regras de validação encontradas no ficheiro DTD referenciado para determinar se o ficheiro XML está sintaticamente correto. Por exemplo, o ficheiro struts-config_1_1.dtd define as regras para a construção do ficheiro de configuração struts-config.xml para a versão 1.1 do Struts.
Vamos agora ver onde colocar os vários elementos da estrutura de diretórios do Struts para implementar uma aplicação Struts no servidor Tomcat.
1.5. Implantação de uma aplicação Struts
Uma aplicação Struts é uma aplicação web como qualquer outra. Segue, portanto, as regras de implementação do contentor no qual é executada. Aqui, uma aplicação — a que chamaremos strutspersonne — será executada por um servidor Tomcat versão 4.x. O procedimento de implementação para o Tomcat versão 5.x está incluído no apêndice. Aqui, seguiremos as regras de implementação para o Tomcat 4.x:
- Definimos o contexto strutspersonne no ficheiro de configuração server.xml do Tomcat:
Depois de fazer isto, reiniciamos o Tomcat, se necessário, para que ele tenha em conta o novo contexto. Podemos verificar a validade do contexto solicitando o URL http://localhost:8080/strutspersonne:

Se não obtivermos uma página de erro, o contexto está correto.
- Criamos a subpasta WEB-INF na pasta física associada ao contexto strutspersonne.
- Na pasta WEB-INF da aplicação, definimos o ficheiro de configuração web.xml da aplicação:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
- A classe controladora (servlet) da aplicação é uma classe Struts predefinida chamada ActionServlet. Está localizada no ficheiro struts.jar. Para garantir que o Tomcat consiga encontrar esta classe, colocaremos o struts.jar na pasta <tomcat>\common\lib, que é uma das pastas que o Tomcat pesquisa quando procura classes. Na verdade, vamos colocar todos os ficheiros .jar encontrados na pasta <struts>\lib nesse local, sendo que <struts> é a pasta raiz da árvore de diretórios do Struts.

- Colocaremos também os ficheiros struts-el.jar e jstl.jar localizados em <struts>\contrib\struts-el\lib:

- Aqui, temos acesso ao servidor web. Nem sempre é esse o caso. Se implementar uma aplicação web/Java num contentor web que não administra, é melhor que a aplicação inclua todas as bibliotecas de que necessita. Estas devem então ser colocadas na pasta WEB-INF/lib, que terá de criar.
- Observámos que o controlador requer determinadas informações, que normalmente encontra num ficheiro struts-config.xml localizado na mesma pasta que o web.xml. Na verdade, o nome deste ficheiro é configurável. É o parâmetro config, mencionado acima, que define este nome.
- A tag <servlet-mapping> indica que o controlador será acedido através de todos os URLs que terminem com o sufixo .do. Este mapeamento é exigido pelo Struts. Estes URLs serão então filtrados pelo controlador, que só aceitará os URLs declarados no seu ficheiro de configuração struts-config.xml
Por enquanto, o nosso ficheiro web.xml é suficiente.
- Vamos solicitar a URL /main.do da aplicação strutspersonne. De acordo com o ficheiro web.xml anterior, esta URL será, portanto, passada para o servlet org.apache.struts.action. A classe ActionServlet será instanciada e o seu método init chamado. Este método tenta ler o ficheiro de configuração definido pelo parâmetro config. Este ficheiro deve, portanto, existir. Criamos o seguinte ficheiro struts-config.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<action-mappings>
<action
path="/main"
parameter="/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
</struts-config>
Note que o ficheiro DTD para struts-config.xml não é o mesmo que o de web.xml, indicando que não têm a mesma estrutura. Para cada URL que o controlador deve processar, precisamos de definir uma tag <action>. Esta tag é utilizada para indicar ao controlador o que fazer quando recebe um pedido para essa URL. Aqui, especificamos os seguintes elementos:
- path="/main": define o nome da URL configurada pela tag <action>. O sufixo .do é implícito.
- type="org.apache.struts.actions.ForwardAction": define o nome da classe Action que deve tratar a solicitação. Aqui, usamos uma classe Action predefinida no Struts. Ela não faz nada por si só e encaminha a solicitação do cliente para a URL especificada no atributo parameter.
- parameter="/main.html": o nome da URL para a qual a solicitação deve ser encaminhada. Aqui, trata-se de um ficheiro HTML estático.
Em resumo, quando o utilizador solicitar a URL /main.do, será redirecionado para a URL /main.html.
- O ficheiro main.html terá o seguinte conteúdo:
<html>
<head>
<title>Application strutspersonne</title>
</head>
<body>
Application strutspersonne active ....
</body>
</html>
Este ficheiro está localizado na pasta da aplicação strutspersonne/views:

Pode ser acedido diretamente através do URL http://localhost:8080/strutspersonne/main.html:

Aqui, o controlador Struts da aplicação não interveio, uma vez que só intervém quando é solicitada uma URL do tipo *.do. No entanto, neste caso, solicitámos a URL /vues/main.html.
- O ficheiro struts-config.xml criado anteriormente deve ser colocado na mesma pasta WEB-INF que o ficheiro web.xml:

- Vamos agora verificar se o controlador da aplicação strutspersonne está a funcionar corretamente, solicitando o URL /main.do após reiniciar o Tomcat, se necessário.

Neste caso, o controlador Struts interveio, uma vez que solicitámos um URL do tipo *.do. Conseguimos aceder à página esperada (main.html). Dispomos agora dos componentes básicos para que a nossa aplicação funcione: o contexto strutspersonne, os ficheiros de configuração web.xml e struts-config.xml e as bibliotecas Struts.
O que teria acontecido se tivéssemos solicitado uma URL como /toto.do? De acordo com o ficheiro web.xml da aplicação strutspersonne, o controlador Struts é chamado para tratá-la. Em seguida, verifica o seu ficheiro de configuração struts-config.html e não encontra nenhuma configuração para a URL /toto. O que faz então? Vamos experimentar:

Recebemos uma página de erro, o que parece normal. Podemos agora avançar para a criação de uma aplicação.



