Professional Documents
Culture Documents
Web
Prof. M.Sc Fabiano Costa Teixeira
U N I D A D E 4
4 Considerações Iniciais
Até agora as unidades de ensino apresentaram o desenvolvimento de páginas HTML
estáticas. Nessa unidade serão apresentados alguns exemplos de como realizar a geração das
páginas de forma dinâmica utilizando tecnologias Java.
São apresentados os servlets e Java Server Pages. Recomenda-se que os exemplos sejam
executados (o código fonte encontra-se no ambiente para download) para que seja verificado o
comportamento da aplicação.
Uma vez que esse material apresenta alguns conceitos básicos e exemplos, é importante que
a bibliografia seja estudada para que o conhecimento seja ampliado.
}else{
var op = document.createElement('option');
op.text="Campinas";
op.value="CA";
document.getElementById("cidade").add(op);
op = document.createElement('option');
op.text="Ribeirão Preto";
op.value="RP";
document.getElementById("cidade").add(op);
op = document.createElement('option');
op.text="São Paulo";
op.value="SP";
document.getElementById("cidade").add(op);
}
}
</script>
</header>
<body>
<Font size="10">Localização</font>
<br><br>
Estado
<select id="estado" onblur="carregaCidades()">
<option value="MG">Minas Gerais</option>
<option value="SP" SELECTED>São Paulo</option>
</select>
<br><br>
Cidade
<select id="cidade">
<option value="CA">Campinas</option>
<option value="RP" selected>Ribeirão Preto</option>
<option value="SP" selected>São Paulo</option>
</select>
</body>
</html>
A apresentação, em uma página Web, dos dados existentes em um SGBD requer que o
documento HTML a ser enviado ao usuário seja gerado automaticamente no momento que o
servidor recebe a requisição, de maneira que os dados possam ser recuperados do banco de dados e
inseridos no documento. Esses documentos gerados automaticamente resultam nas chamadas
páginas dinâmicas.
Para que uma página dinâmica possa ser gerada, o servidor Web (que nesse caso é um
servidor de aplicações) necessita ser capaz de executar um programa desenvolvido, em função das
regras de negócio existentes, para realizar todo o procedimento de busca de dados e escrita da
página Web. A figura 3 ilustra o processo de requisição, geração e recepção de uma página
dinâmica. Primeiramente o navegador envia a requisição de um documento ao servidor Web que ao
receber invoca (2) a aplicação responsável por aquele tipo de requisição. Essa aplicação envia
requisições (3) e recebe respostas de um SGBD (4). Por fim, o documento HTML é escrito pela
aplicação (5) e enviado para o navegador do usuário (6).
Diversas linguagens e plataformas oferecem suporte para a geração dinâmica de páginas
como, por exemplo, PHP, Dot Net, JEE, etc. Para o navegador, a tecnologia usada do lado do
servidor não é importante, uma vez que o documento recebido como resposta (HTML, por
exemplo) seja suportado por ele.
Figura 3: Arquitetura básica de um servidor de aplicações
As aplicações corporativas fazem uso maciço de dados armazenados nos SGBDs. Muitas
vezes, é preciso, por diversos motivos, que a aplicação seja capaz de operar com bancos de dados
diferentes, em função da necessidade do cliente. No entanto, se a forma de escrever código fosse
completamente diferente para utilizar SGBDs diferentes, essa flexibilidade seria inviável.
O JDBC (Java Database Conectivity) é uma forma que a tecnologia Java disponibiliza para
que o acesso a um SGBD possa ser realizado. Para isso, a Sun disponibiliza um conjunto de
interfaces que definem e padronizam as operações necessárias para realizar acessos (escrita e
leitura) em um banco de dados.
Uma vez definidas as interfaces, cada fabricante de SGBD deve implementá-las de acordo
com os requisitos do sistema de banco de dados distribuídos por ele. O resultado dessa
implementação gera um pacote de classes que determina o Driver JDBC que deverá ser utilizado
para acessar um determinado SGBD.
Essa sub-seção será focada na utilização do driver JDBC distribuído pelo MySql para
realizar o acesso ao seu sistema de gerenciamento de banco de dados. Para isso, primeiramente é
preciso realizar o download do driver no site do MySql. Acesse o endereço www.mysql.com,
selecione a opção Downloads=>Connectors=>Connector/J=>5.1=>Source and Binaries(zip). O
seguinte link também pode ser utilizado para realizar diretamente o download do driver:
http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-
5.1.8.zip/from/http://mysql.skynet.be/
Uma vez com o driver em “mãos” é preciso configurar o ambiente NetBeans para que seja
possível fazer uso das classes existentes. Antes de mais nada é necessário que seja criado o projeto
que será utilizado para esse exemplo. Para isso, no NetBeans, selecione Arquivo=>Novo Projeto.
Conforme ilustrado pela figura 4, selecione a categoria “Java Web” e o projeto “Aplicação Web”.
Quando o projeto for finalizado ele aparecerá na guia “projetos” do NetBeans. Para realizar
a configuração para que esse faça uso do driver JDBC é preciso clicar com o botão direito do mouse
sobre o nome do projeto e selecionar “Propriedades”. Será aberta uma tela, conforme a figura 7,
onde é preciso clicar em “Bibliotecas”.
Para realizar os exemplos a seguir é necessário que seja criada uma tabela no servidor
MySql com o nome de “estados”, conforme figuras 4.
Figura 8: Criação da tabela “estados”
Para que uma aplicação possa utilizar um SGBD é preciso estabelecer uma conexão entre os
dois. O primeiro passo para isso é realizar a carga das classes Java que implementam o driver JDBC
a ser utilizado. Essa carga é feita utilizando o método estático forName da classe Class.
Após a carga das classes do driver chega o momento de realizar o estabelecimento da
conexão propriamente dita. A classe DriverManager oferece o método getConnection que é
responsável por todo o trabalho da conexão. Esse método recebe três parâmetros: uma string que
informa o endereço IP do servidor e o nome do Schema do banco de dados a serem conectados, o
usuário e a senha. Abaixo é apresentado um exemplo de código que realiza a conexão a um schema
chamado “tópicos” que está localizado um servidor MySql endereçado com o IP 127.0.0.1. O
usuário é “root” que tem a senha “pw”.
public class exemploJdbc{
public static void main(String args[]){
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/topicos“,
"root", “pw");
} catch (Exception ex) {
System.out.println("Erro de conexão: " + ex.getMessage());
}
}
}
Após a conexão ter sido estabelecida com sucesso chega a hora de começar a manipular os
dados. Para isso, é preciso que a aplicação envie, por meio da comunicação estabelecida, comandos
ao servidor MySql e receba os retornos.
A classe Statement do Java tem a função de permitir o envio de uma instrução SQL para um
servidor. Uma vez que ela utiliza a conexão estabelecida para enviar a instrução, para obter uma
instância dessa classe é preciso realizar uma solicitação ao objeto que representa tal conexão.
Voltando ao exemplo anterior, o código abaixo ilustra o processo de obtenção de uma instância da
classe Statement.
public class exemploJdbc{
public static void main(String args[]){
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/topicos“,
"root", “pw");
Statement st = con.createStatement();
} catch (Exception ex) {
System.out.println("Erro de conexão: " + ex.getMessage());
}
}
}
Uma vez que se possui um objeto da classe Statement, é possível enviar uma instrução SQL
para o servidor. No entanto, as instruções variam em relação ao seu propósito e por conseqüência o
tipo de dado retornado também. Quando se envia uma instrução de consulta (select) é retornado o
conjunto de registros selecionados do banco. Se a instrução for de alteração de dados (isso inclui:
inserção, remoção e alteração propriamente dita) o retorno é apenas o número de registros da tabela
que foram afetados pela instrução.
A classe Statement oferece dois métodos para o envio de instruções ao SGBD:
• executeUpdate: Permite o envio de uma instrução SQL para atualização do banco de
dados e retorna o número de registros afetados.
• executeQuery: Permite o envio de uma instrução SQL para o servidor e recebe um
objeto contendo os registros selecionados pela instrução.
O código abaixo ilustra um exemplo de como realizar a inserção de um registro na tabela de
estados.
public class exemploJdbc{
public static void main(String args[]){
try {
int num = 0;
Class.forName("com.mysql.jdbc.Driver");
Connection con =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/topicos“,
"root", “pw");
Statement st = con.createStatement();
num = st.executeUpdate(“insert into estados (sigla,nome) values (‘MG’,
‘Minas Gerais’)”);
} catch (Exception ex) {
System.out.println("Erro de conexão: " + ex.getMessage());
}
}
}
Quando uma instrução de consulta é enviada ao SGBD o retorno dos dados é realizado pelo
JDBC utilizando um objeto da classe ResultSet. Esse objeto realiza a abstração de uma tabela de
dados e permite que seja realizada uma navegação pelos registros selecionados pela instrução SQL.
É interessante pensar nessa navegação como um “ponteiro” que identifica o registro atual que está
sendo processado. No momento que o objeto da classe ResultSet é criado esse “ponteiro” está
“apontando” para um registro nulo, localizado antes do primeiro existente.
Para realizar a navegação básica nos registros, quatro métodos são de suma importância:
• first: Posiciona o ponteiro no primeiro registro.
• previous: Posiciona o ponteiro no registro anterior.
• next: Posiciona o ponteiro no próximo registro.
• last: Posiciona o ponteiro no último registro.
Esses métodos retornam uma variável booleana que determina se após a execução do
método o ponteiro ficou em um registro válido. Imagine que o ponteiro está localizado no último
registro de uma tabela, se o método next for invocado ele apontará para uma posição nula,
retornando o valor false.
A classe ResultSet oferece métodos que realizam a recuperação dos campos existentes no
registro indicados pelo ponteiro. Para cada tipo de dado existente no banco existe um método
correspondente nessa classe. Como parâmetro para esse método é possível informar o nome do
campo ou sua posição no registro retornado (há uma sobrecarga de métodos). Exemplos de métodos
para retorno de parâmetros são: getString, getInt, etc.
O código abaixo ilustra um exemplo de acesso à tabela de estados. Os dados são
recuperados e apresentados na tela (considerando uma aplicação JSE).
public class exemploJdbc{
public static void main(String args[]){
try {
String sigla, nome;
int num = 0;
Class.forName("com.mysql.jdbc.Driver");
Connection con =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/topicos“,
"root", “pw");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(“select * from estados”);
while(rs.next()){
sigla = rs.getString(“sigla”);
nome = rs.getString(“nome”);
System.out.println(“Sigla: “ + sigla + “ Nome: “ + nome);
}
} catch (Exception ex) {
System.out.println("Erro de conexão: " + ex.getMessage());
}
}
}
De maneira a permitir que a SQL seja criada de forma dinâmica, em função de valores
variáveis, o JDBC disponibiliza uma classe denominada PreparedStatement. Com essa classe o
programador define a estrutura básica da SQL e determina o local onde as variáveis serão inseridas
por meio do sinal de interrogação (?).
Após a preparação da SQL é possível definir qual o valor que deve ser inserido no local de
cada ponto de interrogação existente. Para isso, há um método para cada tipo de dado (setInt,
setString, etc). Uma vez que o método define o tipo de dado utilizado, automaticamente a API faz o
gerenciamento da formatação dos dados variáveis como, por exemplo, colocá-los entre aspas
quando o tipo for String.
Note que no método setString (ou para qualquer outro tipo de dado) são informados dois
parâmetros. O primeiro indica qual é o ponto de interrogação que deverá ser substituído pelo valor
do segundo parâmetro.
O JEE (Java Enterprise Edition) é uma plataforma desenvolvida e mantida pela Sun
Microsystems que dá suporte ao desenvolvimento de sistemas corporativos voltados para Web.
Sendo assim, a plataforma oferece mecanismos para o desenvolvimento de aplicações que serão
hospedadas e executadas em um servidor como, por exemplo, o GlassFish.
Para que a implementação, implantação e execução das aplicações JEE possam ser
realizadas de uma maneira mais ágil e amigável, é bastante interessante a utilização de uma IDE
(Integrated Development Environment). Essa ferramenta provê a abstração de diversas rotinas que
são necessárias durante o processo de desenvolvimento de uma aplicação.
Nos exemplos apresentados neste capítulo, será feito uso de uma IDE chamada NetBeans, o
qual pode ser copiado livremente por meio do site: www.netbeans.org. No momento do download é
bastante importante que seja selecionada a distribuição denominada “Web & Java EE”, pois essa já
inclui os pacotes necessários para o desenvolvimento e um servidor GlassFish embutido.
Visto que o NetBeans é desenvolvido utilizando a linguagem Java, é necessário que exista o
ambiente de execução apropriado para essa plataforma. Sendo assim, previamente é preciso realizar
a instalação do ambiente de desenvolvimento e execução do JSE (Java Standard Edition). O
download pode ser realizado por meio do endereço http://java.sun.com/javase/downloads/index.jsp.
4.3.1 Servlets
Conforme citado anteriormente, para que uma página Web possa ser gerada dinamicamente
é preciso que haja uma aplicação, a ser executada no servidor, que será a responsável pela geração
do documento HTML. A plataforma J2EE oferece os Servlets como uma alternativa para esse
requisito.
Um servlet é uma classe Java que é instanciada e executada pelo servidor de aplicações de
maneira que quando uma requisição de uma página Web é recebida, o servidor invoca a instância
dessa classe para que ela realize a geração do documento HTML (veja a animação “Funcionamento
Básico do Servlet”). Quando um Servlet é executado, sua “saída padrão” é a página HTML que
deverá ser retornada ao navegador web que realizou a requisição HTTP. Voltando à figura 3, o
servlet é a parte da arquitetura que está denominada como “Aplicação”.
Para realizar a criação de um novo Servlet, seleciona-se a opção “Arquivo” da barra de
menus e em seguida a opção “Novo Arquivo”. Será aberta uma janela conforme ilustrado na figura
9, onde se deve selecionar a categoria Web e o tipo de arquivo Servlet.
Figura 9: Seleção do tipo de arquivo a ser criado
Ao clicar no botão “Próximo” será aberta a janela solicitando o nome do Servlet a ser criado
e o pacote Java onde sua classe será inserida. No exemplo dado, conforme figura 10, foi utilizado o
nome “CadastroEstado” para a classe que será inserida no pacote “Cadastro”.
Após salvar, faça um teste executando a aplicação. Para isso, basta clicar no botão “Executar
Main Project”, conforme ilustrado na figura 12.
Note que foi criado um formulário conforme visto na unidade de ensino sobre HTML. No
entanto, é importante verificar o conteúdo do atributo “action” do formulário. Esse atributo indica
que quando o formulário for submetido ele deve invocar a URL relativa “/CadastroEstado”. É dito
relativa porque a URL a ser requisitada é composta pelo endereço do servidor onde a página atual
foi requisitada mais o identificador do servlet.
Sendo dessa forma, é fácil verificar que o formulário irá invocar o mesmo servlet que gerou
o HTML ao qual ele pertence. Ao executar essa página agora, se forem digitados nos campos sigla e
nome os valores “MG” e “Minas Gerais”, respectivamente, pode-se notar que os dados do
formulário são enviados como parâmetros na URL. Veja figura 14.
Figura 14: URL utilizada na requisição HTTP quando o formulário é submetido
No entanto, o formulário é reapresentado com os campos em branco. Por que? Porque o
servlet foi executado novamente e ele gera o formulário com os campos vazios. Nesse ponto, torna-
se interessante realizar o tratamento dos parâmetros recebidos. Com isso, o formulário poderia ser
gerado novamente com os valores digitados anteriormente pelo usuário.
O objeto request possui um método chamado getParameter que retorna um determinado
parâmetro. Dessa forma, são criadas duas variáveis do tipo String chamadas sigla e nome, as quais
serão responsáveis por armazenar os valores digitados pelo usuário. Uma vez que esses dados são
conhecidos, pode-se alterar a geração do formulário para que os campos sejam apresentados ao
usuário com os valores digitados. Veja o código abaixo e teste-o.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String sigla, nome;
sigla = request.getParameter("sigla");
if(sigla==null)
sigla="";
nome = request.getParameter("nome");
if(nome==null)
nome="";
out.println("<HTML>");
out.println("<TITLE>Topicos Especiais em Informatica</TITLE>");
out.println("</HEAD>");
out.println("<BODY style='font-family:Verdana'>");
out.println("<H1>Cadastro de Estados</H1><BR>");
out.println("<FORM action='CadastroEstado' method='get'>");
out.println("Sigla:<BR>");
out.println("<INPUT type='text' name='sigla' size='2' maxlength='2'
value='" + sigla + "'><BR><BR>");
out.println("Nome:<BR>");
out.println("<INPUT type='text' name='nome' size='45' maxlength='45'
value='" + nome + "'><BR><BR>");
out.println("<INPUT type='submit' value='Cadastrar'>");
out.println("</FORM>");
out.println("</BODY>");
out.println("</HTML>");
} finally {
out.close();
}
}
Agora que os parâmetros já estão sendo processados, é preciso partir para a última parte
dessa aplicação: salvar os dados no SGBD. Para isso, é preciso realizar os procedimentos descritos
na parte onde foi dito sobre o JDBC. Isso inclui importar as bibliotecas do JDBC, fazer a carga do
driver e implementar o código que realizará o acesso ao banco de dados.
O código abaixo ilustra todo esse processo. É importante notar que ao realizar a
manipulação dos dados no SGBD a aplicação ainda não sabe se o usuário está inserindo ou
atualizando um cadastro. Sendo assim, primeiramente o aplicativo tenta realizar uma alteração, se
não existir registro para a chave primária informada a inserção é realizada.
package Cadastro;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.*;
/**
*
* @author FabianoC
*/
public class CadastroEstado extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String sigla, nome;
sigla = request.getParameter("sigla");
if(sigla==null)
sigla="";
nome = request.getParameter("nome");
if(nome==null)
nome="";
//Conexão com o banco de dados
if(!nome.equals("")){
//Existe um parâmetro. Realiza a atualização do BD
Class.forName("com.mysql.jdbc.Driver");
Connection con =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/topicos", "root", "pw");
PreparedStatement ps = con.prepareStatement("update estados set
nome=? where sigla=?");
ps.setString(1, nome);
ps.setString(2, sigla);
int numReg = ps.executeUpdate();
if(numReg == 0){
//Não há o registro no banco...realiza a inclusão
ps = con.prepareStatement("insert into estados (sigla, nome)
values (?,?)");
ps.setString(1, sigla);
ps.setString(2, nome);
ps.executeUpdate();
}
con.close();
}
out.println("<HTML>");
out.println("<TITLE>Topicos Especiais em Informatica</TITLE>");
out.println("</HEAD>");
out.println("<BODY style='font-family:Verdana'>");
out.println("<H1>Cadastro de Estados</H1><BR>");
out.println("<FORM action='CadastroEstado' method='get'>");
out.println("Sigla:<BR>");
out.println("<INPUT type='text' name='sigla' size='2' maxlength='2' value='" + sigla +
"'><BR><BR>");
out.println("Nome:<BR>");
out.println("<INPUT type='text' name='nome' size='45' maxlength='45' value='" + nome +
"'><BR><BR>");
out.println("<INPUT type='submit' value='Cadastrar'>");
out.println("</FORM>");
out.println("</BODY>");
out.println("</HTML>");
}catch(Exception e){
out.println("Erro: " + e.getMessage());
} finally {
out.close();
}
}
...
}
Atenção: Não esqueça de alterar o usuário e senha do banco para aqueles que foram
configurados no seu servidor MySql.
Em uma aplicação web é muito comum que seja necessário que páginas (ou servlets, no caso
desse exemplo) compartilhem informações entre si. Muitas vezes, determinadas informações devem
permanecer disponíveis enquanto o usuário utiliza o sistema.
Para isso, é disponibilizado o conceito de sessão de usuário que permite que dados de um
determinado usuário permaneçam no servidor entre diversas conexões HTTP. Como exemplo disso,
imagine um sistema web que possua diversas páginas diferentes e no início é preciso que o usuário
se identifique por meio de um processo de login. Dessa forma, as informações sobre o usuário que
foram informadas nessa tela devem estar disponíveis para todas as páginas que forem acessadas
pelo usuário.
Voltando ao exemplo utilizado nessa unidade de ensino, suponha que seja necessário inserir
uma página que obrigue o usuário informar seu nome. Se o nome é informado corretamente é feito
um redirecionamento para o cadastro de estados, caso contrário é apresentada uma mensagem
dizendo da obrigatoriedade da informação.
Uma vez que o nome foi informado é preciso armazená-lo na sessão do usuário para que
esse dado seja utilizado pelas demais páginas da aplicação. Para isso, a classe HttpServletRequest
oferece o método getSession, o qual retorna um objeto da classe HTTPSession que é responsável
por gerenciar a sessão do usuário. Essa classe HTTPSession possui vários métodos para o
gerenciamento de sessões. No entanto, é importante destacar alguns deles:
• setAttribute: Permite que um objeto Java seja armazenado na sessão. Esse objeto é
associado a um nome.
response.setContentType("text/html;charset=UTF-8");
try {
request.getSession().invalidate();
String nome;
out.println("<html>");
out.println("<head>");
out.println("</head>");
out.println("<body style='font-family:Verdana'>");
nome = request.getParameter("nome");
if(nome!= null)
if(nome.equals(""))
else{
request.getSession().setAttribute("nomeUsuario", nome);
response.sendRedirect("CadastroEstado");
out.println("</FORM>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
Observe que as tags HTML são inseridas normalmente, o que indica que elas deverão ser
enviadas dessa forma para o navegador. O código Java é executado e a instrução out.println
adiciona de forma dinâmica novos elementos ao hiperdocumento.
O próximo exemplo (EntradaSistema.jsp) apresenta uma página web igual aquela
apresentada pelo servlet CadastroEstado. É interessante notar que a utilização do JSP agiliza de
forma significativa a produção no desenvolvimento de aplicações.
No servlet, para inserir o valor de uma variável no documento HTML pode-se usar a
concatenação da parte estática do elemento e a variável. Repare o exemplo da propriedade value do
elemento do formulário responsável por receber a sigla do estado.
No JSP, como é possível escrever o texto HTML diretamente no documento desenvolvido, é
permitido que o valor de uma variável seja acrescentado de maneira bastante simples, utilizando <
%=variável%>. Dessa forma, no momento da geração do documento hipertexto a ser enviado ao
navegador o valor da variável é recuperado e inserido automaticamente.
Nessa unidade de ensino foram apresentados alguns exemplos que demonstram a utilização
de tecnologias Java na implementação de aplicações web. Foi visto como implementar uma
aplicação simples utilizando servlets e JSP.