Struts – Introdução Rápida
Jobson Ronan {[email protected]}
O que é?

Um framework para facilitar a implementação de uma arquitetura MVC em
aplicações web

Oferece



Um servlet controlador configurável (Front Controller) através de arquivos XML
externos, que despacham requisições a classe Action (Command) implementados
pelo desenvolvedor
Uma vasta coleção de taglibs JSP
Classes ajudantes que oferecem suporte a tratamento de XML, preenchimento de
JavaBeans, validação de formulários e gerenciamento externo de conteúdo
Componentes

Model (M)


View (V)


Geralmente um objeto java (JavaBean)
Geralmente uma página HTML ou JSP. Embora o Struts seja independente
da camada de apresentação (ex. velstruts)
Controller (C)

org.apache.struts.action.ActionServlet ou subclasse
Componentes

Classes ajudantes






FromBean: Encapsula dados de um formulário HTML (M)
ActionError(s): Encapsula dados de Erros (M) (deprecated 1.2)
ActionMessage(s): Encapsula dados de Mensagens (M)
Custon tags: Encapsulam lógica de apresentação (V)
Actions: implementam lógica comandos (C)
ActionForward: Encapsulam lógica de redirecionamento (C)
Como funciona?

Componentes-chave:



ActionServlet: despachante de ações
Action: classe estendida por cada ação (comando) a ser implementada
(Command pattern)
struts-config.xml: arquivo onde se definem mapeamentos entre ações,
páginas, beans e dados
JSP
Form
Bean
http
lê
Bean
despacha
prenche
delega
Action
Servlet
Action
Dados, Dao
ou Session
Facade
Como usar?

struts-blank.war

Um template básico para um aplicação web já configurada para
usar o struts

web.xml
<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>
Como usar?

web.xml (cont.)
...
<!-- Standard Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
...
<!-- 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>
...
Como usar?

struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<!-- ============================================== Form Bean Definitions -->
<form-beans>
</form-beans>
<!-- ======================================= Global Exception Definitions -->
<global-exceptions>
</global-exceptions>
<!-- ========================================= Global Forward Definitions -->
<global-forwards>
<forward name="welcome" path="/Welcome.do"/>
</global-forwards>
Como usar?

struts-config.xml (cont.)
...
<!-- ========================================= Action Mapping Definitions -->
<action-mappings>
<action path="/Welcome“ forward="/pages/Welcome.jsp"/>
</action-mappings>
<!-- =========================================== Controller Configuration -->
<controller
processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>
<!-- ====================================== Message Resources Definitions -->
<message-resources parameter="MessageResources" />
...
Entendendo...

Index.jsp
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<logic:redirect forward="welcome"/>
Actions

Implementando a ação cadastrar novo filme
package pec;
//imports
public class CadastrarFilmeAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
//código de efetuar cadastro...
return mapping.findForward("sucesso");
}
}
Actions

Declarando
<!-- ========================================= Action Mapping Definitions -->
<action-mappings>
<action path="/Welcome“ forward="/pages/Welcome.jsp"/>
<action
path="/cadastrarFilme"
type="pec.CadastrarFilmeAction"/>
<forward
name="sucesso"
path="pages/cadastroSucesso.jsp"/>
</action-mappings>
...
ActionForm

Nossa ação precisa de um formulário

Java bean comum
public class CadastroFilmeForm extends ActionForm {
private
private
private
private
String
String
String
String
idRef;
nomeOriginal;
nomeNacional;
numeroCopias;
//get´s e set´s
}

As propriedades do bean são populadas de forma transparente
ActionForm

ActionFroms podem ser validados
package pec;
Commons validator
public class CadastroFilmeForm extends ActionForm {
//...
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest response) {
ActionErrors validatorErros = new ActionErrors();
if (idRef == null || idRef.trim().equals(""))
validatorErros.add("idRef", new ActionMessage(
"filme.cadastro.idRef.required"));
if (nomeOriginal == null || nomeOriginal.trim().equals(""))
validatorErros.add("nomeOriginal", new ActionMessage(
"filme.cadastro.nomeOriginal.required"));
if (numCopias == null || numCopias.trim().equals(""))
validatorErros.add("numCopias", new ActionMessage(
"filme.cadastro.numCopias.required"));
else if (!GenericValidator.isInt(numCopias))
validatorErros.add("numCopias", new ActionMessage(
"filme.cadastro.numCopias.notInt"));
return validatorErros;
}
}
ActionForm
Formulário
(HTML/JSP)
Request recebido pelo controler
Cria ou recicla um ActionForm
Chama reset()
Formulário
(HTML/JSP)
Guarda o ActionForm no
escopo desejado
Com menssagens de erro!
Popula ActionForm a partir do request
Dá um forward para o input
Página Sucesso
(HTML/JSP)
Validação falha
Chama validate() do ActionForm
Validação ok
Chama execute() do Action
Dá um forward para “sucesso”
ActionForm

