Java Servlets – JDBC, JNDI a dátové zdroje 2.

15. října 2003

V ostatnej časti našej série som predstavil možnosti využitia technológie JDBC v spojení so servletmi. Ukázali sme si ako nastaviť potrebné parametre, ako sa pripojiť k DB a ako položiť dotaz. V závere článku som naznačil, že pri použití JDBC môžu vzniknúť určité výkonnostné problémy a že existuje riešenie. Tak sa poďme na to pozrieť.

Dátové zdroje a Tomcat = DBCP

Implementácia connection poolingu môže silne závisieť na konkrétnom aplikačnom prostredí. Keďže pri písaní tohto seriálu využívame Tomcat, chcem vám predostrieť riešenie problému s JDBC na tejto platforme. Pri práci s databázami a Tomcatom sa odporúča používať nástroj Database Connection Pool (DBCP), čo je tzv. connection broker. Ide o časť projektu Apache Jakarta, ktorý nájdete na adrese http://jakarta.apache.org/commons/dbcp/. Momentálne je vo verzii 1.0 a mal by byť súčasťou vašej kópie Tomcata. Nachádza sa v /common/lib/commons-dbcp.jar. Prípadne si ho môžete z horeuvedenej adresy stiahnuť. V tom istom adresáry sa musí nachádzať aj súbor commons-pool.jar. Ak nie treba ho stiahnuť tiež.

Aké sú vlastne výhody DBCP? Prvá a najdôležitejšia je, že zabezpečuje samotné zdieľanie a manažovanie databázových pripojení. O to nám samozrejme išlo. Ďalej DBCP je schopné spolupracovať s akýmkoľvek JDBC driverom a plne využívať jeho možnosti. DBCP spĺňa nariadenia normy J2EE a v neposlednom rade je integrovanou súčasťou Tomcata. Samozrejme ho môžete využiť aj v iných prostrediach.

Určitou črtou DBCP je, že využíva Java Naming and Directory Interface (JNDI) technológiu a preto je nutné najprv vytvoriť JNDI zdroj. Aby ste teda mohli využívať connection pooling a Tomcat musíte urobiť tieto tri kroky:

  1. Definovať JNDI zdroj v deskriptore webovej aplikácie – wwb.xml.
  2. Namapovať tento zdroj na skutočný dátový zdroj, resp. databázové spojenie.
  3. V aplikácii vyhľadať referenciu na JNDI zdroj a začať využívať zdieľané pripojenie.

Definovanie JNDI zdroja

V prvom rade potrebujete referenčné meno a malo by začínať na jdbc/. Následne treba do web.xml vložiť značku <resource-ref>. Postupujte podľa uvedeného príkladu:

<resource-ref>
    <res-ref-name>jdbc/CustomersDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

Značka <res-ref-name> obsahuje referenčné meno zdroja, <res-type> definuje že ide o JDBC dátový zdroj a <res-auth> špecifikuje, že autentifikácia je zabezpečovaná servlet kontajnerom.

Definovanie dátového zdroja

Teraz je nutné editovať súbor server.xml z dôvodu vloženia informácií týkajúcich sa databázového pripojenia, ktorý sa nachádza v adresáry conf/. Tieto informácie je možné vložiť buď do časti <DefaultContext> alebo pod vlastný <Context>. V prvom prípade budú informácie dostupné pre všetky web aplikácie na vašom servery a v druhom prípade len pre vami určenú aplikáciu. Ukážeme si na príklade použitie druhej možnosti:

<Context path=“/dbapplication“ docBase=“dbapplication“
        debug=“0″ reloadable=“true“>
  <ResourceParams name=“jdbc/CustomersDB“>
    <parameter>
      <name>user</name>
      <value>sa</value>
    </parameter>
    <parameter>
      <name>password</name>
      <value>passwd</value>
    </parameter>
    <parameter>
      <name>driverClassName</name>
      <value>com.informix.jdbc.IfxDriver</value>
    </parameter>
    <parameter>
      <name>url</name>
      <value>jdbc:informix-sqli://IP:port/database:INFORMIXSERVER=ol1</value>
    </parameter>
  </ResourceParams>
</Context>

Nadefinovali sme teda štyri parametre: user, password, driver a url. Zároveň sme prostredníctvom atribútu name namapovali JNDI zdroj na skutočný databázový zdroj uvedený v parametry url. Myslím že je samozrejmé, že referenčný názov JNDI zdroja <res-ref-name> musí presne odpovedať hodnote atribútu name uvedeného v elemente <ResourceParams>.

Získanie a využívanie zdieľaného pripojenia na dátový zdroj

Po vytvorení JNDI zdroja a jeho namapovaní na skutočný zdroj nám už nič nebráni začať využívať výhody connection poolingu. Keďže využívame JNDI na vyhľadanie zdroja a prístup k dátam, musíme importovať balíček javax.naming. Referenčný názov zdroja, ktorý ste uviedli v <res-ref-name> musíte uviesť vo vašom kóde. Aby ste mohli začať využívať dátový zdroj asociovaný s referenčným názvom, musíte najprv získať tzv. JNDI kontext pre web aplikáciu. Postupujte podľa nasledovného príkladu:

Context init_con = new InitialContext();
Context cntx = (Context) init_con.lookup(„java:comp/env“);
DataSource ds = (DataSource) cntx.lookup(„jdbc/CustomersDB“);
Connection con = ds.getConnection();

Ak už máte objekt Connection môžete ho začať využívať presne tým istým spôsobom ako ste boli zvyknutý. Nasledovný príklad je upraveným príkladom z predchádzajúcej časti seriálu.

package interval;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
public class DBServlet extends HttpServlet {
  private Connection con;
  private DataSource ds;
  public void init(ServletConfig conf)
        throws ServletException {
    try {
      Context init_con = new InitialContext();
      Context cntx = (Context) init_con.lookup(„java:comp/env“);
      ds = (DataSource) cntx.lookup(„jdbc/CustomersDB“);
    }
    catch (NamingException ex) {
      throw new ServletException („java:comp/env/jdbc/CustomersDB“, ex);
    }
  }
  public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {
      synchronized(ds) {
        con = ds.getConnection();
      }
      Statement stm = con.createStatement();
      String sql = „SELECT * FROM TABLE“;
      ResultSet rs = stm.executeQuery(sql);
      stm.close();
    }
    catch (SQLException e) {}
    finally {
      try { con.close(); } catch (Exception e) {}
    }
  }
}

Rovnako ako v predošlej časti aj tento príklad ilustruje len použitie niekoľkých základných objektov a ich metód. Príklad končí v okamihu naplnenie objektu ResultSet výsledkami dotazu.

Časovo náročné operácie vyhľadania databázového pripojenia prostredníctvom JNDI sú umiestnené v časti init(), takže budú vykonané len raz. Keďže premenná ds môže byť potenciálne zdieľaná medzi jednotlivými vláknami, prístup k nej je synchronizovaný.

Tým by som dnešnú časť uzavrel. Dúfam, že už nebude pre vás problém využívať vo vašich aplikáciách connection pooling a tým zdvihnúť ich výkon.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Další článek moment-bar.com
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *