Laboratório de Programação 3 Parte II 2 - Struts Maj Mello SE/8 IME cgmello@de9.ime.eb.br http://www.des.ime.eb.br/~cgmello
Introdução O Jakarta Struts é um framework MVC-2 criado por Craig R. McClanahan e doado para a ASF - Apache Software Foundation no ano de 2000 Um framework é uma aplicação semicompleta e reutilizável que pode ser pode ser especializada para produzir soluções personalizadas As aplicações Web constituem um tipo de aplicação com uma base comum muito grande, o Struts constitui uma base para a construção de um produto específico Struts é um framework Web que tem se tornado um padrão de facto na comunidade J2EE Struts é indicado para qualquer projeto? Não.
Introdução O nome Struts é devido ao seu papel estrutural de servir como base comum para a construção de aplicações Web Struts é suportado hoje pelas principais IDEs, livres e proprietárias Integra-se a outras tecnologias de visualização, não apenas JSP JSF Tiles JSTL Tapestry Velocity
Introdução Framework maduro mas sem o charme da novidade Versões 1.3 2.0 (conhecido como WebWork 2) Criador do Struts agora esta no projeto do JSF, mas isso não quer dizer que o Struts está morto JSF Java Server Faces Modelo de componentes GUI-like para aplicações web Trata eventos dos componentes GUI AJAX
Requisitos J2SE - Java 2 Plataform Standard Edition Servlet Container (ex: Tomcat) Framework Struts
Arquitetura do Struts Container Web 1. Recebe requisição HTTP 2. Popula e Valida ActionForm ActionServlet struts-config.xml 5. Mapeia a View 3. Executa Action 6. Retorna Página JSP 4. Retorna uma View
Arquitetura do Struts 1 - O container Web recebe uma requisição HTTP e repassaparao ActionServlet O ActionServlet é um servlet do Struts que recebe a requisição HTTP e, baseando-se no arquivo de configuração struts-config.xml, redireciona o fluxo para uma classe Action definida pelo usuário, para que esta trate a requisição, passando os parâmetros da requisição HTTP em uma classe ActionForm definida pelo usuário
Arquitetura do Struts 2 - O ActionServlet instancia e popula uma classe ActionForm definida pelo usuário com os dados da requisição HTTP e chama o método de validação A classe ActionForm é um JavaBean que encapsula os parâmetros recebidos da requisição HTTP e permite a implementação de um método validade O Struts usa introspecção para converter os parâmetros da requisição HTTP em atributos da classe ActionForm
Arquitetura do Struts 3 - Após popular a classe ActionForm, o ActionServlet instancia e chama o método execute de uma classe Action definida pelo usuário passando o ActionForm como parâmetro. A Action é quem faz o processamento. Deve utilizar Façades e DAOs (Data Access Object) como modelo e persistência É possível definir no arquivo de configuração um outro método a ser chamado na classe Action do usuário ao invés do execute Caso haja erro na validação, o ActionServlet redireciona o fluxo para uma página de erro definida pelo usuário no arquivo de configuração
Arquitetura do Struts 4 - A classe Action definida pelo usuário faz o processamento, chamando classes de negócio e DAOs, e retorna uma constante que identifica qual View (página JSP geralmente) deve ser chamada O resultado do processamento da Action é geralmete armazenado na mesma ActionForm recebida ou em outra classe que persiste na aplicação
Arquitetura do Struts 5 - O ActionServlet recebe o retorno da Action e mapeia o identificador através do arquivo de configuração, determinando qual página chamar (página jsp, servlet, páginas HTML estáticas) para que a visualização do resultado do processamento da Action seja feita A View tem acesso à classe ActionForm ou alguma outra classe que tenha persistido na aplicação para recuperar e mostrar o resultado da Action Um resultado pode persistir numa classe através dos escopos de página, sessão, aplicação, request ou através de um ThreadLocal
Arquitetura do Struts 6 - O processo se repete quando a View gera uma nova requisição HTTP
Por onde começar? Criar uma aplicação Web Definir o controlador do Struts no arquivo /WEB- INF/web.xml Incluir as bibliotecas necessárias no /WEB-INF/lib antlr.jar commons-beanutils.jar commons-digester.jar commons-fileupload.jar commons-logging.jar commons-validator.jar jakarta-oro.jar struts.jar
Aplicação exemplo: Calculadora (1) TOMCAT http://dominio:8080/calculadora welcome-page (2) (4) *.do popula/valida (5) CalculadoraForm org.apache.struts. action. ActionServlet (8) redireciona para view (resultado ou erro) executa (6) CalculadoraAction (3) - (9) submit p/ /action.do -num1 -num2 - operacao calc.jsp (7) resultado ou erro Calculadora (model)
A aplicação
Definindo o controlador do Struts em /WEB-INF/web.xml
Não é necessário o *.do
Welcome page
Arquivo de configuração do Struts /WEB-INF/struts-config.xml
Exemplo Calculadora
Definindo um ActionForm
ActionForms ActionForm é um JavaBean onde cada atributo da classe tem um correspondente em um parâmetro da requisição HTTP que o ActionServlet recebe É uma classe do usuário que extende a classe ActionForm
Exemplo de ActionForm
Método validate do ActionForm
Método validate do ActionForm Deve retornar um objeto do tipo ActionErrors, que é uma coleção de objetos ActionMessage Tem acesso ao parâmetros da requisição HTTP via os métodos Gets do ActionForm em que está inserido Deve adicionar os erros encontrados criando novas ActionMessage e incluindo na ActionErrors Se o método retorna null ou vazio para o objeto ActionErrors, significa que a validação foi bem sucedida O usuário define no arquivo de configuração qual fluxo tomar no caso de erro, geralmente retornar para a página JSP de entrada
Método validate do ActionForm É necessário criar um arquivo de mensagens (um message-resource) para conter as mensagens de erro Devem existir mensagens de erro associadas a cada campo dos formulários presentes na aplicação, e para cada um dos erros possíveis para esse campo Os erros são mostradas pela página JSP com a seguinte tag <html:errors /> ou <html:errors property="" />
Definindo um action-mapping
Action-mapping <action path="/inicio" forward="/calc.jsp"> faz o mapeamento da URL http://dominio/inicio.do para o JSP calc.jsp
Action-mapping <action path="/calc" name= calcform" type="calculadoraaction"... </action> faz o mapeamento da URL http://dominio/calc.do para a Action CalculadoraAction associa o path (do qual é removido o sufixo - ex: calc.do) a uma página qualquer (forward) ou a uma classe Action (type) copia os parâmetros da requisição HTTP para os atributos do JavaBean ActionForm referenciado por calcform
Action-mapping <action path="/calc" name= calcform" scope="request" input="/calc.jsp" validate="true" type="calculadoraaction"> <forward name="resultado" path="calc.jsp" /> < forward name="erro" path="calc.jsp" /> </action> scope: request/page/session/application validate: valida dados de entrada (true/false) input: página de tratamento de erro (se o método validade do ActionForm retornar null) forward: retorno da Action direciona fluxo de chamada de outra página JSP, HTML, servlet, etc.
Exemplo de Action
Exemplo de Action (cont.)
Actions Extende a classe Action Implementa o método padrão execute que será chamado por default pelo ActionServlet Pode implementar outros métodos e configurar no /WEB-INF/struts-config.xml qual será chamado de acordo com o parâmetro method=<método> Deve fazer um cast do form que recebe para o ActionForm definido no arquivo de configuração Recebe também request/response - framework baseado em servlet (pode usar para gravar dados na sessão) mapping - para informar o resultado da ação
Actions Normalmente um Action não retorna erros, pois estes serão tratados pelo validate do ActionForm Mas deve capturar e tratar as exceções, incluindo o redirecionamento para uma página de tratamento de erros
Definindo message-resources
Message-resources São arquivos de propriedades padrão do Java, da forma chave=valor São recursos da aplicação, para o armazenamento de mensagens O nome do arquivo pode ser salvo com o sufixo _xx, onde xx indica a língua, para efeito de tratamento de internacionalização
Exemplo de message-resources
Uso das mensagens
Taglibs do Struts Taglibs do struts: bean, html, logic e nested Geração facilitada de tags HTML Erros Mensagens internacionalizadas Iteração de coleções Acesso aos JavaBeans persistentes (escopo de page/request/session/application) Comparações (equal, greater, etc.) Padrões em string (match) Redirecionamento de páginas (forward, redirect) Atualmente: preferência por JSTL
Taglibs
Taglibs
Taglibs
JSTL JavaServer Pages Standard Tag Library (JSTL) JSTL disponibiliza um conjunto de 4 bibliotecas de tags Suporte a EL (Expression Language) do JSP 2.0 EL são definidas por ${ } na página JSP
EL ${anobject.aproperty} ${anobject["apropertyname"]} ${anobject[avariablecontainingpropertyname]} ${alist[4]} ${alist[somevariable]}
Taglibs
JSTL Inclusão das tag libraries na página JSP: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix= fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix= sql" uri="http://java.sun.com/jsp/jstl/sql" %> <%@ taglib prefix= x" uri="http://java.sun.com/jsp/jstl/x" %>
JSTL - core Mostra/atribui valores (c:out, c:set) Tratamento de exceções Controle de fluxo (c:if, c:choose, c:foreach, etc.) etc. <c:out value="${mycell}"/> <c:set var="customerid" value="$client:customernumber" scope="session" /> <c:if test="${status.totalvisits == 1000000}" var="visits"> Congratulations!</c:if> <table><c:foreach var="name" items="${customernames}"><tr><td><c:out value="${name}"/></td></tr></c:foreach></table>
JSTL - fmt Formatação <fmt:formatnumber value="1000.001" pattern="#,#00.0#"/> <fmt:formatnumber value="3456.789" type="currency" var="dollars"/> <jsp:usebean id="now" class="java.util.date" /><fmt:formatdate value="${now}" timestyle="long" datestyle="long"/>
JSTL - fmt Internacionalização Internationalization = i18n locale = br, en, fr, etc. (no web.xml ou via progr.) xxx.properties, xxx_en.properties, xxx_fr.properties,.. Ex: Resource Bundle /WEB-INF/classes/labels.properties hello=hello goodbye=goodbye <fmt:setbundle basename="labels"/> Hello: <fmt:message key="hello" /> Goodbye: <fmt:message key="goodbye" />
JSTL - sql Acesso a banco de dados na página JSP Não recomendável, contra o padrão MVC <sql:setdatasource url="jdbc:mysql://dbserver/dbname" driver="org.gjt.mm.mysql.driver user="scott password="tiger" /> <h1>reading database data</h1> <sql:query var="emps" sql="select * FROM Employee" /> <ul><c:foreach items="${emps.rows}" var="${emp}"> <li><c:out value="${emp.name}" /> </c:foreach></ul>
JSTL - x Parse XML <!-- Find and parse a XML document (somewhere on the WWW) --> <c:import url="http://somestuff.com?order=1001" var="xml"/> <x:parse xml="${xml}" var="doc"/> <x:out select="$doc/name"/> <x:out select="$doc/shippingaddress"/> <x:out select="$doc/deliverydate"/>
JSTL - x Extensible Stylesheet Language Transformations Specification (XSLT) transformations <c:import var="${xmlsource}" url="${somedocumenturl}" /> <c:import var="${xsltsource}" url="${anotherdocumenturl}" /> <!-- stylesheet --> <x:transform xml="${xmlsource}" xslt="${xsltsource}" > <table cellpadding="0" cellspacing="0" border="1" bgcolor="#ffffff"> <tr> <td><strong>artist</strong></td> <td><strong>album</strong></td> </tr> <xsl:for-each select="artists"> <tr> <td><xsl:value-of select="artist"/></td> <td><xsl:value-of select="album"/></td> </tr> </xsl:for-each> </table>
Deploy Comprima o diretório raiz (ex: usando o Winzip) Renomeie para.war Copie para o diretório de aplicações do seu servlet container Ex: <TOMCAT>/webapps/calculadora.WAR O contexto será criado e a aplicação estará disponível em http://localhost:8080/calculadora Outras opções build (Ant) para gerar o WAR e copiar para o /webapps do Tomcat plug-in Tomcat mapear diretório do projeto no contexto do Tomcat
TOMCAT Admin
TOMCAT Manager
Projeto no Eclipse
struts-blank É fornecida como exemplo para novas aplicações Struts Já inclui os arquivos de configuração no diretório /WEB- INF web.xml struts-config.xml Já inclui todas as classes necessárias em /WEB-INF/lib Arquivo WAR para deploy: /webapps/struts-blank
Struts-blank (from README) It's an "empty" application provided to help you get started on your own project. Just copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent), and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container, and you are on your way!
struts-blank
struts-mailreader A aplicação struts-mailreader acompanha a distribuição do Struts Vamos utilizar essa aplicação para exemplificiar como criar, compilar, executar e debugar um projeto Struts completo utilizando a IDE Eclipse Tutorial em How to setup a basic Struts Action Framework project using Eclipse IDE http://struts.apache.org/struts-action/faqs/eclipse.html
struts-mailreader Crie um diretório para o projeto e descompacte a aplicação /webapps/struts-mailreader.war que acompanha a distribuição do Struts
struts-mailreader Remova o diretório /META-INF porque este será criado durante o processo de build/jar/war (Ant) Crie um build.xml na raiz do projeto
build.xml
build.xml (ações principais)
Criando um novo projeto File > New > Project > Java Project
Criando um novo projeto Nome e diretório do projeto
Criando um novo projeto O Eclipse detecta fontes e bibliotecas
Criando um novo projeto Configurar o diretório de output para as classes compiladas Incluir sempre o pacote de servlets no projeto Incluído no servlet container do servidor web (ex: Tomcat) Ex: <TOMCAT>/common/lib/servlet.jar ou <TOMCAT>/common/lib/servlet-api.jar e <TOMCAT>/common/lib/jsp-api.jar
Compile com o build.xml (Run As Ant Build)
Deploy Modifique o build.xml para também fazer o deploy <target name="main" depends="clean, prep, cleanwebapp, compile, war, deploy"/>
Enjoy: http://localhost:8080/struts-mailreader
Dynaforms DynaActionForms tentativa de minimizar a criação de classes ActionForms somente para especificar containers de dados todos os atributos definidos como String declaração no struts-config.xml
Dynaforms DynaValidatorForms uso do plugin Validator forms derivam de ValidatorForm arquivos de configuração validation.xml validator-rules.xml validação de dados automática pelo Struts através do plugin, no servidor e no cliente (Javascript) regras de validação pré-definidas required, minlength, maxlength, integer, date, mask, url, email, etc. possibilidade de criar novos validadores classe para o servidor e código javascript para ser usado no cliente
Exemplo com dynaforms
DynaActionForms e DynaValidatorForms (struts-config.xml)
DynaValidatorForms (validation.xml)
DynaActionForms e DynaValidatorForms Recuperação dos atributos do form: na Action getmap() ou getstring( nome-do-atributo ) nas páginas JSP variável ${form.map.nome-do-atributo} tag <html:errors property="num1" /> mensagens de erro são definidas no arquivos de mensagens para cada regra de validação errors.required={0} is required. errors.minlength={0} can not be less than {1} characters. errors.maxlength={0} can not be greater than {1} characters. errors.integer={0} must be an integer. errors.date={0} is not a date. errors.email={0} is an invalid e-mail address.
/WEB-INF/classes/Mensagens.properties
DynaActionForms e DynaValidatorForms
Plugin
Validator-rules.xml
Na página JSP
Filters Definido pelo padrão de servlets Implementa javax.servlet.filter Usado como pré- ou pós-processamento de servlets Métodos init(), destroy(), dofilter() Uso em contadores, login, etc. Configuração no arquivo web.xml da aplicação
Filters
Filters
Comparativo Struts 1 x Struts 2