105
Struts Características Avançadas

Características Avançadas · HttpServletRequest request, ... • Em seguida é só chamar o forward ... valor que será mostrado ao usuário – Se o id do bean for igual ao id

Embed Size (px)

Citation preview

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