Características Avançadas · HttpServletRequest request, ... • Em seguida é só chamar o...

105
Struts Características Avançadas

Transcript of Características Avançadas · HttpServletRequest request, ... • Em seguida é só chamar o...

StrutsCaracterísticas Avançadas

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

bean• bean:struts• bean:write

logic• logic:empty• logic:present• logic:iterate• logic:{...}

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>

index.jsp<body onLoad="window.location='PaginaInicial.do';">

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>

Tela de Consulta

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>&nbsp;<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

Tela de Edição

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; }}

TipoDeNoticia• Apesar de simples, temos vários elementos

utilizados em

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

Tela de seleção

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

Tela de resultado

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

Exercícios• Crie as regras de validação para o

Formulário FonteForm

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>

Exercícios• No formulário de consulta notícias, combine

as tags Struts com a JSP EL