ActionForm são firewalls dos Actions


O ActionForms só chegam aos actions caso tenham sido
validados
Cuidado com a definição dos tipos

Se o usuário digita um valor, torne esta propriedade uma String
ActionForm

Declarando (struts-config.xml)
...
<form-beans>
<form-bean name="cadastroFilmeForm" type="pec.CadastrarFilmeForm"/>
</form-beans>
...
<action-mappings>
...
<action
path="/cadastrarFilme"
type="pec.CadastrarFilmeAction"
name="cadastroFilmeForm"
input="/cadastrarNovoFilme.jsp">
<forward name="sucesso" path="/pages/cadastroFilmeSuc.jsp" />
</action>
...
ActionForm

De volta ao action...
package pec;
//imports
public class CadastrarFilmeAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
CadastroFilmeForm cadastroForm = (CadastroFilmeForm) form;
//código de efetuar cadastro...
return mapping.findForward("sucesso");
}
}

Garantia de validação!
ActionForm

cadastrarNovoFilme.jsp
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<html:html locale="true">
<head>
<title>Cadastrar Filme</title>
</head>
<body>
<h1>Cadastrar Filme</h1>
<html:errors />
<table>
<html:form action="cadastrarFilme">
<tr>
<td><bean:message key="filme.cadastro.idRef" />*</td>
<td><html:text property="idRef" /></td>
</tr>
<td><bean:message key="filme.cadastro.nomeOriginal" />*</td>
<td><html:text property="nomeOriginal" /></td>
<tr>
<td><bean:message key="filme.cadastro.nomeNacional" /></td>
<td><html:text property="nomeNacional" /></td>
</tr>
...
ActionForm

cadastrarNovoFilme.jsp (cont)
...
<tr>
<td><bean:message key="filme.cadastro.numCopias" />*</td>
<td><html:text property="numCopias" /></td>
</tr>
<tr>
<td colspan="2">
<html:submit value="Cadastrar"/>
<html:cancel value="Cancelar"/>
</td>
</tr>
</html:form>
</table>
</body>
</html:html>
ActionForm

MessageResources.properties
# -- cadastro filme success -filme.cadastro.title=Filme Cadastrado
filme.cadastro.heading=Sucesso!
filme.cadastro.message=Filme Cadastrado com sucesso!
# -- cadastro filme form -filme.cadastro.idRef=Id Ref
filme.cadastro.nomeOriginal=Nome Original
filme.cadastro.nomeNacional=NomeNacional
filme.cadastro.numCopias=Número de Cópias
filme.cadastro.idRef.required=Id Ref Requerido
filme.cadastro.nomeOriginal.required=Nome Original Requerido
filme.cadastro.numCopias.required=Número de Cópias Requerido
filme.cadastro.numCopias.notInt=Número de Cópias inválido
ActionForm

ActionForm também podem ser usados para fornecer dados
...
<form-beans>
<form-bean name="filmeForm" type="pec.FilmeForm"/>
</form-beans>
...
<action-mappings>
...
<action
path="/verDadosFilme"
type="pec.VerDadosFilmeAction"
name="filmeForm"
scope="request"
validate="false">
<forward name="sucesso" path="/pages/filmeForm.jsp" />
</action>
...
ActionForm

Problemas


Muitos objetos de domínio duplicados
Muito código de cópia de propriedades


Usar BeanUtils.copyProperties(Object dest, Object src);
Grande quantidade de Froms com grandes quantidades de
propriedades pode ser difícil de manter

Usar DynaActionForm?
Exceções

Struts dá suporte a um tratamento de exceções
declarativo

Suponha que o código de negócio de
VerDadosFilmeAction lance a exceção
pec.FilmeNaoEncontradoException
<action
path="/verDadosFilme"
type="pec.VerDadosFilmeAction"
name="filmeForm"
scope="request"
validate="false">
<forward name="sucesso" path="/pages/filmeForm.jsp" />
<exception key="filmeNaoEncontrado.exception"
type="pec.FilmeNaoEncontradoException"
path="/pages/exception.jsp" />
</action>
...
O que mais?

Outros tipos de actions


DispatchAction: quando tempos um formulário que terá mais de
uma ação associada
Plugins


Struts-Validator
Struts-Tiles
Exercícios

Implementar o Exercício de Mensagens usando Struts
Download

pec-11-struts