• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Tutorial struts
 

Tutorial struts

on

  • 1,725 views

 

Statistics

Views

Total Views
1,725
Views on SlideShare
613
Embed Views
1,112

Actions

Likes
0
Downloads
26
Comments
0

4 Embeds 1,112

http://www.portalgsti.com.br 1031
http://feeds.feedburner.com 78
http://portalgstinovolayout.blogspot.com.br 2
http://portalgsti.wordpress.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Tutorial struts Tutorial struts Document Transcript

    • Tutorial - Struts FrameworkWelington B. Souza wbsouza@yahoo.com.brIntroduçãoO objetivo deste tutorial é dar uma visão geral sobre o funcionamento da Struts Framework. Aqui você iráaprender o necessário para começar a desenvolver uma aplicação web usando a Struts. Embora estaframework implemente o padrão MVC, isso não quer dizer que vamos seguir a risca as explicações de cadacamada, mas sim expondo o conteúdo teórico dependendo da necessidade do tutorial, visando a facilidadeno entendimento dos conceitos à medida em que eles forem necessários.A Struts Framework é um projeto open source mantido pela Apache Software Foundation. É umaimplementação do design pattern MVC (Model-View-Controller) para aplicações java com internet. O objetivodo pattern MVC é separar de maneira clara a camada de apresentação (View) da camada de Negócio(Model).A arquitetura MVC - Model-View-Controller (Modelo-Visualização-Controle) é um padrão que separa demaneira independente o Modelo, que representa os objetos de negócio (Model) da camada de apresentação,que representa a interface com o usuário ou outro sistema (View); e o Controle de fluxo da aplicação(Controller).Figura 1 - O Padrão MVCA Struts Foi escrita por Craig McClanahan em Maio de 2000, e desde então vem sendo melhorado pelacomunidade open-source. Foi desenvolvida com o objetivo de fornecer uma framework para facilitar odesenvolvimento de aplicações para web.Motivos utilizar a Struts Framework • Se tornou um padrão de mercado; • Garantia de que alguém (Apache Group) irá manter a framework (correção de bugs e novos releases); • Integração com a maioria das IDEs de mercado • Não reinventar a roda, focando os seus esforços em regras de negócio; • Separar a camada de negócio da camada de apresentação; • Já incorpora diversos design patterns • Criação de aplicações padronizadas, facilitando a manutenção; • Criação de Aplicações Internacionalizadas; • Possibilidade de gerar a saída de acordo com o dispositivo usado (HTML, SHTML, WML, etc); • Aumentar a produtividade
    • LicençaA Struts está disponível sobre a licença "free-to-use-license" da Apache Software Foundation (vejahttp://www.apache.org/LICENSE-1.1).Detalhes do funcionamentoFigura 2 - Fluxo de Navegação nos componentes da Struts 1. O usuário faz uma solicitação através de uma url no browser. Ex: http://localhost:8080/cadastro/listUsers.do. Note que no final da url tem um .do que será usado para invocar (na verdade mapear) o servlet controller da struts. 2. Se for a primeira solicitação que o container recebeu para esta aplicação, ele irá invocar o metodo init() da ActionServlet (controller da Struts) e irá carregar as configurações do arquivo struts- config.xml em estruturas de dados na memória. Vale lembrar que esta passagem só será executada uma única vez, pois nas solicitações subsequentes, a servlet consulta estas estruturas na memória para decidir o fluxo a ser seguido. 3. Baseado no fluxo definido no arquivo struts-config.xml, e que neste momento já se encntra carregado em estruturas na memória, o ActionSerlet identificará qual o ActionForm (classe para a validação dos dados) irá invocar. A classe ActionForm através do método validate irá verificar a integridade dos dados que foram recebidos na solicitação que vem do browser. 4. O controle da aplicação é retomado pelo ActionServlet, que verifica o resultado da verificação do ActionForm. • Se faltou alguma coisa (campo não preenchido, valor inválido, etc), o usuário recebe um formulário html (geralmente o mesmo que fez a solicitação), informando o motivo do não atendimento da solicitação, para que o usuário possa preencher corretamente os dados para fazer uma nova solicitação. • Se não faltou nenhuma informação, ou seja, todos os dados foram enviados corretamente, o controller passa para o proximo passo (Action). 5. O ActionServlet, baseado no fluxo da aplicação (estruturas já carregadas em memória) invoca uma classe Action. A classe Action passará pelo método execute que irá delegar a requisição para a camada de negócio. 6. A camada de negócio irá executar algum processo (geralmente popular um bean, ou uma coleção). O resultado da execução deste processo (objetos já populados) será usado na camada de
    • apresentação para exibir os dados. 7. Quando o controle do fluxo da aplicação votar ao Action que invocou o processo da camada de negócio, será analisado o resultado, e definido qual o mapa adotado para o fluxo da aplicação. Neste ponto, os objetos que foram populados na camada de negócio serão "atachados" como atributos na seção do usuário. 8. Baseado no mapeamento feito pelo o Action, o Controller faz um forward para o JSP para apresentar os dados. 9. Na camada de apresentação (View), os objetos que foram setados como atributos da sessão do usuário serão consultados para montar o html para o browser. 10.Chega o html da resposta requisitada pelo usuário.O Controller já vem implementado na Struts, embora, caso seja possível estendê-lo a fim de adicionarfuncionalidade. O fluxo da aplicação é programado em um arquivo XML através das ações que serãoexecutadas. As ações são classes base implementadas pela framework seguindo o padrão MVC. Assimdevemos estendê-las a fim de adicionar a funcionalidade desejada.A geração da interface é feita através de custom tags, também já implementadas pela Struts, evitando assimo uso de Scriptlets (códigos java entre <%> e <%>), deixando o código JSP mais limpo e fácil de manter.Baixando e instalando a documentaçãoA Struts Framework pode ser baixada em http://jakarta.apache.org/struts. Neste tutorial vamos usar aversão 1.1, pois incorpora uma série de melhorias em relação a versão anterior, e já temos uma versãoestável para produção.Após o download, descompactar o arquivo; dentro do diretório descompactado,possui um diretório chamado webapps contendo as aplicações exemplo. Se você tiver usando o TomCat ououtro WebContainer, copie o arquivo struts-documentation.war, para o diretório <webapps> do seucontainer.Neste ponto a documentação da Struts já se enconrtra instalada na sua máquina.Para acessá-la vá parahttp://localhost:8080/struts-documentation.Projeto do TutorialPara entender melhor o funcionamento, vamos fazer uma aplicação prática. Desenvolveremos um cadastrode Usuários com inclusão, alteração e exclusão. Portanto, um nome sugestivo para a nossa aplicação web é"cadastro"Para criar uma nova aplicação com a Struts Framework, devemos seguir os seguintes passos: • Vá para a linha de comando do seu sistema operacional; • Vá para o diretório onde a Struts framework foi descompactada, e entre no diretório webapps; • Faça a seguinte sequencia de comandos: mkdir cadastro cd cadastro jar -xvf ../struts-blank.war • Agora temos uma aplicação web (em branco) baseada na template da Struts para começar a brincar. • Mova este diretório para o local que mais lhe convier, uma vez que os fontes da sua aplicação ficarão abaixo desta estrutura.Estrutura de diretórios da aplicação web com Struts:RootDir|+-- META-INF| Contém meta informação. Usado pelo Web Container, utilitários, etc.|+-- WEB-INF | +-- classes | | Este diretório contém as classes java da sua aplicação (camada denegócio). | | | +-- java | | | +-- resources
    • | | | +-- application.properties | Contém as mensagens (textos fixos) da aplicação, | inclusive as mensagens de erros. | Este arquivo é responsável pela internacionalizaçãoda aplicação. +--- lib | | | +-- struts.jar | Contém as classes da Struts (Controller, Helper class, | Biblioteca de Tags, etc) | Também no diretório lib contém outras bibliotecas da aplicaçãoweb. | +--*.tld | Contém os XML descriptors da biblioteca de tags da Struts. | +-- struts-config.xml | Arquivo de configuração da Struts. | Mais detalhes sobre este arquivo serão vistos adiante. | +-- web.xml Arquivo de configuração da aplicação web, relativo ao WebContainer. Mais detalhes sobre este arquivo serão vistos adiante.O arquivo web.xmlO arquivo web.xml deverá ficar algo parecido com:<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"><web-app> <!-- Standard Action Servlet Configuration (with debugging) --> <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> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Standard Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- The Usual Welcome File List --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
    • <!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-nested</taglib-uri> <taglib-location>/WEB-INF/struts-nested.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location> </taglib></web-app>Temos no arquivo web.xml, três importantes seções: • A definição da Servlet que representa o Controller (ActionServlet) • O URL mapping da servlet, para informar como chamar esta servlet • As definições da biblioteca de tags da StrutsPodemos ver pelo servlet-mapping que a nossa servlet será invocada porhttp://localhost:8080/cadastro/<algumaCoisa>.do, substituindo-se <algumaCoisa> pela ação desejada.Banco de dadosPor questões de facilidade de obtenção e configuração e Usaremos o MySQL como banco de dados. O MySqlpode ser baixado em http://www.mysql.comScript de criação do banco de dados:CREATE DATABASE strutsdemo;USE strutsdemo;CREATE TABLE usuario( id_usuario INTEGER NOT NULL, nome VARCHAR(50) NULL, login VARCHAR(20) NULL, senha VARCHAR(20) NULL, sexo CHAR NULL, ativo BOOL NULL, faixa_idade INTEGER, PRIMARY KEY(id_usuario));INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade)VALUES (1, Marcelo Ferreira Dantas, marcelo, marcelo, M, 1, 1);INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade)VALUES (2, Gerson Hernandes Vilela, gerson, gerson, M, 1, 2);INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade)VALUES (3, Manuela Rodrigues, Manuela, manu, F, 1, 2);Para acessar os dados no MySQL será necessário adicionar o driver JDBC no lib da nossa aplicação. O driver
    • pode ser baixado em http://www.mysql.com/downloads/api-jdbc-stable.html. Após baixá-lo,descompactar e copiar o arquivo mysql-connector-java-3.0.8-stable-bin.jar para diretório lib do seu container(no tomcat é "$CATALINA_HOME/common/lib" já no JBoss vai diretório"$JBOSS_HOME/server/default/deploy").Definindo as configurações do Connection PoolA maioria das aplicações para web que usam banco de dados podem ser beneficiadas por um ConnectionPool (coleção de conexões que ficam permanentemente abertas com o SGBD).Estabelecer uma conexão com o banco de dados a cada solicitação que chega no web server paraconsultar/manipular dados é um processo muito dispendioso (conexão e verificação de permissões dousuário do banco).Uma aplicação não usa banco de dados o tempo todo, somente em algums momentos para obter os dados,depois esta conexão não é mais necessária.Nesse sentido, um Connection Pool pode ajudar bastante, eliminando um overread desnecessário de sereconectar a cada solicitação que chega, pois ele fará o gerenciamento da coleção de conexões prontas paraserem usadas, e "marcará" as conexões em uso. Se por acaso você pegar uma conexão e ficar umdeterminado tempo sem fazer nada (timeout), o Connection Pool regata esta conexão para uso, e invalida oobjeto de conexão que você pegou anteriormente. Tamanha é a importância deste tópico, que acabouentrando na especificação JDBC (javax.sql.DataSource). Praticamente todos os Containers possuem ummecanismo que fornecem um Connection Pool.Embora o nosso projeto seja baseado no MySQL, que provavelmente muitos dirão que não há necessidadede se fazer isto com o MySQL, pois o processo de conexão é extremamente rápido, não podemos dizer omesmo de outros bancos. Mesmo assim, é interessante usar um Connection Pool, pois pode parecerimperceptível para uma só solicitação chegando, mas em um ambiente de produção, com a sua aplicaçãosendo macivamente solicitada para manipular e consultar dados, daí sim haverá uma grande diferença.A Struts Framework implementa um Connection Pool usando DataSource. Na versão 1.0, a Conexão eraobtida do ActionServlet. No entanto, nas nos betas e release candidate da versão 1.1 o metodo paraobtenção de conexões ficou deprecated, e passaram esta tarefa para o Action. Por fim no release 1.1 deprodução, as classes que tratam do DataSource foram parar no arquivo struts-legacy.jar, indicandoclaramente a intenção de descontinuar esta funcionalidade em favor de uma solução padrão (JCA), ou seja,implementada pelo container; apesar de ainda continuar funcionando. Assim, vamos usar umaimplementação fornecida pelo container.Para definir as configurações de um DataSource no TomCat, siga os passos abaixo:Altere o arquivo server.xml adicionando o trecho abaixo:<Host name="localhost" debug="0" appBase="webapps" unpackWARs="true"autoDeploy="true"> ... <DefaultContext> <Resource name="jdbc/StrutsDemoDS" auth="Container"type="javax.sql.DataSource" scope="Shareable"/> <ResourceParams name="jdbc/StrutsDemoDS"> <parameter><name>factory</name><value>org.apache.commons.dbcp.BasicDataSourceFactory</value></parameter> <parameter><name>driverClassName</name><value>com.mysql.jdbc.Driver</value></parameter> <parameter><name>url</name><value>jdbc:mysql://localhost/strutsdemo</value></parameter> <parameter><name>username</name><value>root</value></parameter> <parameter><name>password</name><value>root</value></parameter> <parameter><name>maxActive</name><value>20</value></parameter> <parameter><name>maxIdle</name><value>10</value></parameter> <parameter><name>maxWait</name><value>100</value></parameter> </ResourceParams> </DefaultContext> ...</Host>No código Java, quando precisar de uma conexão de banco de dados, você irá solicitar uma conexão aoConnection Pool, o qual irá marcar uma conexão no Pool, como sendo usada, e lhe dará algum tempo parafazer alguma coisa. Tão logo que você use a conexão para consultar ou manipular dados no banco de dados,será necessário devolver a conexão para o pool (se não fizer isto o Connection Pool fecha a conexão paravocê e a resgata para o pool). Para fazer isto, basta executar o método close(), que na verdade não a fecha,
    • mas devolve para o Pool (dependendo da implementação do Connection Pool, poderá ter variações damaneira de devolver ao pool, algo do tipo invocar um metodo do tipo releaseConnection, do objetoConnection Pool).Definindo a Camada de NegócioPara listar os usuários cadastrados precisaremos definir as classes que farão parte da nossa camada deNegócio. Devemos ter duas classes. Uma classe que representa o registro do usuário "UserData" (valueobject) , e outra que irá gerenciar o cadastro dos usuários "AdminUsers". Segue abaixo o código das duasclasses:package strutsdemo.bean;public class UserData { private int idUsuario; private String nome; private String login; private String senha; private String sexo; private boolean ativo; private int faixaIdade; public void setIdUsuario(int idUsuario) { this.idUsuario = idUsuario; } public void setLogin(String login) { this.login = login; } public void setNome(String nome) { this.nome = nome; } public void setSenha(String senha) { this.senha = senha; } public void setSexo(String sexo) { this.sexo = sexo; } public void setAtivo(boolean ativo) { this.ativo = ativo; } public void setFaixaIdade(int faixaIdade) { this.faixaIdade = faixaIdade; } public int getIdUsuario() { return idUsuario; } public String getLogin() { return login; } public String getNome() { return nome; } public String getSenha() { return senha; } public String getSexo() { return sexo; } public boolean getAtivo() { return ativo; } public String getDescricaoStatus() { return this.ativo ? "Ativo": "Inativo"; } public int getFaixaIdade() {
    • return faixaIdade; }}package strutsdemo.bean;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.LinkedList;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.sql.DataSource;public class AdminUsers { protected static DataSource dataSource; public AdminUsers() throws Exception { if (dataSource == null) { try { InitialContext ic = new InitialContext(); // se for tomcat dataSource = (DataSource) ic.lookup("java:comp/env/jdbc/StrutsDemoDS"); // no JBoss faça // dataSource = (DataSource) ic.lookup("java:jdbc/StrutsDemoDS"); } catch (NamingException ex) { System.out.println(ex.getMessage()); throw ex; } } } protected Connection getConnection() throws SQLException { Connection conn = null; try { conn = dataSource.getConnection(); } catch (SQLException e) { throw e; } return conn; } protected void closeConnection( Connection conn, PreparedStatement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { } } if (conn != null) { try {
    • conn.close(); } catch (SQLException e) { } } } public LinkedList getUserList() throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; LinkedList users = new LinkedList(); try { conn = getConnection(); stmt = conn.prepareStatement("select * from usuario"); rs = stmt.executeQuery(); while (rs.next()) { UserData user = new UserData(); user.setIdUsuario(rs.getInt("id_usuario")); user.setNome(rs.getString("nome")); user.setLogin(rs.getString("login")); user.setSenha(rs.getString("senha")); user.setSexo(rs.getString("sexo")); user.setAtivo(rs.getBoolean("ativo")); user.setFaixaIdade(rs.getInt("faixa_idade")); users.add(user); } } catch (SQLException e) { throw e; } finally { closeConnection(conn, stmt, rs); } return users; } public void insertUser(UserData user) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "insert into usuario n" + "(id_usuario, nome, login, senha, sexo, ativo, faixa_idade) n"+ "values (?, ?, ?, ?, ?, ?, ?)"); stmt.setInt(1, user.getIdUsuario()); stmt.setString(2, user.getNome()); stmt.setString(3, user.getLogin()); stmt.setString(4, user.getSenha()); stmt.setString(5, user.getSexo()); stmt.setBoolean(6, user.getAtivo()); stmt.setInt(7, user.getFaixaIdade()); stmt.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } } }
    • public void updateUser(UserData user) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "update usuario set n" + "nome = ?, login = ?, senha = ?, sexo = ?, ativo = ?,faixa_idade = ? n" + "where id_usuario = ?"); stmt.setString(1, user.getNome()); stmt.setString(2, user.getLogin()); stmt.setString(3, user.getSenha()); stmt.setString(4, user.getSexo()); short ativo = (short) (user.getAtivo()? 1: 0); stmt.setShort(5, ativo); stmt.setInt(6, user.getFaixaIdade()); stmt.setInt(7, user.getIdUsuario()); stmt.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } } } public void deleteUser(int idUsuario) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "delete from usuario where id_usuario = ?"); stmt.setInt(1, idUsuario); stmt.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } } }}Definindo o ControllerO Controller é responsável por receber as requisições do browser e invocar os objetos de negócio do Modelpara executar algum processo retornando um resultado que servirá de base para que o Controller possadirecionar para o JSP que deverá gerar a interface com o usuário.O ActionServlet lê as configurações do arquivo struts-config.xml. Ao receber as solicitações do usuário,chama o ActionBean correspondente à requisição, e de acordo com o resultado do ActionBean, executa umJSP.
    • Para incluir, alterar ou excluir um usuário, precisamos exibir todos os usuários cadastrados para saber o quefazer. Assim, a nossa primeira implementação será exibir os usuários já cadastrados.Siga os procedimentos abaixo:• Criar uma package strutsdemo, e uma classe chamada ListUsersAction dentro desta package. A classe deve estender de org.apache.struts.action.Action (vamos entrar em mais detalhes sobre esta classe na seção "Definindo o Action Bean").package strutsdemo;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;public class ListUsersAction extends Action { /* Metódo que invoca a camada de negócios.*/ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return null; // somente para compilar, implementação futura ... }}• Adicionar configuração no arquivo strutus-config.xml do Action Mapping e seus possíveis forwards de saída.</struts-config> <action-mappings> <action path="/listUsers" type="strutsdemo.ListUsersAction"> <forward name="success" path="/listUsers.jsp" /> </action> </action-mappings></struts-config>Neste caso, quando for solicitado pelo browser /listUsers.do" o Controller chamará o ListUsersAction atravésdo método process, e se este objeto retornar um ActionForward com o valor "sucess", O controllerencaminhará a solicitação para o arquivo "/pages/listUsers.jsp". Se retornar "failure", será encaminhado parao arquivo "/pages/error.jsp".Definindo o Action BeanComo foi visto anteriormente, o Controller irá invocar o Action que foi definido no struts-config.xml. Há umacerta discussão sobre que parte pertence o Action e o ActionForm no padrão MVC (vamos entrar em maioresdetalhes mais adiante em ActionForm, por hora ainda não é necessário). Na realidade tanto o Action, quantoo ActionForm são Helper Classes. A grosso modo podemos entender como classes auxiliadores paraexecução no padrão MVC. Basicamente, os ActionBeans realizam as seguintes ações:• Obtem os valores necessários do ActionForm, JavaBean, request, session ou de outro local;• Chama os objetos de negócio do modelo;• Analisa o resultado da chamada da camada de negócio, e baseado nisso, retorna o ActionForward (indicando qual JSP irá apresentar os dados) correspondenteO Código da nossa Action ficará assim:package strutsdemo.action;import java.sql.SQLException;import java.util.LinkedList;
    • import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import strutsdemo.bean.AdminUsers;public class ListUsersAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { LinkedList users = null; ActionErrors errors = new ActionErrors(); try { AdminUsers adminUsers = new AdminUsers(); users = adminUsers.getUserList(); HttpSession session = request.getSession(); session.setAttribute("userListBean", users); } catch (SQLException e) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.user.list")); getServlet().log("Erro carregando a lista de usuários", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); } }}Definindo a camada de apresentaçãoA Camada de apresentação representa o view (visualização) no padrão MVC. É em sua grande maioriabaseada em JSPs e alguns servlets envolvidos na geração da interface com o usuário ou com outrossistemas. A Struts framework fornece suporte para construir aplicações multi-idiomas, interação comformulários e outras utilidades através de tags personalizadas (Custom Tags).InternacionalizaçãoNo nosso projeto (baseado no template struts-blank ), possui um arquivo de chamado application.propertiesno diretório cadastro/WEB-INF/classes/java/resources. Este arquivo deve conter as chaves e os valores noformato: chave.subchave=texto que pertence ao idioma padrão da aplicação. Vamos adicionar algumaschaves que serão usadas em nosso projeto. Obs: Este arquivo pode ter qualquer nome, desde que terminecom .properties. No entanto existe um certo padrão, geralmente é chamado deApplicationResources.properties. A única ressalva, é que se você mudar o nome deste arquivo, tambémdeverá ser mudado no arquivo struts-config.xml.welcome.title=Bem Vindo ao Projeto Tutorial Strutswelcome.heading=Bem vindo!welcome.message=Projeto Tutorial Struts
    • application.title= Struts Demo - Cadastroindex.header=Bem vindo ao Demo da Strutus Framework - Cadastrousers.title=Cadastro de UsuárioseditUser.title=Alteração de UsuárioinsertUser.title=Inclusão de Usuárioprompt.idUsuario=Códigoprompt.nome=Nomeprompt.login=Loginprompt.senha=Senhaprompt.confirmacaoSenha=Confirmação da Senhaprompt.sexo=Sexoprompt.ativo=Ativoprompt.status=Statusprompt.faixaIdade=Faixa Etáriaprompt.excluir=Excluirprompt.incluir=Incluirprompt.voltar=Voltarprompt.Masculino=Masculinoprompt.Feminino=Femininoprompt.ate20=Até 20 anosprompt.de21a30=De 21 a 30 anosprompt.de31a40=De 31 a 40 anosprompt.de41a50=De 41 a 50 anosprompt.de51a60=De 51 a 60 anosprompt.acima60=Acima de 60 anosprompt.senhaAntiga=Senha Antigaprompt.novaSenha=Nova Senhaprompt.confirmacaoNovaSenha=Confirmação da Senhabutton.send=Enviarbutton.reset=Cancelarerror.title=Erro Inesperadoerror.user.list=Erro obtendo a lista de usuárioserror.idUsuario.required=O identificador do usuário é um campo obrigatórioerror.login.required=O login do usuário é um campo obrigatórioerror.nome.required=O nome do usuário é um campo obrigatórioerror.get.user=Erro ao carregar o usuárioerror.senhaAntiga.required=A senha antiga é um campo obrigatórioerror.novaSenha.required=A nova senha é um campo obrigatórioerror.confirmacaoNovaSenha.required=A confirmação da nova senha é um campoobrigatórioerror.ConfirmacaoSenha=Erro na confirmação da nova senhaerror.user.notFound=Usuário não encontradoerror.senhaAntiga=A senha Antiga não confereerror.update.user=Erro alterando o usuárioerror.update.user=Erro incluindo o usuárioerror.delete.user=Erro excluindo o usuárioerror.idUsuario.duplicateKey=Este código de usuário já existePara cada idioma alternativo, devemos adicionar um novo arquivo (no mesmo diretório do arquivo ondetemos o arquivo do idioma padrão) no formato "application_xx.properties", onde xx é o código ISO doidioma. Ex: (application_en.properties).No arquivo struts-config.xml devemos definir a localização do arquivo com o idioma padrão.Coloque neste:<message-resources parameter="resources.application"/>Obs: Na Struts 1.0 este arquivo era definido no arquivo web.xmlNos JSPs que utilizaremos a internacionalização deveremos incluir:...<%@ taglib uri="/tags/struts-bean" prefix="bean" %>...Para declarar que utilizaremos a TagLibrary struts-bean com o prefixo bean e definida no arquivo /WEB-INF/struts-bean.tld, configurados no arquivo web.xml. E finalmente, utilizaremos a tag (no JSP)<bean:message key="chave.subchave"/> onde a chave e a subchave correspondem ao texto que seráinserido de acordo com o idioma do usuário. Exemplo:...
    • <h3><bean:message key="application.title"/></h3>...Por default, a Struts acessa o idioma principal da aplicação. Devemos utilizar a tag <html:htmllocale="true"> substituindo a tag <html>, assim, deveremos substituir também a tag </html> por</html:html> Deste modo, será usado preferencialmente o idioma principal que se encontra no header"Accept-Language" enviado pelo navegador.Quando o usuário fizer uma solicitação escolher um novo idioma, baseado em uma lista de idiomassuportados, informados previamente, adicionaremos o trecho abaixo:session.setAttribute(Action.LOCALE_KEY,new Java.util.Locale(country, language));Onde country e language será a string do país e que será feita a tradução. Para mais informações a respeitodo assunto, veja a documentação oficial da Sun disponível emhttp://java.sun.com/j2se/1.4.2/docs/guide/intl.Por questões de organização vamos colocar todos os nossos JSPs no diretório cadastro/pages/. Assim, já podemos escrever o nosso primeiro JSP para listar os usuários:<%@ taglib uri="/tags/struts-logic" prefix="logic" %><%@ taglib uri="/tags/struts-html" prefix="html" %><%@ taglib uri="/tags/struts-bean" prefix="bean" %><logic:notPresent name="userListBean" scope="session"> <logic:redirect forward="error"/></logic:notPresent><html:html locale="true"><head> <title><bean:message key="users.title"/></title></head><body> <center> <font face="Comic Sans MS" size="3"> <blockquote> <center> <h3><font color="blue"><bean:messagekey="users.title"/></font></h3> <table width="80%" border="1"> <tr> <th width="10%"><bean:messagekey="prompt.idUsuario"/></th> <th width="50%"><bean:message key="prompt.nome"/></th> <th width="20%"><bean:message key="prompt.login"/></th> <th width="10%"><bean:message key="prompt.ativo"/></th> <th width="10%"></th> </tr> <%-- loop que percorre a Collection de usuarios --%> <logic:iterate name="userListBean" id="user" > <tr> <td align="center"> <bean:write name="user" property="idUsuario"/> </td> <td> <html:link page="/editUser.do"paramId="idUsuario" paramName="user" paramProperty="idUsuario"> <bean:write name="user" property="nome"/> </html:link> </td> <td><bean:write name="user" property="login"/></td> <td><bean:write name="user"property="descricaoStatus"/></td> <td> <html:link page="/deleteUser.do"paramId="idUsuario" paramName="user" paramProperty="idUsuario"> <bean:message key="prompt.excluir"/> </html:link> </td> </tr>
    • </logic:iterate> </table> <br/> <html:link page="/insertUser.do">incluir</html:link> <html:link page="/Welcome.do">Página Inicial</html:link> </center> </lockquote> </body></html:html>Neste ponto, já temos uma aplicação funcionando parcialmente (listando os usuários). No entanto se clicarem algum link, irá ocorrer um erro, pois ainda não temos os ActionBeanss necessários para invocar acamada de negócio. Neste momento para facilitar o entendimento, vamos implementar apenas os Beansnecessários para Alterar o usuário. Devemos criar um ActionBean que deverá invocar a camada de negócio epopular um bean com os dados do usuário a ser alterado, e enviar para a camada de apresentação para queos dados possam ser alterados. Segue abaixo o código do ActionBean.package strutsdemo.action;import java.util.Iterator;import java.util.LinkedList;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import strutsdemo.bean.AdminUsers;import strutsdemo.bean.UserData;public class EditUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionErrors errors = new ActionErrors(); try { HttpSession session = request.getSession(); AdminUsers adminUsers = new AdminUsers(); String idUsuario = request.getParameter("idUsuario"); session.removeAttribute("editUserBean"); LinkedList userList = (LinkedList)session.getAttribute("userListBean"); Iterator iter = userList.iterator(); while (iter.hasNext()) { UserData user = (UserData)iter.next(); if (user.getIdUsuario() == Integer.parseInt(idUsuario)) { session.setAttribute("editUserBean", user); break; } } UserData user = (UserData)session.getAttribute("editUserBean"); if (user == null) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.user.notFound")); } } catch (Exception e) { errors.add( ActionErrors.GLOBAL_ERROR,
    • new ActionError("error.get.user")); getServlet().log("Erro carregando o Usuário", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); } }}Agora devemos alterar o arquivo struts-config.xml, ou seja acrescentar um action-mapping. Para isto bastaadicionar o trecho de código abaixo na seção <action-mappings><action path="/editUser" scope="session" type="strutsdemo.action.EditUserAction" unknown="false" validate="false"> <forward name="success" path="/pages/editUser.jsp" redirect="false" contextRelative="false" /></action>Por fim vamos ver como fica o código JSP para alterar o usuário(editUser.jsp). Vale lembrar que o códigoJSP abaixo ainda não pode ser executado, pois depende de um Action que ainda não foi implementado.<%@ taglib uri="/tags/struts-logic" prefix="logic" %><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-html" prefix="html"%><html:html locale="true"> <head> <title><bean:message key="editUser.title"/></title> </head> <body> <font face="Comic Sans MS" size="3"> <center> <h3><font color="blue"><bean:messagekey="editUser.title"/></font></h3> <html:form action="/saveEditUser.do" method="post"focus="login"> <html:hidden property="idUsuario" name="editUserBean"/> <table width="80%" border="0"> <tr> <td width="30%"></td> <td width="70%"> <%-- exibe os erros de validação --%> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </td> <tr> <tr> <td align="right"><bean:messagekey="prompt.idUsuario"/>: </td> <td align="left"><b><bean:write property="idUsuario"name="editUserBean"/></b></td> </tr> <tr> <td align="right"><bean:message
    • key="prompt.login"/>: </td> <td align="left"><html:text property="login"name="editUserBean" size="20"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.nome"/></td> <td align="left"><html:text property="nome"name="editUserBean" size="60"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.senhaAntiga"/>: </td> <td align="left"><html:passwordproperty="senhaAntiga" size="16" maxlength="20" redisplay="false"value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.novaSenha"/>: </td> <td align="left"><html:password property="novaSenha"size="16" maxlength="20" redisplay="false"value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.confirmacaoNovaSenha"/>: </td> <td align="left"><html:passwordproperty="confirmacaoNovaSenha" size="16" maxlength="20" redisplay="false"value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.faixaIdade"/>: </td> <td align="left"> <html:select property="faixaIdade"name="editUserBean"> <html:option value="1"><bean:messagekey="prompt.ate20"/></html:option></html:option> <html:option value="2"><bean:messagekey="prompt.de21a30"/></html:option></html:option> <html:option value="3"><bean:messagekey="prompt.de31a40"/></html:option></html:option> <html:option value="4"><bean:messagekey="prompt.de41a50"/></html:option></html:option> <html:option value="5"><bean:messagekey="prompt.de51a60"/></html:option></html:option> <html:option value="6"><bean:messagekey="prompt.acima60"/></html:option></html:option> </html:select> </td> </tr> <tr> <td align="right"><bean:message key="prompt.sexo"/>:</td> <td align="left"> <html:radio property="sexo" value="M"name="editUserBean"> <bean:message key="prompt.Masculino"/> </html:radio> <html:radio property="sexo" value="F"name="editUserBean"> <bean:message key="prompt.Feminino"/> </html:radio> </td>
    • </tr> <tr> <td align="right"><bean:messagekey="prompt.ativo"/>: </td> <td align="left"> <html:checkbox property="ativo"name="editUserBean" titleKey="prompt.ativo"/> </td> </tr> <tr> <td colspan="2" align="center"> <html:submit><bean:messagekey="button.send"/></html:submit> <html:reset><bean:messagekey="button.reset"/></html:reset> </td> </tr> </table> </html:form> <br/> <html:link page="/listUsers.do">voltar</html:link> </center> </font> </body></html:html>FormsUma das tarefas mais trabalhosas no desenvolvimento de uma aplicação é a interação com formulários, parase alterar e obter nova informação. As validações, o tratamento de erros, a apresentação, e o mesmo aentrada de dados do form pelo usuário e mensagens de erros, são contempladas pela Struts, o que torna avida um pouco mais fácil. Todo trabalho de validação e geração de mensagens de erros serãoimplementados nos ActionForm e todo o trabalho de geração de interface no JSP.Basicamente o ActionForm será um espelho dos inputs que vem do html do browser, ou seja, deverá contertodos os campos (variaveis privadas com os devidos metodos gets e sets), coincidindo com o nome dosinputs do formulário html.Toda validação de dados pela Struts passa por um FormBean. O FormBean é a primeira classe (quandodefinida no action-mapping) a ser chamada através do método validate (Detalhes na Figura 2). No entanto,nem toda solicitação que vem da web necessita de validação de dados. Assim só será necessário usar umFormBean quando necessitarmos de validação dos dados.No nosso caso, quando precisarmos salvar os dados que foram alterados pelo usuário. No entanto, antes dedevemos fazer uma validação para que não vá besteira para o banco de dados. Um ActionForm possui doismétodos importantes. São eles reset e validate.Veja abaixo a implementação do nosso ActionForm que faz as validações mínimas necessárias.package strutsdemo.form;import javax.servlet.http.HttpServletRequest;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionMapping;public class SaveEditUserForm extends ActionForm { private String idUsuario; private String login; private String nome; private String ativo; private String faixaIdade; private String sexo; private String senhaAntiga; private String novaSenha; private String confirmacaoNovaSenha;
    • public void reset(ActionMapping mapping, HttpServletRequest request) { idUsuario = "-1"; login = ""; nome = ""; ativo = "false"; faixaIdade = "1"; sexo = "M"; senhaAntiga = ""; novaSenha = ""; confirmacaoNovaSenha = ""; } public ActionErrors validate( ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((idUsuario == null) || (idUsuario.length() < 1)) { errors.add("idUsuario", new ActionError("error.idUsuario.required")); } if ((login == null) || (login.length() < 1)) { errors.add("login", new ActionError("error.login.required")); } if ((nome == null) || (nome.length() < 1)) { errors.add("nome", new ActionError("error.nome.required")); } if ((novaSenha == null) || (novaSenha.length() < 1)) { errors.add("nome", new ActionError("error.novaSenha.required")); } if ((confirmacaoNovaSenha == null) || (confirmacaoNovaSenha.length() <1)) { errors.add("confirmacaoNovaSenha", new ActionError("error.confirmacaoNovaSenha.required")); } if ((senhaAntiga == null) || (senhaAntiga.length() < 1)) { errors.add("senhaAntiga", new ActionError("error.senhaAntiga.required")); } if (errors.isEmpty()) { if (!novaSenha.equals(confirmacaoNovaSenha)) { errors.add("senhaAntiga", new ActionError("error.ConfirmacaoSenha")); } } return errors; } public String getNovaSenha() { return novaSenha; } public void setNovaSenha(String novaSenha) { this.novaSenha = novaSenha; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getAtivo() { return ativo; } public void setAtivo(String ativo) { this.ativo = ativo; } public String getLogin() { return login;
    • } public void setLogin(String login) { this.login = login; } public String getSenhaAntiga() { return senhaAntiga; } public void setSenhaAntiga(String senhaAntiga) { this.senhaAntiga = senhaAntiga; } public String getSexo() { return sexo; } public void setSexo(String sexo) { this.sexo = sexo; } public String getConfirmacaoNovaSenha() { return confirmacaoNovaSenha; } public void setConfirmacaoNovaSenha(String confirmacaoNovaSenha) { this.confirmacaoNovaSenha = confirmacaoNovaSenha; } public String getFaixaIdade() { return faixaIdade; } public void setFaixaIdade(String faixaIdade) { this.faixaIdade = faixaIdade; } public String getIdUsuario() { return idUsuario; } public void setIdUsuario(String idUsuario) { this.idUsuario = idUsuario; }}Quando terminar a execução do método validate, se ocorrer algum erro, será adicionado em um Collectionde erros. Se este collection tiver algum erro, o FormBean devolve para o jsp que entrou com os dados, comos campos devidamente preenchidos, e com as mensagens dos erros ocorridos. Caso contrário, ou seja, senão ocorrer nenhum erro, então o fluxo segue para um ActionBean para invocar a camada de negócio paragravar estes dados no banco de dados. Logo, precisamos criar este bean. Segue abaixo o código do nossoActionBean.package strutsdemo.action;import java.sql.SQLException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import javax.sql.DataSource;import org.apache.commons.beanutils.BeanUtils;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import strutsdemo.bean.AdminUsers;import strutsdemo.bean.UserData;import strutsdemo.form.SaveEditUserForm;public class SaveEditUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request,
    • HttpServletResponse response) throws Exception { ActionErrors errors = new ActionErrors(); try { HttpSession session = request.getSession(); SaveEditUserForm editUserForm = (SaveEditUserForm)form; UserData user = (UserData)session.getAttribute("editUserBean"); if (!editUserForm.getSenhaAntiga().equals("zzzzz")) { if (!user.getSenha().equals(editUserForm.getSenhaAntiga())) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.senhaAntiga")); } else { user.setSenha(editUserForm.getNovaSenha()); } } if (errors.isEmpty()) { BeanUtils.copyProperties(user, editUserForm); DataSource dataSource = getDataSource(request); AdminUsers adminUsers = new AdminUsers(); adminUsers.updateUser(user); } } catch (SQLException e) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.update.user")); getServlet().log("Erro alterando o Usuário", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); } }}Agora, que fizemos o FormBean e o ActionBean, devemos fazer o action-mapping associando estes beans.Segue abaixo as alterações necessárias no struts-config.xml.<form-beans><form-bean dynamic="false" name="saveEditUserForm" type="strutsdemo.form.SaveEditUserForm"></form-beans>...<action-mappings>... <action attribute="saveEditUserForm" input="/pages/editUser.jsp" name="saveEditUserForm" path="/saveEditUser" scope="session" type="strutsdemo.action.SaveEditUserAction" unknown="false" validate="true"> <forward name="success" path="/pages/listUsers.jsp" redirect="false" contextRelative="false" /> </action>
    • ...</action-mappings>Obs: Até a versão 1.0 da Struts, a única maneira de validar os dados era herdando do ActionForm, ecolocando as regras de validação no método validate. No entanto com a Struts 1.1 é possível fazer avalidação através de um Form Dinâmico, mais adiante veremos como definir um Form dinâmico.Outra novidade na Struts 1.1 é o suporte para validação do lado client através de uma biblioteca dejavascript definidos no arquivo validator.xml. Assim, podemos evitar o overread gerado pelas solicitaçõesdesnecessárias no servidor, pois quando a solicitação chega ao web server, estaremos tratando com osdados previamente tratados pelo javascript do lado client.Só pra constar como lembrete para os novatos em internet. Pode parecer tentador, mas nunca deixe devalidar os dados no lado servidor se tiver tudo tratado no lado client, pois o usuário pode desabilitar ojavascript do browser e causar erros imprevisíveis na sua aplicação. Conclusão: Use javascript para validar sepuder, e sempre use validação do lado servidor.Validando dados via javascriptPara fazer a validação com a struts no client via javascript devemos acrescentar os criterios no arquivo noarquivo validation.xml. Adicionar o trecho de código abaixo na seção <formset>. <formset> <form name="saveEditUserForm"> <field property="idUsuario" depends="required"> <arg0 key="prompt.idUsuario"/> </field> <field property="login" depends="required"> <arg0 key="prompt.login"/> </field> <field property="nome" depends="required"> <arg0 key="prompt.nome"/> </field> <field property="novaSenha" depends="required,mask"> <arg0 key="prompt.novaSenha"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> <field property="senhaAntiga" depends="required,mask"> <arg0 key="prompt.senhaAntiga"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> <field property="confirmacaoNovaSenha" depends="required,mask"> <arg0 key="prompt.confirmacaoNovaSenha"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> </form> </formset>Também precisaremos "traduzir" algumas mensagens que já vieram no arquivo application.properties datemplate struts-blank.war, pois serão usados no javascript.# Mensagens de erro padrão para as validaçõeserrors.required={0} é um campo obrigatório.errors.minlength={0} Não pode ser menor que {1} caracteres.errors.maxlength={0} Não pode ser maior que {2} caracteres.errors.invalid={0} está inválido.errors.byte={0} deve ser um byte.errors.short={0} deve ser um inteiro curto.errors.integer={0} deve ser um inteiro.errors.long={0} deve ser um inteiro longo.errors.float={0} deve ser um ponto flutuante de precisão simples.errors.double={0} deve ser um ponto flutuante de precisão dupla.
    • errors.date={0} não é uma data.errors.range={0} não está na faixa entre {1} e {2}.errors.creditcard={0} não é um número de cartão de crédito válido.errors.email={0} não é um e-mail válido.Neste ponto temos a aplicação Listando e alterando o cadastro de usuários. No entanto, precisamos aindafazer a Inclusão e a Exclusão de Usuários. Então vamos lá ...Forms DinâmicosUma das grandes melhorias do Struts 1.1 em relação à 1.0 (pode haver controvérsias, mas ...) foi aintrodução dos DynamicForms. Assim você não é mais "obrigado" a criar um Form para validar as entradasde cada formulário HTML. O Dynamic Form é configurado apenas no struts-config.xml e a Struts já tem umaclasse "prontinha para fazer as validações para você.Veja o trecho abaixo do codigo para um Form Dinâmico:<form-bean dynamic="true" name="saveInsertUserForm"type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="idUsuario" type="java.lang.String" /> <form-property name="login" type="java.lang.String" /> <form-property name="nome" type="java.lang.String" /> <form-property name="faixaIdade" type="java.lang.String" /> <form-property name="sexo" type="java.lang.String" /> <form-property name="ativo" type="java.lang.String" /> <form-property name="senha" type="java.lang.String" /> <form-property name="confirmacaoSenha" type="java.lang.String" /></form-bean>Terminando o projetoNeste ponto o nosso projeto está praticamente finalizado. A partir de agora vamos repetir alguns passos quejá foram feitos antes. ou seja, se você chegou até aqui, só falta um pouco de pratica para você se tornar umexpert nesta framework. Segue abaixo os codigos que ainda faltam:• cadastro/pages/Welcome.jsp<%@ taglib uri="/tags/struts-bean" prefix="bean" %><%@ taglib uri="/tags/struts-html" prefix="html" %><%@ taglib uri="/tags/struts-logic" prefix="logic" %><html:html locale="true"><head><title><bean:message key="welcome.title"/></title><html:base/></head> <body bgcolor="white"> <font face="Comic Sans MS" size="3"> <center> <h1><font color="blue"><bean:messagekey="welcome.title"/></font></h1> <logic:notPresent name="org.apache.struts.action.MESSAGE"scope="application"> <font color="red"> ERROR: Application resources not loaded -- checkservlet container logs for error messages. </font> </logic:notPresent> <h3><bean:message key="welcome.heading"/></h3> <p><bean:message key="welcome.message"/></p> <html:link page="/listUsers.do">Cadastro de Usuários</html:link> </center> <p><font color="darkblue"> Autor: <html:link href="mailto:wbsouza@yahoo.com.br">WelingtonB.Souza</html:link> <br>01/07/2003 </font></p> </p> </font>
    • </body></html:html>• cadastro/pages/error.jsp<%@ taglib uri="/tags/struts-bean" prefix="bean" %><%@ taglib uri="/tags/struts-html" prefix="html" %><%@ taglib uri="/tags/struts-logic" prefix="logic" %><html:html locale="true"><head><title><bean:message key="error.title"/></title><html:base/></head><body bgcolor="white"> <font face="Comic Sans MS" size="3"> <center> <blockquote> <h1><font color=red><bean:message key="error.title"/></font></h1> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </blockquote> <br/> <html:link page="/Welcome.do">Página Inicial</html:link> </center></body></html:html>package strutsdemo.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import strutsdemo.bean.UserData;public class InsertUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); UserData user = new UserData(); session.setAttribute("insertUserBean", user); return (mapping.findForward("success")); }}• cadastro/pages/insertUser.jsp<%@ taglib uri="/tags/struts-logic" prefix="logic" %><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-html" prefix="html"%><html:html locale="true"> <head> <title><bean:message key="insertUser.title"/></title> </head> <body> <font face="Comic Sans MS" size="3">
    • <center> <h3><font color="blue"><bean:messagekey="insertUser.title"/></font></h3> <html:form action="/saveInsertUser.do" method="post"onsubmit="return validateSaveInsertUserForm(this);" focus="idUsuario"> <table width="80%" border="0"> <tr> <td width="30%"></td> <td width="70%"> <%-- exibe os erros de validação --%> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </td> <tr> <tr> <td align="right"><bean:messagekey="prompt.idUsuario" name="insertUserBean"/>: </td> <logic:equal name="insertUserBean"property="idUsuario" value="0"> <td align="left"><html:text property="idUsuario"size="5" value=""/></td> </logic:equal> <logic:notEqual name="insertUserBean"property="idUsuario" value="0"> <td align="left"><html:text property="idUsuario"size="5" name="insertUserBean"/></td> </logic:notEqual> </tr> <tr> <td align="right"><bean:messagekey="prompt.login"/>: </td> <td align="left"><html:text property="login"size="20" name="insertUserBean"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.nome"/></td> <td align="left"><html:text property="nome"size="60" name="insertUserBean"/></td> </tr> <tr> <td align="right"><bean:messagekey="prompt.senha"/>: </td> <td align="left"> <html:password property="senha" size="16"maxlength="20" redisplay="false"/> </td> </tr> <tr> <td align="right"><bean:messagekey="prompt.confirmacaoSenha"/>: </td> <td align="left"> <html:password property="confirmacaoSenha"size="16" maxlength="20" redisplay="false"/> </td> </tr> <tr> <td align="right"><bean:messagekey="prompt.faixaIdade"/>: </td> <td align="left"> <html:select property="faixaIdade"name="insertUserBean"> <html:option value="1"><bean:message
    • key="prompt.ate20"/></html:option></html:option> <html:option value="2"><bean:messagekey="prompt.de21a30"/></html:option></html:option> <html:option value="3"><bean:messagekey="prompt.de31a40"/></html:option></html:option> <html:option value="4"><bean:messagekey="prompt.de41a50"/></html:option></html:option> <html:option value="5"><bean:messagekey="prompt.de51a60"/></html:option></html:option> <html:option value="6"><bean:messagekey="prompt.acima60"/></html:option></html:option> </html:select> </td> </tr> <tr> <td align="right"><bean:message key="prompt.sexo"/>:</td> <td align="left"> <html:radio property="sexo" value="M"name="insertUserBean"> <bean:message key="prompt.Masculino"/> </html:radio> <html:radio property="sexo" value="F"name="insertUserBean"> <bean:message key="prompt.Feminino"/> </html:radio> </td> </tr> <tr> <td align="right"><bean:messagekey="prompt.ativo"/>: </td> <td align="left"> <html:checkbox property="ativo"titleKey="prompt.ativo" name="insertUserBean" /> </td> </tr> <tr> <td colspan="2" align="center"> <html:submit><bean:messagekey="button.send"/></html:submit> <html:reset><bean:messagekey="button.reset"/></html:reset> </td> </tr> </table> </html:form> <br/> <html:link page="/listUsers.do">voltar</html:link> </center> </font> </body> <html:javascript formName="saveInsertUserForm"/></html:html>package strutsdemo.action;import java.sql.SQLException;import java.util.LinkedList;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;
    • import org.apache.struts.validator.DynaValidatorForm;import strutsdemo.bean.AdminUsers;import strutsdemo.bean.UserData;public class SaveInsertUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { DynaValidatorForm dynaForm = (DynaValidatorForm) form; ActionErrors errors = new ActionErrors(); String senha1 = (String)dynaForm.get("senha"); String senha2 = (String)dynaForm.get("confirmacaoSenha"); // como utilizamos um DynamicForm, precisamos terminar a validação aqui. if (senha1.equals(senha2)) { try { HttpSession session = request.getSession(); // popula o bean do usuario com os dados que vieram do Form UserData user = (UserData) session.getAttribute("insertUserBean"); user.setIdUsuario(Integer.parseInt((String)dynaForm.get("idUsuario"))); user.setLogin((String)dynaForm.get("login")); user.setNome((String)dynaForm.get("nome")); user.setFaixaIdade(Integer.parseInt((String)dynaForm.get("faixaIdade"))); user.setSexo((String)dynaForm.get("sexo")); user.setNome((String)dynaForm.get("nome")); user.setSenha(senha1); boolean ativo = ((String)dynaForm.get("ativo")).equals("on"); user.setAtivo(ativo); AdminUsers adminUsers = new AdminUsers(); adminUsers.insertUser(user); LinkedList userList = (LinkedList) session.getAttribute("userListBean"); userList.add(user); session.removeAttribute("insertUserBean"); } catch (SQLException e) { if (e.getErrorCode() == 1062) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.idUsuario.duplicateKey")); } else { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.insert.user")); } } } else { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.ConfirmacaoSenha")); } if (!errors.isEmpty()) {
    • saveErrors(request, errors); return (mapping.findForward("error")); } else { return (mapping.findForward("success")); } }}package strutsdemo.action;import java.util.Iterator;import java.util.LinkedList;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import strutsdemo.bean.AdminUsers;import strutsdemo.bean.UserData;public class DeleteUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); String idUsuario = request.getParameter("idUsuario"); ActionErrors errors = new ActionErrors(); try { LinkedList userList = (LinkedList)session.getAttribute("userListBean"); Iterator iter = userList.iterator(); while (iter.hasNext()) { UserData user = (UserData)iter.next(); if (user.getIdUsuario() == Integer.parseInt(idUsuario)) { AdminUsers adminUsers = new AdminUsers(); adminUsers.deleteUser(Integer.parseInt(idUsuario)); userList.remove(user); break; } } } catch (Exception e) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.delete.user")); getServlet().log("Erro carregando a lista de usuários", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); }
    • }}Outras fontes de pesquisa • Struttin With Struts - Lessons • Stepping through Jakarta Struts • About Struts • i18n with Struts • Introduction to Jakarta Struts Framework • Learn Struts Form-Related Tags • TheServerSide.com J2EE Community • Project Refinery, Inc • Create Better Web Apps with Struts • Struts Tutorial OverviewFerramentas para a StrutsAtualmente existem diversas ferramentas para configuração da Struts de forma visual com diversas opçõesentre produtos pagos e open source (EasyStruts, Struts Console). No entanto, é recomendável familiarizar-seprimeiro com a configuração manual antes de utilizar estas ferramentas, pois caso ocorra algum problemaimprevisto, possa ser corrigido manualmente. Você pode encontrar mais detalhes em buscas noSourceForge.net, tem um monte de coisas legais lá.Integração com outras bibliotecasAssim como existe a Struts, existem também outras bibliotecas para algumas funcionalidades específicas(custom tags, templates, etc). Assim é possível fazer uma série de combinações no sentido de conseguir oefeito desejado na sua aplicação web. Veja algumas bibliotecas que podem ser integradas à Struts. • Struts-Layout • Struts Menu • Velocity • JavaServer Faces • Novamente faça buscas no site SourceForge.netBoa sorte nos seus projetos com a Struts Framework !Clique aqui e baixe os fontes deste tutorial.••