Carregar apresentação
A apresentação está carregando. Por favor, espere
1
Desenvolvimento Java para Web
Osvaldo Pinali Doederlein Visionnaire
2
Introdução à Plataforma J2EE 1.4
3
Agenda Containers Padrões JCP Servidores de Aplicação
4
J2EE e Containers http://java.sun.com/j2ee/
Container: Conceito fundamental do J2EE Aplicação executa num “casulo” que assume ou facilita diversas responsabilidades Administração / Ciclo de vida Conectividade (SGBD, Messaging, HTTP, SOAP etc.) Funcionalidades: Persistência, Segurança...
6
APIs O Container também implementa APIs J2EE
APIs J2SE: stand-alone (bibliotecas simples) APIs J2EE: maior dependência de serviços XML-RPC: exige server HTTP JMS: exige middleware de mensagens Connector: exige bridges com outros sistemas EJB: exige servidor RMI/IIOP
8
APIs do J2EE 1.4: Diversos JavaMail JavaBeans Activation Framework
Envio e recepção de por POP, IMAP, SMTP JavaBeans Activation Framework Ativação de funcionalidades via tipos MIME JNDI (Java Naming and Directory) LDAP, NDS, DNS, NIS, CosNaming; serviços J2EE JAAS (Autenthication & Authorization Service) Autorização e Autenticação; PAM
9
APIs do J2EE 1.4: Middleware
JMS (Java Message Service) Comunicação assíncrona robusta JTA (Java Transaction API) Transações de alto nível JCA (J2EE Connector Architecture) Integração com sistemas não-J2EE JDBC (Java Database Connectivity) J2SE + DataSources, transações XA
10
APIs do J2EE 1.4: Web Servlets JSP (Java Sever Pages)
Programação Web dinâmica JSP (Java Sever Pages) Idem, mais visual JSTL (Java Standard Template Library) Idem, mais estruturado Alternativas/Complementos: Struts, Spring... Futuro (J2SE 5.0): JSF (JavaServerFaces)
11
APIs do J2EE 1.4: XML e Web Services
JAXP (Java API for XML Processing) DOM, SAX, XSLT SAAJ (SOAP with Attachments API for Java) Web Services: SOAP (modelo documento) JAX-RPC (Java API for XML-based RPC) Web Services: SOAP (modelo RPC), WSDL JAXR (Java API for XML Registries) Web Services: UDDI / ebXML
12
APIs do J2EE 1.4: EJB EJB (Enterprise Java Beans) EJB BMP/CMP/CMR
Componentes Distribuídos; Session; RMI/IIOP EJB BMP/CMP/CMR Entity; Persistência Automática (mapeamento O/R) EJB MDB (Message-Driven Beans) Facilidade de alto nível para JMS e Web Services Transações, Segurança Facilidades declarativas
13
Padrões do JCP J2EE 1.4 (JSR-151 + 15 JSRs, jcp.org)
Padroniza quase tudo APIs Schemas, Deployment Comportamentos (ciclos de vida, etc.) Não cobre: Ferramentas, Metodologias QoS Integração (ex.: suporte a SGBDs e middlewares)
14
Tomcat 5.5 Apache + Sun; RI de JSRs de Servlet, JSP, etc.
Container Web do JBoss, Sun AppServer, … Conectores para Apache e IIS
15
JBoss 4.0 JBoss Group Open Source & Comercial
Arquitetura: Microkernel (JMX), AOP
16
Design Patterns para J2EE
17
Agenda Design Patterns Singleton Façade Factory DAO MVC
18
Design Patterns Design Patterns (GoF, 1995)
Pattern = design reutilizável; problema+solução Modelos; ex.: Intenção, Motivação, Aplicabilidade, Estrutura, Implementação, Implicações, Categoria... Instanciável, mas não reusável, como código Linguagem de Patterns: Coleção de patterns relacionados, com modelo comum
19
Singleton: Motivação Garantir que uma classe tenha instância única
Sem abrir mão do suporte à herança (como static) Implementação robusta de entidades que precisam ser únicas; ex: configuração Alternativa OO às variáveis globais Facilita a inicialização “lazy”
20
Singleton: Estrutura
21
class Configuracao { private static Configuracao singleton; private final Properties props; private Configuracao (Properties props) { this.props = props; } public static Configuracao getInstance () { if (singleton == null) { properties props = // ... Lê properties de um arquivo singleton = new Configuracao(props); } return singleton; public getProperties () { return props; } Properties props = Configuracao.getInstance().getProperties();
22
Façade: Motivação Interface única e simples para um sistema
Simplifica API, reduz curva de aprendizado Reduz dependências e acoplamento Se o modelo interno do sistema evoluir, basta mudar a implementação da Façade; clientes são preservados Conduz a modelos em camadas (layers) Ex: Cliente (JSP) Façade (Session Bean) Negócio
23
Façade: Estrutura
24
Façade (Session / J2EE)
25
public class SistemaPagamentos {
public void alteraSalario (String matricula, double salario) { Funcionario func = CadastroFuncs.getInstance().find(matricula); if (func != null && func.isAtivo()) func.setSalario(salario); } // ... Outros métodos da Façade // Cliente não precisa conhecer Funcionario, CadastroFuncs, etc. SistemaPagamentos sp = // ... sp.alteraSalario(" ", );
26
Factory: Motivação Cria objetos sem saber suas classes concretas
Encapsula decisões sobre a criação de objeto Melhoram OO (construtores não são polimórficos!) Variante: Factory Method Útil com herança, delega criação à subclasse Evita instanceof para criar objetos relacionados Variante: Abstract Factory Suporta um conjunto de entidades relacionadas Suporta implementações "plugáveis", ex.: JDBC, XML
27
Factory Method: Estrutura
28
public interface Cliente {
public Conta abreConta (); } public class ClienteSimples implements Cliente { public Conta abreConta () { return new ContaComum(this); public class ClientePremier implements Cliente { return new ContaEspecial(this); Cliente cli = // ... obtém da database ou outra fonte Conta ct = cli.abreConta(); // cria conta do tipo correto
29
Abstract Factory: Estrutura
30
// Utiliza fábrica abstrata de engine XML (Xerces, Crimson, etc.)
SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setValidating(true); spf.setNamespaceAware(true); // Utiliza fábrica abstrata de parser (com ou sem validação, etc.) SAXParser parser = spf.newSAXParser(); XMLReader reader = parser.getXMLReader(); reader.setContentHandler(this); reader.parse(config);
31
DAO: Motivação Desacoplar o acesso a dados dos clientes
Ocultar a complexidade do acesso a dados Permitir alternância fácil e dinâmica da implementação de persistência Não é necessário com ferramentas ORM (como Hibernate), mas facilita migração JDBCORM
32
DAO: Estrutura
33
public class Venda { /* nenhum acesso a dados */ }
public interface VendaDao { public Venda find (String id) throws SQLException; } public class VendaDaoJDBC implements VendaDao { private DataSource ds; public Venda find (String id) throws SQLException { try { Connection c = ds.getConnection(); Statement stmt = c.createStatement(); ResultSet rs = stmt.executeQuery("SELECT…"); if (rs.next()) return new Venda(id, rs.getString("produto"), …); } finally { if (c != null) try { c.close(); } catch (SQLException e){} } return null; // Objeto não encontrado
34
MVC-2: Motivação Desacoplar responsabilidades de uma GUI:
Model: Camada de Implementação das Regras de Negócio View: Layout dos dados (ex.: telas HTML) Controller: Comportamento da GUI (ex.: consultas, atualizações, tratamento de erros, defaults) Permite variar/evoluir cada um separadamente View editável por não-programadores Back-end pode variar sem afetar GUI
35
MVC-2: Estrutura Controller View Model Requisição Envio de Dados
Seleção do Visualizador Resposta do Envio de dados Resposta View Model
36
<html:form action="/LoginSubmit.do"> <table>
<tr><td>Login:</td> <td><html:text property="login" size="20"/></td> </tr> <tr><td>Senha:</td> <td><html:password property="password" size="20"/></td> <tr><td><html:submit>OK</html:submit></td></tr> </table> </html:form> <html:messages id="error" property="invalid"> <script>alert('<bean:write name="error" />');</script> </html:messages> <html:javascript formName="LoginForm"/> View
37
public class LoginAction extends DispatchAction {
public ActionForward login (ActionMapping map, ActionForm form, HttpServletRequest req, HttpServletResponse resp) throws Exception { audit(request, PortalAudit.ACCESS); if (isFirstLogin(request)) return mapping.findForward("firstLogin"); else return mapping.findForward("loginOk"); } private boolean isFirstLogin (HttpServletRequest req) {...} // ... Outras ações ... Controller
38
Logging
39
Agenda Log4J java.util.logging
40
Log4J Biblioteca do projeto Apache Jakarta
Substitui System.out.println()... Níveis de log; ativação dinâmica sem mudar código Opções de output (console, arquivo, rede, DB etc.) Formatação, Extensibilidade Logs detalhados, de qualidade; fácil e eficiente Para diagnóstico de problemas (debug ou produção) Para auditoria, etc.
41
Log4J: Exemplo Logger logger = Logger.getLogger("SIST");
logger.debug("x=“ + x); logger.log(Level.DEBUG, "x=“ + x); if (logger.isDebugEnabled()) // Se não estiver habilitado... logger.debug(a+b+c+d+e+f); // ...evita custo de gerar dados
42
Log4J: log4j.properties log4j.logger.SIST = INFO, APP_SIST
log4j.appender.APP_SIST = org.apache.log4j.RollingFileAppender log4j.appender.APP_SIST.File = ../logs/SIST.log log4j.appender.APP_SIST.MaxFileSize = 10MB log4j.appender.APP_SIST.MaxBackupIndex = 10 log4j.appender.APP_SIST.layout = org.apache.log4j.PatternLayout log4j.appender.APP_SIST.layout.ConversionPattern = [%p] %d{HH:mm:ss} - %m%n
43
Log4J: log4j.xml <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j=' <logger name=“SIST"> <level value="INFO"/> </logger> <appender name="APP_SIST" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="../logs/SIST.log"/> <param name="MaxFileSize" value="10MB"/> <param name="MaxBackupIndex" value="10"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%p] %d{HH:mm:ss} - %m%n"/> </layout> </appender> </log4j:configuration>
44
java.util.logging API padrão do J2SE 1.4+ (JSR-47)
Semelhante à Log4J, mas não igual/compatível Menos poderosa; Mais leve, simples, eficiente Log4J ou java.util.logging? Log4J não é o padrão, mas ainda é mais popular java.util.logging melhor para componentes reusáveis (não impõe dependência da Log4J para projetos) A Jakarta Commons Logging só piora as coisas
45
java.util.logging: Exemplo
Logger logger = Logger.getLogger("SIST"); logger.fine("x=“ + x); logger.log(Level.FINE, "x=“ + x); if (logger.isLoggable(Level.FINE)) // Se não estiver habilitado... logger.fine(a+b+c+d+e+f); // ...evita custo de gerar dados
46
java.util.logging: logging.properties
handlers= java.util.logging.FileHandler SIST.level = INFO java.util.logging.FileHandler.pattern = ../logs/SIST%u.log java.util.logging.FileHandler.limit = java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
47
JDBC
48
Agenda JDBC API J2EE/DataSources
49
A API JDBC Baseada na ODBC (Microsoft; Open Group CLI) Características
Microsoft: novas APIs (OleDB, ADO, RDO, RDS...) JDBC: evolução compatível + frameworks O/R Características Baixo nível: conexões, statements, cursores, SQL Leve e eficiente Infra-estrutura para todas as outras soluções
50
JDBC: Connection Representa sessão com o SGBD, e transação
Alto custo de criação. Usar pools! Default: auto-commit, não usar!! Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); // Utiliza a conexão... } catch (SQLException e) { if (conn != null) try { conn.close(); } catch (SQLException e) {} }
51
JDBC: Statement e ResultSet
Statement: Query, Update, ou DDL Prefira PreparedStatement sempre! ResultSet: Cursor (resultado de Statement) Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id,nome FROM FUNC"); while (rs.next()) { System.out.println(rs.getInt(1)); System.out.println(rs.getString("nome")); } stmt.close();
52
JDBC: PreparedStatement
Estende Statement, mais poderoso e eficiente Binding (?), reduz recompilação e formatação de SQL Cache no cliente (driver JDBC) Também é mais seguro (evita "injeção de SQL") PreparedStatement stmt = conn.prepareStatement( "SELECT id,nome FROM FUNC WHERE salario >= ?"); stmt.setDouble(1, 3000); ResultSet rs = stmt.executeQuery(); ... stmt.close();
53
JDBC: CallableStatement
Invocação de stored procedures / functions “Anti-OO”, mas reduz tráfego com SGBD CallableStatement stmt = conn.prepareCall( “{call CALCULA_SALARIO (?,?)}"); stmt.setInt(1, idFuncionario); stmt.registerOutParameter(2, Types.DOUBLE); stmt.executeUpdate(); double salario = stmt.getDouble(2); stmt.close();
54
Gerenciamento de Recursos
Invocação dos métodos close() Connection.close(): fecha todos Statements e blobs Statement.close(): fecha ResultSet corrente Statemet.execute*(): também fecha ResultSet anterior ResultSet.close(): não fecha seus blobs! Regra: fechar só o objeto “raiz local” do método Ex.: Se um método recebe a Connection como parâmetro, basta fechar os Statement criados Evite dividir responsabilidades (um método cria, outro faz o close()) bugs, bugs, bugs!!
55
Opções: Connection TRANSACTION_READ_UNCOMMITTED
Permite dirty/non-repeatable/phantom reads TRANSACTION_READ_COMMITTED Permite non-repeatable/phantom reads TRANSACTION_REPEATABLE_READ Permite phantom reads TRANSACTION_SERIALIZABLE Isolamento ACID total CONFIABILIDADE DESEMPENHO
56
Opções: ResultSet FETCH_FORWARD/REVERSE/UNKNOWN
Direção da leitura (hints para o driver) CONCUR_READ_ONLY/UPDATABLE Somente leitura, ou cursor atualizável TYPE_FORWARD_ONLY/ SCROLL_SENSITIVE/SCROLL_SENSITIVE Leitura randômica ou aleatória PRODUTIVIDADE DESEMPENHO
57
DataSource Abstração sobre obtenção de conexões
J2EE, mas também pode ser usada sem container Suporte a JNDI, pools, transações distribuídas Configuração no container Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/Sistema"); ... Connection conn = ds.getConnection();
58
Testes Unitários
59
Agenda Testes Unitários JUnit
60
Testes Unitários TDD (Test-Driven Development), XP
1 funcionalidade = 1 teste Funcionalidade: método, classe, caso de uso, cenário Escrever teste antes do código a testar Objetivos: melhorar qualidade e produtividade Planejar componentes, do ponto de vista do cliente Proteção contra bugs de regressão Otimizações, refactoring... "fearless programming"
63
JUnit Framework para testes unitários em Java
Kent Beck (XP) + Erich Gamma (Patterns, Eclipse) Simples Extensível Exemplos públicos para examinar... J2SE/TCK ( testes) Eclipse (feito com o JUnit)
65
public class TestaRaizes extends TestCase {
public void testOk () { double[] x = Raizes.calcula(3, 4, 1); // 3x2+4x+1=0 assertTrue(x[0] == -3 && x[1] == -9); System.out.println(x[0] + "," + x[1]); } public void testDeltaNegativo () { try { double[] x = Raizes.calcula(3, 0, 1); // 3x2=-1 fail(); catch (IllegalArgumentException e) {}
66
public class Raizes { public static double[] calcula (double a, double b, double c) { double delta = Math.sqrt(b*b-4*a*c); if (Double.isNaN(delta)) throw new IllegalArgumentException("Delta negativo"); double x1 = (-b+delta)/2*a; double x2 = (-b-delta)/2*a; return new double[]{x1,x2}; }
67
Servlets
68
Agenda Servlet Inicialização Filtros Redirecionamento Sessões Cookies
69
Servlet Servlet = Classe Java que responde a HTTP
Exige um conector HTTP (webserver) Servlet recebe um request Conector cuida de headers, TCP/IP, etc. Base para todo stack Java Web JSP, JSTL, JSF, Struts, Velocity, Spring, etc.
71
public class AloMundo extends HttpServlet {
public void doGet (HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { resp.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Alô Mundo</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Alô, Mundo!</h1>"); out.println("</body>"); out.println("</html>"); }
72
Web.xml: <servlet> <servlet-name>AloMundo</servlet-name> <servlet-class>AloMundo</servlet-class> </servlet> <servlet-mapping> <url-pattern>/alo</url-pattern> </servlet-mapping> </web-app>
73
Inicialização e Shutdown
Servlet.init(), Servlet.destroy() init() na primeira invocação, ou load-on-startup=true ServletContextListener Mecanismo apropriado para ciclo de vida da aplicação como um todo
74
public class MeuListener implements ServletContextListener{
public void contextInitialized (ServletContextEvent sce) { System.out.println("inicializando..."); } public void contextDestroyed (ServletContextEvent sce) { System.out.println("terminando..."); Web.xml: <listener> <listener-class>TesteListener</listener-class> </listener>
75
Filtros Interceptação de requests Verificação de desempenho
Logging automatizado Controle de segurança, transações, etc. Transformações, ex.: via XSLT Implementação de frameworks dinâmicos, ex.: Struts Implementação do próprio container
76
public class PSSFilter implements Filter {
// Omitidos: init(), destroy() public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { try { chain.doFilter(req, resp); } finally { Catalog.closeConnection(); } } Web.xml: <filter> <filter-name>PSSFilter</filter-name> <filter-class>com.visionnaire.PSS.servlet.PSSFilter</filter-class> </filter> <filter-mapping> <filter-name>PSSFilter</filter-name><url-pattern>*.jsp</url-pattern> </filter-mapping>
77
Forward e Include Forward: Desvio para outra URL
request.getRequestDispatcher("/Header.jsp") .forward(request, response); Include: Cópia do output de uma URL request.getRequestDispatcher("/OK.jsp") .include(request, response);
78
Contexto, Sessões e Cookies
ServletContext: Representa a web-app MIME, dispatchers, resources, servlets, atributos, log HttpSession: Permite armazenar informações sobre um cliente, através de várias páginas ID, atributos, criação, último acesso, timeout Cookies ou URL rewriting Cookie: Pacote de dados armazenável no browser Utiliza headers do HTTP Pode ser restrito pelo cliente (número, tamanho)
79
JSP
80
Agenda JSP Taglibs Expression Language JSTL
81
JSP Servlet: Java com HTML, JSP: HTML com Java
Semelhante a ASP, PHP, etc. JSP gera uma Servlet Compilado pelo container, em demanda ou deploy Acesso a toda a API de Servlets Diretrizes de página Scriptlets Ações
82
JSP: Sintaxe Comentário Expressão Scriptlet Declaração
Diretiva include Diretiva page <%-- comentário --> <%= expressão %> <% statement %> <%! declaração %> file="url-absoluta"> atrib="valor" %> language="java", import="pkg" errorPage="url", extends="classe" info="msg", contentType="MIME" buffer="kb|none", isErrorPage, session, autoflush, isThreadSafe
83
JSP: Ações Ação include Ação useBean Ação getProperty Ação forward
Ação plugin <jsp:include page="url"> <jsp:useBean atrib="valor"/> id="nome" scope="page|request| session|application" type="class" class="class" beanName="class" <jsp:getProperty name="name" value="valor"/> <jsp:forward page="url"/> <jsp:plugin atrib="valor"/>
84
JSP: Variáveis predefinidas
As mesmas que estariam disponíveis na Servlet HttpServletRequest request HttpServletResponse response HttpSession session PrintWriter out <h2>Seu host é: <%= request.getRemoteHost() %></h2>
85
<%@page language="java"%>
import="java.util.Date"/> <jsp:include page="Titulo.html"/> <jsp:include page="Navegacao.jsp"/> <html><head/> <body> <p> Alo, mundo! Agora são <%= new Date() %> </p> </body> </html>
86
Taglibs Declaração e Uso (JSP) Configuração (web.xml)
prefix="opd" uri="/tags/osvaldo" %> <tt:alo name="Osvaldo"> ... </tt:alo> Configuração (web.xml) <jsp-config> <taglib> <taglib-uri>/tags/osvaldo</taglib-uri> <taglib-location>/WEB-INF/tags/osvaldo.tld</taglib-location> </taglib> </jsp-config>
87
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" " <taglib> <tlibversion>1.0.0</tlibversion> <jspversion>1.1</jspversion> <shortname>Taglib Demo</shortname> <tag> <name>alo</name> <tagclass>tags.AloTag</tagclass> <bodycontent>empty</bodycontent> <attribute> <name>nome</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute> </tag> </taglib>
88
public class AloTag extends BodyTagSupport {
private String nome; public void setNome (String nome) { this.nome = nome; } public int doEndTag () throws JspException { try { pageContext.getOut().write("Alo, " + nome); catch (IOException e) {} return SKIP_BODY;
89
EL (Expression Language)
Parâmetros de tags; reduz uso de scriptlets Sintaxe: ${var} (= var) ${var.x.y} (= var.getX().getY()) Operadores extra; números e strings div, mod, and, or, not, eq, ne, lt, gt, le, ge, empty Ex.: ${(10 mod 4 == 5) and empty x} ${(10 % 4 == 5) && x == null}
90
EL (Expression Language)
Variáveis predefinidas pageContext (servletContext, session, request, response) param, paramValues header, headerValues cookie, initParam pageScope, requestScope, sessionScope, applicationScope Sintaxe [ ] para acesso a variáveis Map (get()) ${header["host"]} ${pageScope.departamentos[nomeDepto]}
91
JSTL (JSP Standard TagLib)
JSR-52: Biblioteca padrão de tags para JSP Core: Iteração, Condições, Output… FMT: Formatação, Internacionalização SQL: Acesso a dados via JDBC XML: Parsing, Xpath, XSLT Functions: Manipulação de strings
92
<%@ taglib prefix="sql" uri="http://java. sun
taglib prefix="c" uri=" %> <html> <head><title>Demo de JSTL</title></head> <body> <sql:transaction dataSource=“jdbc/MinhaDatabase"> <sql:query var=“produtos"> SELECT * FROM PRODUTO </sql:query> </sql:transaction> <h2>Componentes de Hardware</h2> <table border="1"> <c:forEach var="row" items="${produtos.rowsByIndex}"> <tr> <c:forEach var="col" items="${row}"> <td><c:out value="${col}"/></td> </c:forEach> </tr> </table> </body></html>
93
JSTL: Core <c:out value="texto“/>
<c:set var="nome" value="valor" scope="page|request|session|application"/> <c:remove var="nome" scope="page|request|session|application"/> <c:catch var="nome"> ... </c:catch> <c:if test="condição" var,scope> ... </c:if> <c:choose> <c:when test="condição">...</c:when> <c:otherwise>...</c:otherwise> </c:choose>
94
JSTL: Core <c:forEach var="nome" items="coleção" varStatus="status" begin="n" end="n" step="n"> <c:forTokens var="nome" items="string" delims="sep" varStatus="status" begin="n" end="n" step="n"> <c:import url="url" charEncoding="encoding" context="contexto" varReader="nome" var,scope> <c:param name="nome" value="valor"/> <c:url value="url" context="contexto" var,scope/> <c:redirect url="url" context="contexto" >
95
JSTL: Formatação <fmt:setTimeZone value="timeZone"/>
<fmt:timeZone var,scope> corpo </fmt:timeZone> <fmt:formatNumber value="valor" currencyCode="code" currencySymbol="symbol" type="number|currency|percent" var,scope groupingUsed="bool" pattern="pattern" maxIntegerDigits="n" minIntegerDigits="n" maxFractionDigits="n" minFractionDigits="n"> <fmt:parseNumber value="valor" parseLocale="locale" type="number|currency|percent" integerOnly="bool" var,scope/>
96
JSTL: Formatação <fmt:formatDate value="data" type="{time|date|both}" dateStyle="{default|short|medium|long|full}" timeStyle="{default|short|medium|long|full}" pattern="pattern" timeZone="zona" var,scope/> <fmt:parseDate value="data" type="{time|date|both}" dateStyle="{default|short|medium|long|full}" timeStyle="{default|short|medium|long|full}" var,scope pattern="pattern" timeZone="zona" parseLocale="locale"/>
97
JSTL: SQL <sql:query sql="query" var="var" dataSource="nome" maxRows="max" startRow="start" var,scope> <sql:param value="valor"/> </sql:query> <sql:update sql="update" dataSource="nome" var,scope> params </sql:update> <sql:dateParam value="valor" type="timestamp|time|date"/>
98
JSTL: SQL <sql:transaction dataSource="nome" isolation="read_committed|read_uncommitted|repeatable_read|serializable"> ... </sql:tx> <sql:setDataSource dataSource="nome" url="url" driver="classe" user="nome" password="pwd" var,scope/>
99
Mais taglibs... JSTL JSR-128: JESI, JSP TagLib for Edge Side Includes
XML (<x:...>) Internacionalização (<fmt:...>) Funções EL definidas pelo usuário JSR-128: JESI, JSP TagLib for Edge Side Includes JSR-267: JSP TagLib for Web Services
100
Deployment
101
Agenda Pacotes jar, war, ear Deploy em servidores J2EE
102
Pacotes jar, war, ear JAR: J2SE WAR: J2EE EAR: J2EE (EJB)
/ Classes, Resources /META-INF/ Manifest.MF WAR: J2EE / Páginas (e subdiretórios) /WEB-INF Configurações, TLDs /WEB-INF/classes Classes /WEB-INF/lib JARs /WEB-INF/tags tagfiles EAR: J2EE (EJB)
104
Deploy em servidores J2EE
"Hot deploy", copiar WAR/EAR para diretório Tomcat: /webapps JBoss: server/config/deploy DataSources: deploy de .XML Outros (JBoss): RAR (Resource Adapter) SAR (Service) Deploy "explodido" (opcional / debug) Ferramentas GUI de Deploy: overrides
105
Struts
106
Agenda Model (forms) View Controller (actions) Configuração Taglibs
Tiles Validação
107
Controller View Model Requisição Envio de Dados
Seleção do Visualizador Resposta do Envio de dados Resposta View Model
108
View Página JSP "amarrada" à Struts
<html:form action> Action (Controller) Campos Form (View)
109
Controller Herda Action Implementar execute()
Predefinidas: Tiles, Download, Forward, Include... Implementar execute() Uma ou mais actions: request.getParameter("action") Dispara alguma ação de negócio Determina próxima página (forward) DispatchAction: implementar métodos similares ao execute(), mas com nome igual à da ação
110
Configuração WEB-INF/struts-config.xml WEB-INF/web.xml
Mapeamento MVC, page flow WEB-INF/web.xml Configuração padrão da Struts, ex.: ActionServlet WEB-INF/: Outros arquivos da Struts WEB-INF/lib: Binários da Struts WEB-INF/.struts-config.mex: Layout visual para o struts-config.xml (MyEclipse)
112
public class ContatoForm extends ActionForm {
private String nome="", sobrenome="", ="", fone="", warning=""; public String getNome () { return nome; } public void setNome (String nome) { this.nome = nome; } // Omitido: outros getters/setters public String valida () { if (nome == null || nome.length() == 0) return "nome"; if (sobrenome == null || sobrenome.length() == 0) return "sobrenome"; if ( == null || .length() == 0 || == -1) return " "; if (fone == null || fone.length() == 0) return "fone"; return null; }
113
public class MessageBean {
private String message = ""; public String getMessage () { return message; } public void setMessage (String message) { this.message = message;
114
public class AssinaAction extends Action {
public ActionForward execute (ActionMapping map, ActionForm aForm, HttpServletRequest req, HttpServletResponse resp) throws Exception { ContatoForm form = (ContatoForm)aForm; String campoRuim = form.valida(); if (campoRuim != null) { warn(req, campoRuim); return map.findForward("valor-errado"); } else return map.findForward("sucesso"); protected void warn (HttpServletRequest req, String msg) { MessageBean msgBean = new MessageBean(); msgBean.setMessage(msg); req.setAttribute("messageBean", msgBean);
115
assina.jsp: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib uri=" prefix="html" %> <html><head><title>Assinatura</title></head> <body><h1 align="center">Assinatura</h1> Digite seus dados de contato para receber nossa Newsletter!<p/> <center> <html:form action="/assina"> <table> <tr><td>Nome:</td><td><html:text property="nome"/></td></tr> <tr><td>Sobrenome:</td><td><html:text property="sobrenome"/></td></tr> <tr><td> </td><td><html:text property=" "/></td></tr> <tr><td>Fone:</td><td><html:text property="fone"/></td></tr> </table> <html:submit value="Assine!"/> </html:form> </center> </body></html>
116
confirma.jsp: (Usando taglib Struts Beans – NÃO PROGRAMAR ASSIM!!!)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib uri=" prefix="bean" %> <html><head><title>Confirmação</title></head> <body><center><h1>Confirmação</h1> Muito obrigado, prepare seu Inbox para nosso spam! <table> <tr><td>Nome:</td> <td><bean:write name="contatoForm" property="nome"/></td></tr> <tr><td>Sobrenome:</td> <td><bean:write name="contatoForm" property="sobrenome"/></td></tr> <tr><td> </td> <td><bean:write name="contatoForm" property=" "/></td></tr> <tr><td>Fone:</td> <td><bean:write name="contatoForm" property="fone"/></td></tr> </table> </center> </body></html>
117
confirma.jsp: (Usando taglib JSTL Core – FAZER DESSA MANEIRA!!!)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib prefix="c" uri=" %> <html><head><title>Confirmação</title></head> <body><center><h1>Confirmação</h1> Muito obrigado, prepare seu Inbox para nosso spam! <table> <tr><td>Nome:</td> <td><c:out value="${contatoForm.nome}"/></td></tr> <tr><td>Sobrenome:</td> <td><c:out value="${contatoForm.sobrenome}"/></td></tr> <tr><td> </td> <td><c:out value="${contatoForm. }"/></td></tr> <tr><td>Fone:</td> <td><c:out value="${contatoForm.fone}"/></td></tr> </table> </center> </body></html>
118
valor-errado.jsp: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib prefix="c" uri=" %> <html> <head><title>Valor faltando ou incorreto!</title></head> <body><center> <h2>Valor faltando ou incorreto: <c:out value="${messageBean.message}"/>!</h2> Por favor, <a href="assina.jsp">Tente novamente</a>. </center> </body></html>
119
assina2.jsp: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib uri=" prefix="html" %> taglib uri=" prefix="bean" %> <html><head><title>Assinatura</title></head> <body><h1 ALIGN="CENTER">Assinatura</h1> Digite seus dados de contato para receber nossa Newsletter!<p/><center> <html:form action="/assina2"> <c:if test="${not empty contatoForm.warning}"> Campo faltando ou inválido: <bean:write name="contatoForm" property="warning" filter="false"/> </c:if> <table> <tr><td>Nome:</td><td><html:text property="nome"/></td></tr> <tr><td>Sobrenome:</td><td><html:text property="sobrenome"/></td></tr> <tr><td> </td><td><html:text property=" "/></td></tr> <tr><td>Fone:</td><td><html:text property="fone"/></td></tr> </table> <html:submit value="Assine!"/> </html:form></center></body></html>
120
struts-config.xml: <struts-config> <form-beans> <form-bean name="contatoForm" type="ContatoForm"/> </form-beans> <global-forwards> <forward name="sucesso" path="/confirma.jsp"/> </global-forwards> <action-mappings> <action path="/assina" type="AssinaAction" name="contatoForm" scope="request"> <forward name="valor-errado" path="/valor-errado.jsp"/> </action> <action path="/assina2" type="AssinaAction2" name="contatoForm" scope="request"> <forward name="valor-errado" path="/assina2.jsp"/> </action-mappings> </struts-config>
121
Struts Taglibs Struts inclui várias taglibs:
Bean, Logic (maior parte obsoleta; usar JSTL) HTML: Gera elementos, útil para forms Nested: Relacionamentos entre tags (pai/filho) Utilities: Diversos Tiles
122
Tiles Taglib da Struts Permite compor páginas complexas, juntando fragmentos (tiles) reutilizáveis Como <jsp:include>, mas mais flexível e estruturado Facilidade de template Separa estrutura, layout e componentes Permite recombinar estes elementos facilmente
123
Tiles: Preparando Configuração do struts-config.xml:
(copiar do struts-blank.war) <controller processorClass= "org.apache.struts.tiles.TilesRequestProcessor"/> <plug-in className="org.apache.struts.tiles.TilesPlugin"> <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml"/> <set-property property="moduleAware" value="true"/> </plug-in>
124
Tiles: Planejando Comece planejando seu layout "master"... Cabeçalho
Menu Corpo Rodapé
125
Tiles: Planejando Defina estrutura de página/layout/fragmentos página1
Menu Cabeçalho Rodapé Corpo
126
Tiles: Implementando Página (instancia/parametriza o layout)
pagina1.jsp: uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> <tiles:insert page="/layout.jsp" flush="true"> <tiles:put name="titulo" value="Página 1"/> <tiles:put name="cabecalho" value="/cabecalho.html"/> <tiles:put name="menu" value="/menu.jsp"/> <tiles:put name="rodape" value="/rodape.jsp"/> <tiles:put name="corpo" value="/corpo1.jsp"/> </tiles:insert>
127
Tiles: Implementando Layout
layout.jsp: taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> <html><head> <title><tiles:getAsString name="titulo"/></title></head> <body><table width="100%"> <tr><td colspan="2"><tiles:insert attribute="cabecalho"/></td></tr> <tr><td width="120"><tiles:insert attribute="menu"/></td> <td><tiles:insert attribute="corpo"/></td></tr> <tr><td colspan="2"><tiles:insert attribute="rodape"/></td></tr> </ table></body></html>
128
Tiles: Implementando os Tiles
JSPs, HTMLs ou imagens, normais Exemplo: cabecalho.html <a href=" <img src="/BannerEsq.gif" align="left" border="0"> </a> <img src="/BannerDir.gif" align="right" border="0">
129
Tiles: Usando Definitions
Especificação declarativa das páginas Suporta herança de páginas JSPs de página reduzidas 1 insert: uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> <tiles:insert definition="pagina2.page" flush="true"/> Ainda mais facilidade para sites dinâmicos JSP pode decidir entre várias definitions
130
Tiles-defs.xml: <?xml version="1.0" encoding="ISO " ?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" " <tiles-definitions> <definition name=".layoutBase" path="/layout.jsp"> <put name="titulo" value=""/> <put name="cabecalho" value="cabecalho.html"/> <put name="menu" value="menu.jsp"/> <put name="rodape" value="rodape.jsp"/> <put name="corpo" value=""/> </definition> <definition name="pagina1.page" extends=".layoutBase" > <put name="titulo" value="Página 2"/> <put name="corpo" value="corpo2.jsp"/> </tiles-definitions>
131
pagina1.jsp layout.jsp (titulo="Página 1") cabecalho.html menu.jsp corpo1.jsp rodape.jsp pagina2.jsp pagina3.jsp layout.jsp (titulo="Página 2") layout.jsp (titulo="Página 3") cabecalho.html cabecalho.html menu.jsp corpo2.jsp menu.jsp corpo3.jsp rodape.jsp rodape.jsp
132
Validação Opções de validação Código de validação, onde?
Sem Validator: ad-hoc Validação Manual (ou semi-automática) Validação Automática Código de validação, onde? Form (e/ou JavaScript): Só regras encapsuláveis no bean; ex.: formato de string; valores mín/máx Action: Acesso à lógica de negócio, database, etc.
133
Validação Manual Implementar ActionForm.validate()
public ActionErrors validate ( ActionMapping map, HttpServletRequest req) { ActionErrors ae = super.validate(map, req); if (ae == null) ae = new ActionErrors(); if (...) ae.add("nome", new ActionMessage("contatoForm.nome")); if (...) ae.add(" ", new ActionMessage("contatoForm. ")); ... return ae; } Detecte todos os erros, não só o primeiro!
134
struts-config.xml: <action path="/assina" type="AssinaAction" name="contatoForm" scope="request" input="/assina.jsp" validate="true"> </action> <message-resources parameter="MessageResources" null="false"/> WEB-INF/classes/MessageResources.properties: contatoForm.nome=Nome não pode ser vazio contatoForm. = deve ter formato
135
assina.jsp: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib uri=" prefix="html" %> <html><head><title>Assinatura</title></head> <body><h1 align="center">Assinatura</h1> Digite seus dados de contato para receber nossa Newsletter!<p/> <center> <html:form action="/assina"> <table> <html:errors/> <tr><td>Nome:</td><td><html:text property="nome"/></td></tr> <tr><td>Sobrenome:</td><td><html:text property="sobrenome"/></td></tr> <tr><td> </td><td><html:text property=" "/></td></tr> <tr><td>Fone:</td><td><html:text property="fone"/></td></tr> </table> <html:submit value="Assine!"/> </html:form> </center> </body></html>
136
public class AssinaAction extends Action {
public ActionForward execute (ActionMapping map, ActionForm aForm, HttpServletRequest req, HttpServletResponse resp) throws Exception { // Se chegou até aqui, é porque o Struts já // executou a validação com sucesso! return map.findForward("sucesso"); }
137
Validação Automática Validação declarada em arquivo XML
Validação Server-Side (Validator), obrigatória Mais segura, não contornável pelo usuário Validação Client-Side (JavaScript), opcional Mais eficiente, evita request ao servidor e refresh
138
struts-config.xml: <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in> validator-rules.xml, validation.xml: extraia do struts-blank.war WEB-INF/classes/MessageResources.properties: # Mensagens-padrão (copiar do comentário no validator-rules.xml): errors.required={0} é obrigatório. errors.minlength={0} não pode ter menos que {1} caracteres. ...
139
validation.xml: <?xml version="1.0" encoding="ISO " ?> <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" " <form-validation> <formset> <form name="contatoForm"> <field property="nome" depends="required"><arg key="contatoForm.nome"/></field> <field property="sobrenome" depends="required"> <arg key="contatoForm.sobrenome"/> </field> <field property=" " depends="required,mask"> <arg key="contatoForm. "/> <var> <var-name>mask</var-name> </var> </field> <field property="fone" depends="required"> <arg key="contatoForm.fone"/> </field> </form> </form-validation>
140
assina.jsp: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> taglib uri=" prefix="html" %> <html><head><title>Assinatura</title></head> <body><h1 align="center">Assinatura</h1> <p align="center">Digite seus dados de contato para receber nossa Newsletter!</p> <center> <html:form action="/assina" onsubmit="return validateContatoForm(this);"> <table> <tr><td>Nome:</td><td><html:text property="nome"/> <html:errors property="nome"/></td></tr> <tr><td>Sobrenome:</td><td><html:text property="sobrenome"/> <html:errors property="sobrenome"/> </td></tr> <tr><td> </td><td><html:text property=" "/> <html:errors property=" "/> </td></tr> <tr><td>Fone:</td><td><html:text property="fone"/> <html:errors property="fone"/> </td></tr> </table> <html:submit value="Assine!"/> </html:form><html:javascript formName="contatoForm"/></center></body></html>
141
public class ContatoForm extends ValidatorForm {
private String nome=""; private String sobrenome=""; private String =""; private String fone=""; public String getNome () { return nome; } public void setNome (String nome) { this.nome = nome; } public String getSobrenome () { return sobrenome; } public void setSobrenome (String sn) {this.sobrenome = sn;} public String get () { return ; } public void set (String ) { this. = ; } public String getFone () { return fone; } public void setFone (String nome) { this.fone = fone; } } // Nenhum código de validação!
142
Validação no Servidor
143
Validação no Cliente
144
Validação: Capacidades
Validações predefinidas: required, requiredif, validwhen, minlength, maxlength mask, creditCard, , url integer, float, double, long, short, byte, date intRange, longRange, floatRange, doubleRange Definições globais (constantes) Validadores plugáveis Validação Híbrida (Manual + Automática)
145
Visionnaire Informática S.A.
Muito Obrigado Visionnaire Informática S.A. R. Eng Roberto Fischer, CIC - Curitiba - PR Tel: (41)
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.