首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Oracle Servlet 測試範例:JDBC Thin 驅動連線與查詢

     編輯:Java 相關知識

前言

本範例展示一個完整的 Servlet 連線 Oracle 資料庫 (使用 JDBC Thin 驅動),包含詳細的生命週期日誌、JDBC 驅動日誌啟用、連線參數設定與查詢執行。適合作為整合測試、環境驗證或教學參考。

完整 Servlet 程式碼

import java.io.*;
import java.sql.*;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.http.*;

public class OracleTestServlet extends HttpServlet {
    private static final String SERVLET_NAME = "OracleTestServlet";
    private static final String JDBC_LOG_FILE = "./OracleServletJDBC.log";
    private long servletStartTimeStamp;
    private boolean servletInitialized = false;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        servletStartTimeStamp = System.currentTimeMillis();
        log(SERVLET_NAME + ": Init Completed at " + new Date(servletStartTimeStamp));
        servletInitialized = true;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        long startTime = System.currentTimeMillis();
        log(SERVLET_NAME + " doGet Start");
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        out.println("Oracle JDBC Test");
        out.println("

Employee List Test


"); out.println("
");

        // 1. 啟用 JDBC 驅動日誌 (除錯用)
        enableJdbcLogging();
        
        Connection conn = null;
        Statement stmt = null;
        ResultSet rset = null;
        
        try {
            // 2. 註冊驅動 (JDBC 4.0+ SPI 自動載入,可省略)
            log(SERVLET_NAME + " Registering Driver");
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
            
            // 3. 建立連線 (Thin 模式: host:port:SID)
            // 格式: jdbc:oracle:thin:@::
            // 或服務名: jdbc:oracle:thin:@//:/
            String url = "jdbc:oracle:thin:@9.12.2.10:1621:MPM5";
            String user = "system";
            String pwd = "manager"; // 實際專案請勿硬編碼,使用 JNDI DataSource
            
            log(SERVLET_NAME + " Getting Connection...");
            conn = DriverManager.getConnection(url, user, pwd);
            log(SERVLET_NAME + " Connection Established");
            
            // 4. 執行查詢
            stmt = conn.createStatement();
            log(SERVLET_NAME + " Statement Created");
            
            String sql = "SELECT EMPNO, ENAME FROM SCOTT.EMP";
            rset = stmt.executeQuery(sql);
            log(SERVLET_NAME + " Query Executed");
            
            // 5. 處理結果
            out.println("EMPNO\tENAME");
            out.println("----\t-----");
            while (rset.next()) {
                out.println(rset.getString(1) + "\t" + rset.getString(2));
            }
            log(SERVLET_NAME + " Results Processed");
            
        } catch (SQLException sqle) {
            log(SERVLET_NAME + " SQLException: " + sqle.getMessage(), sqle);
            out.println("SQL Error: " + sqle.getMessage() + "");
        } catch (Exception e) {
            log(SERVLET_NAME + " Exception: " + e.getMessage(), e);
            out.println("Error: " + e.getMessage() + "");
        } finally {
            // 6. 關閉資源 (逆序)
            closeQuietly(rset);
            closeQuietly(stmt);
            closeQuietly(conn);
            log(SERVLET_NAME + " Resources Closed");
        }
        
        out.println("

"); out.println("

Execution time: " + (System.currentTimeMillis() - startTime) + " ms

"); out.println(""); out.close(); log(SERVLET_NAME + " doGet End"); } @Override public void destroy() { log(SERVLET_NAME + ": Terminated at " + new Date()); super.destroy(); } @Override public String getServletInfo() { return "Oracle JDBC Thin Driver Test Servlet"; } // --- Helper Methods --- private void enableJdbcLogging() { try { File logFile = new File(JDBC_LOG_FILE); // 確保目錄可寫 File parent = logFile.getParentFile(); if (parent != null && !parent.canWrite()) { log(SERVLET_NAME + " Log directory not writable: " + parent.getAbsolutePath()); return; } // 追加模式 DriverManager.setLogStream(new PrintStream( new FileOutputStream(logFile, true), true, "UTF-8")); log(SERVLET_NAME + " JDBC Logging enabled: " + logFile.getAbsolutePath()); } catch (IOException ioe) { log(SERVLET_NAME + " Failed to enable JDBC logging: " + ioe.getMessage()); } } private void closeQuietly(AutoCloseable resource) { if (resource != null) { try { resource.close(); } catch (Exception ignored) {} } } private void closeQuietly(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException ignored) {} } } private void closeQuietly(Statement stmt) { if (stmt != null) { try { stmt.close(); } catch (SQLException ignored) {} } } private void closeQuietly(Connection conn) { if (conn != null) { try { conn.close(); } catch (SQLException ignored) {} } } }

關鍵技術點解析

項目說明
JDBC Thin 驅動Type 4 純 Java,無需 Oracle Client 安裝。Maven: com.oracle.database.jdbc:ojdbc11:23.4.0.0 (需 Oracle 帳號下載或從 Maven Central 取較舊版本)
連線 URL 格式jdbc:oracle:thin:@host:port:SID (SID) 或 jdbc:oracle:thin:@//host:port/service_name (服務名,RAC/PDB 推薦)
驅動日誌DriverManager.setLogStream() 捕獲驅動內部網路封包、協定交互,極難除錯時啟用,**生產環境關閉** (效能影響大)
生命週期日誌覆寫 init()/destroy() 記錄 Servlet 載入/卸載時間,配合 log() 寫入容器日誌 (catalina.out 等)
資源管理統一 closeQuietly() 避免 finally 區塊重複 try-catch,JDK 7+ 建議改用 try-with-resources
硬編碼帳密**教學示範用**。實際專案**必須**使用 JNDI DataSource + 連線池,帳密由容器/設定中心管理

部署與驗證步驟

  1. 將 ojdbc11.jar 放入 WEB-INF/lib 或容器共用庫目錄 (Tomcat: $CATALINA_HOME/lib)
  2. 編譯 Servlet:javac -cp servlet-api.jar:ojdbc11.jar OracleTestServlet.java
  3. 部署至 Web 容器 (Tomcat/Jetty/WebLogic/WebSphere)
  4. 瀏覽器存取:https://host:port/context/OracleTestServlet
  5. 檢查容器日誌與 OracleServletJDBC.log 確認連線流程

常見問題排查

  • ORA-12505 / ORA-12514:SID/服務名錯誤,確認 lsnrctl status 監聽器註冊的服務名
  • ORA-01017:帳密錯誤,注意 Oracle 11g+ 區分大小寫密碼
  • ClassNotFoundException:驅動 JAR 未在 Classpath
  • 中文亂碼:確認資料庫字元集 (NLS_CHARACTERSET=AL32UTF8)、JDBC 連線屬性 oracle.jdbc.defaultNChar=true、Servlet response.setCharacterEncoding("UTF-8")
  • 防火牆/網路不通:telnet host 1521 測試埠口連通性

現代化改造建議

// Spring Boot 2.7+ / Spring 6 整合範例
@Repository
public class EmployeeRepository {
    @Autowired JdbcTemplate jdbcTemplate;
    
    public List findAll() {
        return jdbcTemplate.query(
            "SELECT EMPNO, ENAME FROM SCOTT.EMP",
            (rs, rowNum) -> new Employee(rs.getInt("EMPNO"), rs.getString("ENAME"))
        );
    }
}

// application.yml
spring:
  datasource:
    url: jdbc:oracle:thin:@//localhost:1521/ORCLPDB
    username: app_user
    password: ${DB_PASSWORD}
    hikari:
      maximum-pool-size: 20
  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.OracleDialect

總結

本 Servlet 示範了 Oracle JDBC Thin 驅動的標準連線、查詢、日誌、資源管理完整流程。實際專案請遷移至 **連線池 + JNDI/DataSource + 框架封裝 (Spring JDBC/MyBatis/JOOQ)** 架構,並嚴格管理憑證與連線參數。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved