Desenvolvimento Java para Web
Osvaldo Pinali Doederlein
Visionnaire
Introdução à Plataforma
J2EE 1.4
Agenda



Containers
Padrões JCP
Servidores de Aplicação
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...
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
APIs do J2EE 1.4: Diversos
 JavaMail
 Envio e recepção de e-mail 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
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
APIs do J2EE 1.4: Web
 Servlets
 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)
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
APIs do J2EE 1.4: EJB
 EJB (Enterprise Java Beans)
 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
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)
 http://java.sun.com/reference/blueprints/
Tomcat 5.5




Apache + Sun; RI de JSRs de Servlet, JSP, etc.
Container Web do JBoss, Sun AppServer, …
Conectores para Apache e IIS
http://jakarta.apache.org/tomcat/
JBoss 4.0




JBoss Group
Open Source & Comercial
Arquitetura: Microkernel (JMX), AOP
http://www.jboss.com/products/jbossas/
Design Patterns para J2EE
Agenda






Design Patterns
Singleton
Façade
Factory
DAO
MVC
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
 http://java.sun.com/blueprints/patterns/
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”
Singleton: Estrutura
Singleton
-singletonInstance
...
«constructor»
-Singleton( )
«misc»
+getInstance( )
...
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();
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
Façade: Estrutura
Cliente
1
 Usa
*
Façade
Façade (Session / J2EE)
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("93764622", 4350.00);
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
Factory Method: Estrutura
public interface Cliente {
public Conta abreConta ();
}
public class ClienteSimples implements Cliente {
public Conta abreConta () {
return new ContaComum(this);
}
public class ClientePremier implements Cliente {
public Conta abreConta () {
return new ContaEspecial(this);
}
Cliente cli = // ... obtém da database ou outra fonte
Conta ct = cli.abreConta(); // cria conta do tipo correto
Abstract Factory: Estrutura
// 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);
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 JDBCORM
DAO: Estrutura
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
}
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
MVC-2: Estrutura
Requisição
Controller
Envio de Dados
Seleção do Visualizador
Resposta
View
Resposta do
Envio de dados
Model
<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>
<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
public class LoginAction extends DispatchAction {
Controller
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 ...
}
Logging
Agenda
 Log4J
 java.util.logging
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.
 http://logging.apache.org/log4j/
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
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
Log4J: log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/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>
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 
 http://java.sun.com/j2se/1.5.0/docs/guide/logging/
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
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 = 10000000
java.util.logging.FileHandler.formatter =
java.util.logging.SimpleFormatter
JDBC
Agenda
JDBC API
J2EE/DataSources
A API JDBC
 Baseada na ODBC (Microsoft; Open Group CLI)
 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
 http://java.sun.com/products/jdbc/
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) {}
}
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();
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();
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();
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!!
Opções: Connection
 TRANSACTION_READ_UNCOMMITTED
Permite non-repeatable/phantom reads
 TRANSACTION_REPEATABLE_READ
Permite phantom reads
 TRANSACTION_SERIALIZABLE
Isolamento ACID total
DESEMPENHO
 TRANSACTION_READ_COMMITTED
CONFIABILIDADE
Permite dirty/non-repeatable/phantom reads
Opções: ResultSet
 FETCH_FORWARD/REVERSE/UNKNOWN
Direção da leitura (hints para o driver)
 TYPE_FORWARD_ONLY/
SCROLL_SENSITIVE/SCROLL_SENSITIVE
Leitura randômica ou aleatória
DESEMPENHO
Somente leitura, ou cursor atualizável
PRODUTIVIDADE
 CONCUR_READ_ONLY/UPDATABLE
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();
Testes Unitários
Agenda
 Testes Unitários
 JUnit
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"
 http://www.extremeprogramming.org/rules/unittests.html
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 (45.000 testes)
 Eclipse (feito com o JUnit)
 http://www.junit.org/
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) {}
}
}
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};
}
}
Servlets
Agenda






Servlet
Inicialização
Filtros
Redirecionamento
Sessões
Cookies
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.
 http://java.sun.com/products/servlet/
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>");
}
}
Web.xml:
<servlet>
<servlet-name>AloMundo</servlet-name>
<servlet-class>AloMundo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AloMundo</servlet-name>
<url-pattern>/alo</url-pattern>
</servlet-mapping>
</web-app>
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
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>
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
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>
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);
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)
JSP
Agenda




JSP
Taglibs
Expression Language
JSTL
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
JSP: Sintaxe






Comentário
Expressão
Scriptlet
Declaração
Diretiva include
Diretiva page
<%-- comentário -->
<%= expressão %>
<% statement %>
<%! declaração %>
<%@include file="url-absoluta">
<%@page atrib="valor" %>
language="java", import="pkg"
errorPage="url", extends="classe"
info="msg", contentType="MIME"
buffer="kb|none", isErrorPage,
session, autoflush, isThreadSafe
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"/>
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>
<%@page language="java"%>
<%@page 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>
Taglibs
 Declaração e Uso (JSP)
<%@taglib 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>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<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>
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;
}
}
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}
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]}
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
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<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>
</c:forEach>
</table>
</body></html>
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>
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" >
<c:param name="nome" value="valor"/>
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/>
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"/>
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"/>
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/>
Mais taglibs...
 JSTL
 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
Deployment
Agenda
 Pacotes jar, war, ear
 Deploy em servidores J2EE
Pacotes jar, war, ear
 JAR: J2SE
 /  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)
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
Struts
Agenda







