Agenda• Tags do Struts• DispatchAction• Multiplos arquivos de configuração• Command Pattern• DynaActionForm• Array’s• Validation Framework• JSP2.0 Expression Language
html• html:submit• html:cancel• html:button• html:hidden• html:checkbox• html:messages• html:errors• html:file• html:form• html:javascript• html:image/img
html• html:link• html:messages• html:multibox• html:selection/option/options/optionsCollection• html:radio• html:reset• html:rewrite• html:text• html:textarea
bean• bean:cookie• bean:header• bean:parameter• bean:define• bean:include• bean:message• bean:page• bean:resource• bean:size
Preparação do Ambiente• Crie dois projetos (SistemaDeNoticias e
SistemaDeNoticiasWeb)• Configure o nome do contexto web para
noticia• Adicione a lib struts-extras.jar. Utilize,
claro, a versão mais recente• Crie as páginas Menu.jsp e index.jsp
Menu.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Menu :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table><tr><td><html:link page="/PaginaInicial.do">Página Inicial | </html:link></td></tr></table></body></html>
DispatchAction• Subtipo de Action que implementa o padrão
Command• Ao invés de ter várias classes Action, você
centraliza todas as ações num único DispatchAction e seleciona a uma ação específica através de um parâmetro (comando) na url
• Muito prático, economiza várias classes, pois uma mesma Action responde a várias solicitações
NoticiaActionpackage net.noticias.action;
import java.util.*;import javax.servlet.http.*;import net.noticias.form.*;import net.noticias.persistencia.*;import org.apache.struts.action.*;import org.apache.struts.actions.*;public class NoticiaAction extends DispatchAction { public ActionForward listar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DAONoticia daoNoticia = new DAONoticia(); request.setAttribute("noticias", daoNoticia.consultaNoticias()); return mapping.findForward("MostrarPaginaDeConsulta"); }}
Invocando um método do Dispatch• Essa é uma subclasse de DispatchAction• Todos os métodos devem ter a seguinte lista de
parâmetros:– ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response
• O nome do método (no nosso caso listar) será invocado pela url “Noticia.do?comando=listar”
• A url completa é http://localhost:8080/noticia/Noticia.do?comando=listar
Parâmetros do dispath• Noticia.do
– Chama a ação respectiva no struts-config.xml, acionando a classe NoticiaAction
– O método listar faz carrega uma coleção de notícias na variável noticias e chama o forward MostrarPaginaDeConsulta abrindo a página ConsultarNoticias.jsp
• comando=listar– Parâmetro http utilizado para escolher o
método
NoticiaFormpackage net.noticias.form;
import org.apache.struts.action.*;
public class NoticiaForm extends ActionForm { private String id; private String texto; private String titulo; private String data; private String tipoDeNoticia; private String[] noticiasSelecionadas; {...}}
Detalhes• Crie os métodos getter e setters• Temos um atributo do tipo array• Array’s são utilizados para recuperar valores
de componentes como listas de seleção múltipla e checkboxes
• Essa é uma característica do html, não do Struts
DAONoticiapackage net.noticias.persistencia;
import java.util.*;import net.noticias.form.*;
public class DAONoticia { public Collection<NoticiaForm> consultaNoticias() { Collection<NoticiaForm> lista = new ArrayList<NoticiaForm>(); NoticiaForm n = new NoticiaForm(); n.setId("1"); n.setData("01-01-2001"); n.setTexto("Texto da notícia 1"); n.setTitulo("Título da notícia 1"); lista.add(n); n = new NoticiaForm(); n.setId("2"); n.setData("01-01-2002"); n.setTexto("Texto da notícia 2"); n.setTitulo("Título da notícia 2"); lista.add(n); n = new NoticiaForm(); n.setId("3"); n.setData("01-01-2003"); n.setTexto("Texto da notícia 3"); n.setTitulo("Título da notícia 3"); lista.add(n); return lista; }
DAONoticia public NoticiaForm consultaNoticiaPeloId(String id) { NoticiaForm n = new NoticiaForm(); n.setId(id); n.setData("01-01-2001"); n.setTexto("Texto da notícia " + id); n.setTitulo("Título da notícia " + id); n.setTipoDeNoticia("3"); return n; }}
web.xml<?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><display-name>Sistema de Notícias</display-name><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,/WEB-INF/struts-config-form-beans.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>
web.xml<!-- Standard Action Servlet Mapping --><servlet-mapping><servlet-name>action</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>
<taglib><taglib-uri>/tags/struts-bean</taglib-uri><taglib-location>/WEB-INF/lib/struts-bean.tld</taglib-location></taglib><taglib><taglib-uri>/tags/struts-html</taglib-uri><taglib-location>/WEB-INF/lib/struts-html.tld</taglib-location></taglib><taglib><taglib-uri>/tags/struts-logic</taglib-uri><taglib-location>/WEB-INF/lib/struts-logic.tld</taglib-location></taglib>
</web-app>
Múltiplos arquivos de configuração• Arquivos de configuração tendem a crescer
bastante, dificultando sua visualização• Nesse exemplo separamos os form-beans
do resto da aplicação• Para isso, adicione os arquivos de
configuração no parâmetro config separados por vírgula
struts-config.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"><struts-config><global-forwards><forward name="AbrirPaginaPrincipal" path="/PaginaInicial.do" /></global-forwards><action-mappings><action path="/PaginaInicial" forward="/Menu.jsp" /><action path="/Noticia" type="net.noticias.action.NoticiaAction" name="noticiaForm"
parameter="comando"><forward name="MostrarPaginaDeEdicao" path="/EditarNoticia.jsp" /><forward name="MostrarPaginaDeConsulta" path="/ConsultarNoticias.jsp" /></action></action-mappings><message-resources parameter="MessageResources" /></struts-config>
Command Pattern• A ação Noticia deve ter um parâmetro• O nome padrão é comando• Esse parâmetro será usado para escolher o
método a ser executado
Forwards globais• São forwards que podem ser utilizados por
todos os actions<global-forwards><forward name="AbrirPaginaPrincipal" path="/PaginaInicial.do" /></global-forwards>
struts-config-form-beans.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration
1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"><struts-config><form-beans><form-bean name="noticiaForm"
type="net.noticias.form.NoticiaForm" /><form-bean name="tipoDeNoticiaForm"
type="net.noticias.form.TipoDeNoticiaForm" /></form-beans></struts-config>
ConsultarNoticias.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Consulta Notícias :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><tr><td colspan=4 align=center><h2>Consulta Notícias</h2></td></tr><tr><td align=center>Data</td><td>Título</td><td>Texto</td><td>Editar</td>
ConsultarNoticias.jsp</tr><logic:iterate id="noticia" name="noticias"><tr><td align=center><bean:write name="noticia" property="data" /></td><td><bean:write name="noticia" property="titulo" /></td><td><bean:write name="noticia" property="texto" /></td><td><html:link page="/Noticia.do?comando=editar"paramId="idDaNoticia" paramName="noticia" paramProperty="id"><html:image src="imagens/edit.gif" /></html:link></tr></logic:iterate>
<tr><td colspan=4 align=center><html:buttononclick="window.location='PaginaInicial.do'" property="btnVoltar"value="Sair" /></td></table></body></html>
html:link e html:buttonhtml:link<html:link page="/Noticia.do?comando=editar" paramId="idDaNoticia" paramName="noticia"
paramProperty="id">
• /Noticia.do?comando=editar – chama a mesma action (NoticiaAction) executando dessa vez o comando editar
• paramId – nome do parâmetro passado na url• paramName – nome do bean• paramProperty – valor da propriedade
html:button<html:button onclick="window.location='PaginaInicial.do'" property="btnVoltar" value="Sair" />• Botão com javascript para voltar à página inicial
Novo Menu.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Menu :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table><tr><td><html:link page="/PaginaInicial.do">Página Inicial | </html:link></td><td><html:link page="/Noticia.do?comando=listar">Notícia | </html:link></td></tr></table></body></html>
Comando editar• Esse novo comando consulta uma notícia
pelo parâmetro idDaNoticia• Teremos um combobox com os tipos de
notícia, para montá-lo precisamos da coleção de tipos
• Em seguida é só chamar o forward MostrarPaginaDeEdicao
NoticiaAction public ActionForward editar(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("idDaNoticia"); DAONoticia daoNoticia = new DAONoticia(); DAOTipoDeNoticia daoTipo = new DAOTipoDeNoticia(); Collection<TipoDeNoticiaForm> tipos =
daoTipo.consultaTiposDeNoticia(); NoticiaForm n = daoNoticia.consultaNoticiaPeloId(id); request.setAttribute("noticia", n); request.setAttribute("tipos", tipos); return mapping.findForward("MostrarPaginaDeEdicao"); }
EditarNoticia.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Editar Notícia :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><html:form action="/Noticia?comando=confirmar"><tr><td colspan=3 align=center><h2>Editar Notícia</h2>
EditarNoticia.jsp</td></tr><tr><td align=center>ID</td><td><html:text name="noticia" property="id" /></td></tr><tr><td align=center>Data</td><td><html:text name="noticia" property="data" /></td></tr><tr><td align=center>Título</td><td><html:text name="noticia" property="titulo" /></td></tr><tr><td align=center>Texto</td><td><html:text name="noticia" property="texto" /></td></tr><tr><td colspan=3> <tr>
EditarNoticia.jsp<td align=center>Tipo de notícia:<td colspan=2><html:select name="noticia" property="tipoDeNoticia"><html:optionsCollection name="tipos" value="id" label="descricao" /></html:select></td></tr><tr><td colspan=3 align=center><html:submit value="Confirmar" /> <html:button onclick="action='Noticia.do?comando=listar';submit()" value="Sair"property="btnSair" /></td></tr></html:form></table></body></html>
html:form/select<html:form action="/Noticia?comando=confirmar">• Os dados dessa página serão enviados para o método confirmar através da
NoticiaForm<html:select name="noticia" property="tipoDeNoticia"><html:optionsCollection name="tipos" value="id" label="descricao" /></html:select>• html:select – tag para montar uma combobox, inclusive de seleção múltipla
– name, property – nome/propriedade do bean• html:optionsCollection – valores do combobox
– name – nome da collection– value – valor de cada option (id de cada tipoDeNoticia)– label – valor que será mostrado ao usuário– Se o id do bean for igual ao id da combo, essa opção virá selecionada
html:submit<html:submit value="Confirmar" /> • Submete o form para a ação do form<html:button onclick="action='Noticia.do?comando=listar';submit()" value="Sair"property="btnSair" />• Muda o valor da ação através de javascript e a submete
Confirmando a ação• O método confirmar recebe os dados do
formulário de edição e faz a persistência dos dados
• Nossos exemplos não têm bancos de dados, mas um DAO acessando o Hibernate poderia fazer isso facilmente
NoticiaAction public ActionForward confirmar(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response) { NoticiaForm f = (NoticiaForm) form; System.out.println("Dados informados pelo usuário"); System.out.println("ID: " + f.getId()); System.out.println("Data: " + f.getData()); System.out.println("Título: " + f.getTitulo()); System.out.println("Texto: " + f.getTexto()); System.out.println("ID do Tipo: " + f.getTipoDeNoticia()); return mapping.findForward("AbrirPaginaPrincipal"); }
Camadas de Persistência e Negócio• O Struts não fornece nenhuma API para a
camada de negócio• Seguindo as melhores práticas, a Action
deveria acessar um fachada• No nosso exemplo temos acessamos um
DAO diretamente• O próximo passo seria acessar efetivamente
o banco relacional
TipoDeNoticiaFormpackage net.noticias.form;
import org.apache.struts.action.*;
public class TipoDeNoticiaForm extends ActionForm {
private String id; private String descricao; {...}}
Alternativa• A classe TipoDeNoticia é bastante simples,
tem apenas código e descrição• Esse tipo de classe é forte candidata a se
transformar em formulário dinâmico, discutido posteriormente
struts-config.xml• Acrescente a ação respectiva no arquivo de
configuração (siga o padrão da ação Noticia)
• Já é possível notar a quantidade reduzida de classes Action
<action path="/TipoDeNoticia" name="tipoDeNoticiaForm" type="net.noticias.action.TipoDeNoticiaAction" parameter="comando">
<forward name="MostrarPaginaDeEdicao" path="/EditarTipoDeNoticia.jsp" /><forward name="MostrarPaginaDeConsulta" path="/ConsultarTipoDeNoticia.jsp" /></action>
TipoDeNoticiaActionpackage net.noticias.action;
import java.util.*;import javax.servlet.http.*;import net.noticias.form.*;import net.noticias.persistencia.*;import org.apache.struts.action.*;import org.apache.struts.actions.*;
public class TipoDeNoticiaAction extends DispatchAction { public ActionForward editar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { String id = request.getParameter("idDoTipo"); DAOTipoDeNoticia dao = new DAOTipoDeNoticia(); TipoDeNoticiaForm tipo = dao.consultaTipoDeNoticiaPeloId(id); request.setAttribute("tipo", tipo); return mapping.findForward("MostrarPaginaDeEdicao"); }
TipoDeNoticiaAction public ActionForward listar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DAOTipoDeNoticia d = new DAOTipoDeNoticia(); Collection<TipoDeNoticiaForm> lista = d.consultaTiposDeNoticia(); request.setAttribute("tipos", lista); return mapping.findForward("MostrarPaginaDeConsulta"); }
public ActionForward confirmar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { TipoDeNoticiaForm f = (TipoDeNoticiaForm) form; System.out.println("Dados informados pelo usuário"); System.out.println("ID: " + f.getId()); System.out.println("Data: " + f.getDescricao()); return mapping.findForward("AbrirPaginaPrincipal"); }}
DAOTipoDeNoticiapackage net.noticias.persistencia;
import java.util.*;import net.noticias.form.*;
public class DAOTipoDeNoticia { public Collection<TipoDeNoticiaForm> consultaTiposDeNoticia() { Collection<TipoDeNoticiaForm> lista = new ArrayList<TipoDeNoticiaForm>(); TipoDeNoticiaForm n = new TipoDeNoticiaForm(); n.setId("1"); n.setDescricao("Tipo 1"); lista.add(n); n = new TipoDeNoticiaForm(); n.setId("2"); n.setDescricao("Tipo 2"); lista.add(n); n = new TipoDeNoticiaForm(); n.setId("3"); n.setDescricao("Tipo 3"); lista.add(n); return lista; }
public TipoDeNoticiaForm consultaTipoDeNoticiaPeloId(String id) { TipoDeNoticiaForm tipo = new TipoDeNoticiaForm(); tipo.setId(id); tipo.setDescricao("Tipo " + id); return tipo; }}
ConsultarTipoDeNoticia.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Consulta Tipos de Notícia :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><tr><td colspan=4 align=center><h2>Consulta Tipo de Notícia</h2></td></tr><tr><td align=center>ID</td><td>Descrição</td><td>Editar</td></tr>
ConsultarTipoDeNoticia.jsp<logic:iterate id="tipo" name="tipos"><tr><td align=center><bean:write name="tipo" property="id" /></td><td><bean:write name="tipo" property="descricao" /></td><td><html:link page="/TipoDeNoticia.do?comando=editar"paramId="idDoTipo" paramName="tipo" paramProperty="id"><html:img src="imagens/edit.gif" border="0" /></html:link></tr></logic:iterate>
<tr><td colspan=4 align=center><html:buttononclick="window.location='PaginaInicial.do'" property="btnVoltar"value="Sair" /></td></table></body></html>
Consultas• As consultas seguem o mesmo princípio: a
Action salva uma coleção de objetos numa variável (geralmente) de sessão e através do logic:iterate a gente escreve os vários valores na tela
EditarTipoDeNoticia.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html:html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Editar Tipo de Notícia :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><html:form action="/TipoDeNoticia?comando=confirmar"onsubmit="return validateTipoDeNoticiaForm(this);"><tr><td colspan=3 align=center><h2>Edição de Tipo de Notícia</h2></td></tr>
EditarTipoDeNoticia.jsp<tr><td align=center>ID</td><td><html:text name="tipo" property="id" /></td></tr><tr><td align=center>Descrição</td><td><html:text name="tipo" property="descricao" /></td></tr><tr><td colspan=3 align=center><html:submit value="Confirmar" /><html:buttononclick="action='TipoDeNoticia.do?comando=listar';submit()"value="Sair" property="btnSair" /></td></tr></html:form></table></body></html:html>
Edição• O id de um dos objetos da lista é enviado
pela url para a Action, executando o comando de edição
• A aplicação deve recuperar o objeto do banco e guardar seus valores em uma variável de sessão
• A página de edição espera essa variável e escreve seus valores através das tags html
DynaActionForm• Formulário dinâmico baseado na interface
java.util.Map• Não é necessário criar uma classe
ActionForm• Configurado no struts-config como um
simples <form-bean>• Grande flexibilidade• Não utiliza reflexão
struts-config-form-beans.xml• Adicione o form-bean para Fonte <form-bean name="fonteForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="id" type="java.lang.String" /> <form-property name="descricao" type="java.lang.String" /></form-bean>
• Os atributos podem usar todas as classes wrapper, collections e arrays
• Não é necessário criar a classe!
struts-config.xml• Acrescente a Action para o novo form-bean• Veja a diferença: nenhuma<action path="/Fonte" type="net.noticias.action.FonteAction" name="fonteForm"
parameter="comando"><forward name="MostrarPaginaDeEdicao" path="/EditarFonte.jsp" /><forward name="MostrarPaginaDeConsulta" path="/ConsultarFontes.jsp"></forward></action>
FonteActionpackage net.noticias.action;
import javax.servlet.http.*;import net.noticias.persistencia.*;import org.apache.struts.action.*;import org.apache.struts.actions.*;
public class FonteAction extends DispatchAction { public ActionForward listar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DAOFonte dao = new DAOFonte(); request.setAttribute("fontes", dao.consultaFontes()); return mapping.findForward("MostrarPaginaDeConsulta"); }}
Poucas diferenças• o método para listar as fontes não difere dos
outros• A principal diferença fica por conta do DAO,
pois os formulários dinâmicos não têm classes concretas
• Todos são implementados através de mapas
DAOFontepackage net.noticias.persistencia;
import java.util.*;
public class DAOFonte { public Collection<Map<String, String>> consultaFontes() { Collection<Map<String, String>> lista = new ArrayList<Map<String, String>>(); Map<String, String> mapa = new HashMap<String, String>(); mapa.put("id", "1"); mapa.put("descricao", "Fonte 1"); lista.add(mapa); mapa = new HashMap<String, String>(); mapa.put("id", "2"); mapa.put("descricao", "Fonte 2"); lista.add(mapa); mapa = new HashMap<String, String>(); mapa.put("id", "3"); mapa.put("descricao", "Fonte 3"); lista.add(mapa); return lista; }
public Map<String, String> consultaFontePeloId(String id) { Map<String, String> mapa = new HashMap<String, String>(); mapa.put("id", id); mapa.put("descricao", "Tipo " + id); return mapa; }}
Tudo é Map• Como não há classe concreta, nosso valores
ficam encapsulados em mapas• Para fazer a persistência num banco
relacional, você deve implementar utilitários que mapeiem os mapas para seus DTO’s
ConsultarFontes.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Consulta Notícias :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><tr><td colspan=4 align=center><h2>Consulta Fontes</h2></td></tr><tr><td align=center>ID</td><td>Descrição</td><td>Editar</td></tr>
ConsultarFontes.jsp<logic:iterate id="fonte" name="fontes"><tr><td align=center><bean:write name="fonte" property="id" /></td><td><bean:write name="fonte" property="descricao" /></td><td><html:link page="/Fonte.do?comando=editar"paramId="idDaFonte" paramName="fonte" paramProperty="id"><html:image src="imagens/edit.gif" /></html:link></tr></logic:iterate>
<tr><td colspan=4 align=center><html:buttononclick="window.location='PaginaInicial.do';submit()"property="btnVoltar" value="Sair" /></td></tr></table></body></html>
Consulta com DynaActionForm• A página de consulta é idêntica a todas as
outras• Atenção ao DAO, pois temos que usar
apenas Map’s
FonteAction public ActionForward editar(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response) {
DAOFonte dao = new DAOFonte(); String id = request.getParameter("idDaFonte"); request.setAttribute("fonte",
dao.consultaFontePeloId(id)); return
mapping.findForward("MostrarPaginaDeEdicao"); }
EditarFonte.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Editar Fonte :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><html:form action="/Fonte?comando=confirmar"><tr><td colspan=3 align=center><h2>Editar Fonte</h2></td></tr>
EditarFonte.jsp<tr><td align=center>ID</td><td><html:text name="fonte" property="id" /></td></tr><tr><td align=center>Descrição</td><td><html:text name="fonte" property="descricao" /></td></tr><tr><td colspan=3 align=center><html:submit value="Confirmar" /> <html:buttononclick="action='Fonte.do?comando=listar';submit()" value="Sair"property="btnSair" /></td></tr></html:form></table></body></html>
Edição com DynaActionForm• Para preencher a página de edição
precisamos fornecer um mapa com os atributos da fonteForm
public Map<String, String> consultaFontePeloId(String id) { Map<String, String> mapa = new HashMap<String, String>(); mapa.put("id", id); mapa.put("descricao", "Tipo " + id); return mapa; }
A utilização de array’s• Em várias situações precisamos utilizar estruturas complexas,
mas quando trabalhamos com ambientes web, temos uma série de limitações
• Não é interessante, por exemplo, transmitir objetos entre as requisições de usuário. Esse tipo de recurso deve ser evitado ao máximo
• Os valores transmitidos entre as páginas são sempre do tipo String e quando temos vários componentes em uma requisição com o mesmo nome, o request encapsula seus valores em um array
• E trabalhar com array sempre foi razoavelmente complicado
struts-config.xml• Abaixo está a Action dessa nova funcionalidade• O escopo está configurado para request. Depois do
primeiro teste, mude para session• O parâmetro attribute=“noticia” cria a variável
noticia e a passa para a página seguinte, preenchida com os dados da página atual
<action path="/SelecaoMultiplaDeNoticias" type="net.noticias.action.SelecaoMultiplaDeNoticiasAction" name="noticiaForm" attribute="noticia" scope="request" parameter="comando">
<forward name="MostrarPaginaDeConsulta" path="/SelecaoMultiplaDeNoticias.jsp" /><forward name="MostrarNoticiasSelecionadas"
path="/ResultadoDaSelecaoMultiplaDeNoticias.jsp" /></action>
SelecaoMultiplaDeNoticiasActionpackage net.noticias.action;
import javax.servlet.http.*;import net.noticias.persistencia.*;import org.apache.struts.action.*;import org.apache.struts.actions.*;
public class SelecaoMultiplaDeNoticiasAction extends DispatchAction { public ActionForward mostrarTodasAsNoticias(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DAONoticia d = new DAONoticia(); request.setAttribute("noticias", d.consultaNoticias()); return mapping.findForward("MostrarPaginaDeConsulta"); }
public ActionForward mostrarAsNoticiasSelecionadas(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { return mapping.findForward("MostrarNoticiasSelecionadas"); }}
Página de seleção• A Action simplesmente envia uma coleção
de notícias para a página de seleção que mostra seus valores com uma tag html:selection
SelecaoMultiplaDeNoticias.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Consulta Notícias :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><html:formaction="/SelecaoMultiplaDeNoticias.do?comando=mostrarAsNoticiasSelecionadas"><bean:size id="quantidadeDeNoticias" name="noticias" /><tr><td colspan=2 align=center><h2><bean:write name="quantidadeDeNoticias" /> Notícia(s)Cadastrada(s)</h2></td>
SelecaoMultiplaDeNoticias.jsp</tr><tr><td align=center>Notícias:<td><html:select name="noticia" property="noticiasSelecionadas"multiple="true"><html:optionsCollection name="noticias" value="id" label="titulo" /></html:select></td></tr><tr><td colspan=2 align=center><html:button onclick="submit()"property="btnSelecionar" value="Selecionar" /></td></tr></html:form></table></body></html>
html:select e bean:size<html:select name="noticia" property="noticiasSelecionadas" multiple="true"> <html:optionsCollection name="noticias" value="id" label="titulo" /></html:select>• multiple=“true”
– Indica que esse select aceitará seleção múltipla– Os itens selecionados serão armazenados em um array do formBean
<bean:size id="quantidadeDeNoticias" name="noticias" />• Cria a variável quantidadeDeNoticias com a quantidade de itens do bean
noticias<bean:write name="quantidadeDeNoticias" />• Escreve o valor da variável quantidadeDeNoticias
ResultadoDaSelecaoMultiplaDeNoticias.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"%><%@ taglib uri="/tags/struts-html" prefix="html"%><%@ taglib uri="/tags/struts-bean" prefix="bean"%><%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>.: Seleção Múltipla de Notícia :.</title><link rel="stylesheet" href="css/Estilo.css" type="text/css" /></head><body><table width=90% border><bean:size id="quantidadeDeNoticiasSelecionadas" name="noticia"property="noticiasSelecionadas" /><tr><td colspan=2 align=center><h2><bean:write name="quantidadeDeNoticiasSelecionadas" />Notícia(s) Selecionada(s)</h2></td>
ResultadoDaSelecaoMultiplaDeNoticias.jsp</tr><tr><td align=center>ID</td></tr><logic:iterate id="idDaNoticiaSelecionada"property="noticiasSelecionadas" name="noticia"><tr><td align=center><bean:write name="idDaNoticiaSelecionada" /></td></tr></logic:iterate><tr><td colspan=2 align=center><html:buttononclick="window.location='SelecaoMultiplaDeNoticias.do?comando=mostrarTodasAsNoticias';submit()"property="btnSelecionar" value="Voltar" /><html:buttononclick="window.location='PaginaInicial.do';submit()" value="Sair"property="btnSair" /></td></tr></table></body></html>
bean:size e logic:iterate<bean:size id="quantidadeDeNoticiasSelecionadas" name="noticia"
property="noticiasSelecionadas" />• Cria a variável quantidadeDeNoticiasSelecionadas com a quantidade itens
da property noticiasSelecionadas do bean noticia
<bean:write name="quantidadeDeNoticiasSelecionadas" />• Escreve a quantidadeDeNoticiasSelecionadas
<logic:iterate id="idDaNoticiaSelecionada" property="noticiasSelecionadas" name="noticia">• Cria a variável idDaNoticiaSelecionada com o valor de cada item do array
<bean:write name="idDaNoticiaSelecionada" />• Escreve o id na tela
Agora é sua vez• O Struts entrega os dados, mas o
processamento quem faz é você• Seguindo as boas práticas, agora é a vez
consultar as notícias pelo id, através de uma fachada/DAO
• Nunca coloque regras de negócio em suas Actions
Validation Framework• A lógica de validação é escrita em arquivos XML• Originado do Validator Framework do Jakarta• Incluído no Struts a partir da versão 1.1• Permite validação declarativa para vários campos• Valida datas, números, email, cartão de crédito,
código postar (USA), tamanhos, range e expressões regulares
Regras de Validação• Regras são definidas para campos
específicos de um form• Já dispõe de vários validadores prontos
– required, minLength, maxLength, date, integer, mask
• Extensível: você pode criar seus próprios validadores
Validação do ActionForm• Para usar o Validator, torne seus
ActionForm’s subclasses de ValidatorForm ou ValidatorActionForm
• Se estiver usando DynaActionForm, passe a extender de DynaValidatorForm ou DynaValidatorActionForm
NoticiaFormpackage net.noticias.form;
import org.apache.struts.validator.*;
public class NoticiaForm extends ValidatorActionForm { private String id; private String texto; private String titulo; private String data; private String tipoDeNoticia; private String[] noticiasSelecionadas; {...}}
validation.xml• Específico da sua aplicação• Configuração das regras aplicadas a cada
campo do seu formulário• Torna desnecessário o método validate() do
ActionForm
validator-rules.xml• Fornecido pelo Struts • Regras que já fazem parte do Validator• Fica dentro da lib struts-core.jar, no pacote
org.apache.struts.validator
Plugin Validator• Para começar a usar o Validator, acrescente
o plugin no struts-config.xml<plug-in className="org.apache.struts.validator.ValidatorPlugIn"><set-property property="pathnames" value="/org/apache/struts/validator/validator-rules.xml,
/WEB-INF/validation.xml" /></plug-in>
Validação no Cliente• O Validator pode fazer a validação no lado
do cliente• Para tanto, acrescente a tag seguinte logo
após o <head>• Essa tag irá gerar todo o código javascript
para validar seu formulário<head><html:javascript formName="noticiaForm" />
Validação no Cliente• É gerado automaticamente um método
javascript validateXxx, onde Xxx é o nome do seu formulário
• Atualize a tag html:form para seus formulários
<html:form action="/Noticia?comando=confirmar" onsubmit="return validateNoticiaForm(this)">
MessageResources#erro.tipodenoticia.id.requerido={0} é requeridoerro.tipodenoticia.descricao.requerido={0} é requerida#tipodenoticia.id=IDtipodenoticia.descricao=Descrição#noticia.id=IDnoticia.data=Data#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.invalid={0} is invalid.
errors.byte={0} must be a byte.errors.short={0} must be a short.errors.integer={0} must be an integer.errors.long={0} must be a long.errors.float={0} must be a float.errors.double={0} must be a double.
errors.date={0} is not a date.errors.range={0} is not in the range {1} through {2}.errors.creditcard={0} is an invalid credit card number.errors.email={0} is an invalid e-mail address.
Mensagens Personalizadas • O Validator já tem várias mensagens
configuradas (em inglês)• Você pode definir suas próprias mensagens
validation.xml<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration
1.3.0//EN" "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd"><form-validation><formset><form name="tipoDeNoticiaForm"><field property="id" depends="required,integer"><arg key="tipodenoticia.id" /></field><field property="descricao" depends="required"><msg name="required"key="erro.tipodenoticia.descricao.requerido" /><arg key="tipodenoticia.descricao" /></field></form>
validation.xml<form name="noticiaForm"><field property="id" depends="required,integer"><arg key="noticia.id" /></field><field property="data" depends="required,date"><arg key="noticia.data" /><var><var-name>datePattern</var-name><var-value>dd/MM/yyyy</var-value></var></field></form>
</formset>
</form-validation>
Regras de Validação<form name="tipoDeNoticiaForm">• Nome do formulário definido no struts-config.xml<field property="id" depends="required,integer">• Nome da propriedade e suas dependências (definidas no validator-rules.xml)<arg key="tipodenoticia.id" />• Essa é a mensagem que substitui o parâmetro {0} no MessageResources
caso o campo não tenha um valor válido<field property="descricao" depends="required"><msg name="required" key="erro.tipodenoticia.descricao.requerido" />• Essa é a mensagem personalizada para o validador required<var-name>datePattern</var-name><var-value>dd/MM/yyyy</var-value>• Padrão para data. Veja a lista na documentação da SimpleDateFormat
Exemplo de Popup’s• Ao lado você pode ver
alguns exemplos de mensagens
• No primeiro você pode ver uma mensagem padrão (em inglês) e uma personalizada
• Para entender o mecanismo de troca de mensagens, veja todos os arquivos envolvidos
JSP2.0 EL• Linguagem padrão da Sun para a camada
de apresentação• Acesso conciso, rápido e prático• Acessa subpropriedades dos beans• Sintaxe incrivelmente simples• É da Sun...
Concorrentes• jsp:useBean e jsp:getProperty
– Não pode acessar subpropriedades do bean– Complexo e nem um pouco prático
• bean:write– Também não pode acessar subpropriedades do bean– Não é a saída mais prática
• Elementos de script JSP– Resulta em um código JSP impossível de manter– Destrói o principal propósito do MVC
Instalação da EL• Para instalar você só precisa alterar o
cabeçalho do web.xml• Já faz parte dos containers mais novos,
como Tomcat 5• Parte integrante do JSP2.0
web.xml<?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"version="2.4">
{...}
</web-app>
Invocando a EL• Forma básica
– ${expressão}– ${bean.propriedade}
• Você pode combiná-la com as demais notações– • <jsp:include page="${expr1}blah${expr2}" />
Exemplo com Struts<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><UL><LI>First name:<bean:write name="contactFormBean" property="firstName"/><LI>Last name:<bean:write name="contactFormBean" property="lastName"/><LI>Email address:<bean:write name="contactFormBean" property="email"/><LI>Fax number:<bean:write name="contactFormBean" property="faxNumber"/></UL>
Agora com EL<UL><LI>First name: ${contactFormBean.firstName}<LI>Last name: ${contactFormBean.lastName}<LI>Email address: ${contactFormBean.email}<LI>Fax number: ${contactFormBean.faxNumber}</UL>