3.12. Databases and Non-HTML ContentMost web applications need to communicate with a database, either to generate dynamic content or collect and store data from users, or both. With servlets, this communication is easily handled using the JDBC API described in Chapter 8. Thanks to JDBC and the generally sensible design of the servlet lifecycle, servlets are an excellent intermediary between a database and web clients. Most of the general JDBC principles discussed in Chapter 8 apply to servlets. In our example, we create a database connection within the servlet's init( ) method. Larger applications will generally prefer to use a database connection pool, managed by the servlet container. Connection pools and DataSource objects (for container-managed database connections) are discussed in Chapter 8. Another option would be to use the object relational capabilities provided by Hibernate in your servlet. Hibernate is discussed in Chapter 20. So far, all our servlets have produced standard HTML content. Of course, this is all most servlets ever do, but it's not all that they can do. Say, for instance, that your company stores a large database of PDF documents within an Oracle database, where they can be easily accessed. Now say you want to distribute these documents on the Web. Luckily, servlets can dish out any form of content that can be defined with a MIME header. All you have to do is set the appropriate content type and use a ServletOuputStream if you need to transmit binary data. Example 3-8 shows how to pull Adobe Acrobat documents from an Oracle database. Example 3-8. A servlet that serves PDF files from a databaseimport java.io.*; import java.sql.*; import javax.servlet.*; import javax.servlet.http.*; public class DBPDFReader extends HttpServlet { Connection con; public void init(ServletConfig config) throws ServletException { super.init(config); try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = DriverManager.getConnection("jdbc:oracle:thin:@DBHOST:1521:ORCL", "user", "passwd"); } catch (ClassNotFoundException e) { throw new UnavailableException("Couldn't load OracleDriver"); } catch (SQLException e) { throw new UnavailableException("Couldn't get db connection"); } } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { res.setContentType("application/pdf"); ServletOutputStream out = res.getOutputStream( ); Statement stmt = con.createStatement( ); /* This is dangerous for production code. Request parameters should never be injected into SQL without preprocessing. We're keeping syntax simple for this example. */ ResultSet rs = stmt.executeQuery( "SELECT PDF FROM PDF WHERE PDFID = " + req.getParameter("PDFID")); if (rs.next( )) { BufferedInputStream pdfData = new BufferedInputStream(rs.getBinaryStream("PDF")); byte[] buf = new byte[4 * 1024]; // 4K buffer int len; while ((len = pdfData.read(buf, 0, buf.length)) != -1) { out.write(buf, 0, len); } } else { res.sendError(res.SC_NOT_FOUND); } rs.close( ); stmt.close ( ); } catch(SQLException e) { // Report it } } } |