Model (forms)
View
Controller (actions)
Configuração
Taglibs
Tiles
Validação
Requisição
Controller
Envio de Dados
Seleção do Visualizador
Resposta
View
Resposta do
Envio de dados
Model
View
 Página JSP "amarrada" à Struts
 <html:form action>  Action (Controller)
 Campos  Form (View)
Controller
 Herda Action
 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
Configuração
 WEB-INF/struts-config.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)
public class ContatoForm extends ActionForm {
private String nome="", sobrenome="", email="", 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 (email == null || email.length() == 0 ||
email.indexOf('@') == -1) return "email";
if (fone == null || fone.length() == 0) return "fone";
return null;
}
}
public class MessageBean {
private String message = "";
public String getMessage () {
return message;
}
public void setMessage (String message) {
this.message = message;
}
}
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);
}
}
assina.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://struts.apache.org/tags-html" 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>Email:</td><td><html:text property="email"/></td></tr>
<tr><td>Fone:</td><td><html:text property="fone"/></td></tr>
</table>
<html:submit value="Assine!"/>
</html:form>
</center>
</body></html>
confirma.jsp: (Usando taglib Struts Beans – NÃO PROGRAMAR ASSIM!!!)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://struts.apache.org/tags-bean" 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>Email:</td>
<td><bean:write name="contatoForm" property="email"/></td></tr>
<tr><td>Fone:</td>
<td><bean:write name="contatoForm" property="fone"/></td></tr>
</table>
</center>
</body></html>
confirma.jsp: (Usando taglib JSTL Core – FAZER DESSA MANEIRA!!!)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<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>Email:</td>
<td><c:out value="${contatoForm.email}"/></td></tr>
<tr><td>Fone:</td>
<td><c:out value="${contatoForm.fone}"/></td></tr>
</table>
</center>
</body></html>
valor-errado.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<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>
assina2.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" 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>Email:</td><td><html:text property="email"/></td></tr>
<tr><td>Fone:</td><td><html:text property="fone"/></td></tr>
</table>
<html:submit value="Assine!"/>
</html:form></center></body></html>
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>
</action-mappings>
</struts-config>
Struts Taglibs
 Struts inclui várias taglibs:
 Bean, Logic (maior parte obsoleta; usar JSTL)
 HTML: Gera elementos, útil para forms
http://struts.apache.org/userGuide/struts-html.html
 Nested: Relacionamentos entre tags (pai/filho)
 Utilities: Diversos
 Tiles
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
http://struts.apache.org/userGuide/dev_tiles.html
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>
Tiles: Planejando
 Comece planejando seu layout "master"...
Cabeçalho
Menu
Corpo
Rodapé
Tiles: Planejando
 Defina estrutura de página/layout/fragmentos
página1
página2
página3
layout
Menu
Cabeçalho
Rodapé
Corpo
Tiles: Implementando Página
(instancia/parametriza o layout)
pagina1.jsp:
<%@taglib 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>
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>
Tiles: Implementando os Tiles
 JSPs, HTMLs ou imagens, normais
 Exemplo: cabecalho.html
<a href="http://www.companhia.com">
<img src="/BannerEsq.gif" align="left" border="0">
</a>
<img src="/BannerDir.gif" align="right" border="0">
Tiles: Usando Definitions
 Especificação declarativa das páginas
 Suporta herança de páginas
 JSPs de página reduzidas 1 insert:
<%@taglib 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
Tiles-defs.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<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"/>
</definition>
</tiles-definitions>
pagina1.jsp
layout.jsp
(titulo="Página 1")
cabecalho.html
menu.jsp
corpo1.jsp
rodape.jsp
pagina2.jsp
layout.jsp
(titulo="Página 2")
pagina3.jsp
layout.jsp
(titulo="Página 3")
cabecalho.html
cabecalho.html
rodape.jsp
menu.jsp
menu.jsp
corpo2.jsp
corpo3.jsp
rodape.jsp
Validação
 Opções de validação
 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.
http://struts.apache.org/userGuide/dev_validator.html
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("email", new ActionMessage("contatoForm.email"));
... return ae;
}
 Detecte todos os erros, não só o primeiro!
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.email=Email deve ter formato "conta@host"
assina.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://struts.apache.org/tags-html" 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>Email:</td><td><html:text property="email"/></td></tr>
<tr><td>Fone:</td><td><html:text property="fone"/></td></tr>
</table>
<html:submit value="Assine!"/>
</html:form>
</center>
</body></html>
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");
}
}
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
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.
...
validation.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration
1.1.3//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<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="email" depends="required,mask">
<arg key="contatoForm.email"/>
<var>
<var-name>mask</var-name>
<var-value>^([\w]+)(.[\w]+)*@([\w]+)(.[\w]{2,3}){1,2}$</var-value>
</var>
</field>
<field property="fone" depends="required"> <arg key="contatoForm.fone"/> </field>
</form>
</form-validation>
assina.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://struts.apache.org/tags-html" 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>Email:</td><td><html:text property="email"/>
<html:errors property="email"/> </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>
public class ContatoForm extends ValidatorForm {
private String nome="";
private String sobrenome="";
private String email="";
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 getEMail () { return email; }
public void setEMail (String email) { this.email = email; }
public String getFone () { return fone; }
public void setFone (String nome) { this.fone = fone; }
} // Nenhum código de validação!
Validação no Servidor
Validação no Cliente
Validação: Capacidades
 Validações predefinidas:
required, requiredif, validwhen, minlength, maxlength
mask, creditCard, email, 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)
Download

nome - dacjaime