quinta-feira, 8 de setembro de 2011

Servlet completo de leitura de tabela MSAccess - JSP

Como prometido, a seguir a listagem explicada do servlet J2EE para leitura de registros de uma tabela em um banco MSAccess. Ao final, basta unir os trechos em fonte de cor vermelha para obter a script. Os parâmetros a serem substituídos estão sublinhados (PRESTE BASTANTE ATENÇÃO).

Definição de pacote

package TesteServlet.servlets;

Esta declaração produz uma árvore hierarquica dentro da Workspace de um projeto, por exemplo, feito no Eclipse:


O diretório src é dos fontes (source) em java. TesteServlet é o nome do pacote, e servlets é como um grupo de assunto dentro dele. Sugerimos até que você utilize esta conveção para os servlets. TesteServlet pode ser substituído por um nome que lembre a finalidade de seu pacote de classes.

Importação de Bibliotecas

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

O primeiro bloco contém as bibliotecas java cuja responsabilidade é gerenciar as entradas e saídas (java.io) e as consultas e atualizações de bancos de dados (java.sql). O segundo bloco traz as rotinas responsáveis pela característica de servlet de nossas classes.

Estes blocos poderiam ser declarados como:

import java.io.*;
java.sql.*;
javax.servlet.*;

No entanto, muitas rotinas seriam incorporadas sem necessidade.

Corpo do Servlet

Vamos dar o esquema do servlet que vamos apresentar, e posteriormente o método que é o coração do processo.


/**
 * Servlet implementation class LeTabela
 */
public class LeTabela extends HttpServlet {
      private static final long serialVersionUID = 1L;
     
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LeTabela() {
        super();
        // TODO Auto-generated constructor stub
    }

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
               // Posteriormente vamos dar o conteúdo deste método - LOCAL DO CÓDIGO
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}

}


Nesta classe (LeTabela - que extende HttpServlet ) são declarados 3 métodos:


  • Construtor LeTabela público (se não for público, a classe não pode ser instanciada);
  • Método doGet;
  • Método doPost;


Os dois últimos métodos se confundem com o próprio "espírito HTTP". No browser estamos sempre enviando parâmetros (via formulário), ou seja, POST, ou recebendo parâmetros (via análise da requisição), ou seja, GET.

Em nosso caso, executaremos o método GET (doGet) do servlet, ou seja, chamado o servlet, ele dispara este método.

Detalhamento do método doGet


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Connection  conn;
Statement stmt;
ResultSet rs;
String S = "";
response.setContentType("text/html");
PrintWriter out = response.getWriter();

try {


   Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
   // URL da conexão 
                   conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//SERVIDOR/compartilhamento/Nome do banco.mdb");
   stmt = conn.createStatement();
   rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");
   while(rs.next()){ 
    String fname=rs.getString("Nome do Campo"); 
    S += "&bull;"+fname+"<BR>";
    }
   rs.close();
   stmt.close();
   conn.close() ;




   } catch (Exception e) {
           System.out.println(e.toString());
   }
out.println(S+"<BR>");
}

A tentativa de estabelecimento de conexão com um banco de dados e a sua manipulação deve estar dentro de um bloco de tratamento de POSSÍVEIS exceções ( try { ... } catch ( ...) { ... }. Por esta razão, declaramos as variáveis necessárias fora deste bloco, para que sejam acessíveis de qualquer lugar dentro do método, pois o bloco try ... catch PROTEGE AS VARIÁVEIS LOCAIS A ELE. Por exemplo, se você declarar a variável S dentro deste bloco, o comando final (out.println) não a conhecerá.

Abertura da conexão

Como explicado no post Conexão JDBC com banco MSAccess, a conexão é feita pelas instruções:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");

Aqui usamos a pior condição, ou seja, o banco Access em um outro servidor. Mas a forma recomendada é colocar o banco no servidor Web e fazer a conexão pelo nome do ODBC. A melhor prática, frisamos, é ter as scripts e banco de dados no mesmo servidor acessado pelos clientes. Se você não confia na segurança de seu servidor, coloque um outro na DMZ (zona protegida por um roteador) da qual ele faz parte, para que não possa ser devassado caso o servidor Web seja invadido.

Acesso através da linguagem SQL

    stmt = conn.createStatement();
    rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");

Na frase do executeQuery podem ser colocadas cláusulas WHERE (condicionais) ou ORDER BY (ordenação). Mas hoje, com bibliotecas que ordenam as tabelas HTML resultantes de pesquisa, esta ordenação deve ser feita no cliente, economizando recursos do servidor de banco de dados.

Listando os registros de forma bem básica

    while(rs.next()){ 
     String fname=rs.getString("Nome do Campo"); 
     S += "&bull;"+fname+"<BR>";
     }

Um simples loop while resolve a situação. Cada valor de campo é extraído por um tipo de instrução get da interface Java Resultset:



 Tipo de Dado Instrução 
 Blob (Memo)  getBlob()
 Data  getDate()
 Inteiro  getInt()
 String  getString()


Em nosso exemplo simplificamos tudo para a forma String.

Lembre-se que para a exibição num resultado do tipo HTML ou XHTML, o valor terá que ser convertido para o modo string, para ser concatenado com as tags.

Fechando os objetos

Ao final de seu uso, os objetos devem ser fechados, para a boa integridade da pilha de objetos da máquina virtual Java.


   rs.close();
   stmt.close();
   conn.close() ;

Armadilha da exceção do bloco try ... catch


   } catch (Exception e) {
           System.out.println(e.toString());
   }

Este catch se presta a capturar quaisquer outras exceções que não as ServletException, IOException.

Final


out.println(S+"<BR>");
} // Fecha o método

Esta instrução out.println exibe o resultado de tudo o que foi armazenado na variável S durante o loop. Se nada foi lido, pelo fato do SQL não ter achado nada, será exibido um vazio.
























quarta-feira, 7 de setembro de 2011

Conexão JDBC com banco MSaccess

Para os programadores Java e JSP que estão em dúvida com a conexão JDBC para este banco de dados tão eficiente, aqui vão os trechos de código para a conexão:

JDBC sobre ODBC


            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            conn = DriverManager.getConnection("jdbc:odbc:Teste");

JDBC puro no servidor local


    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/Users/usuario/Documents/Teste.mdb");

JDBC puro no servidor local



Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
   conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");



Protótipo do código


try {


    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    conn = DriverManager.getConnection(...);


    .
    .
    .
    conn.close() ;




    } catch (Exception e) {
            System.out.println(e.toString());
    }

A conexão, bem como as instruções de leitura, atualização ou adição de registros devem estar dentro de um bloco de tratamento de exceções.

Lembrete Final

Em todos os casos, é preciso:

Dar permissão nas chaves de registro (via regedit.exe ou regedt32.exe) referentes a ODBC para que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificá-las ou criar novas;
Dar permissão nos diretórios C:\Windows\Temp  para Todos no modo de alteração e criação;
Dar permissão no diretório onde está o banco de dados para  que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificar ou criar arquivos.



Num próximo post, colocaremos o servlet completo.