對於hive-jdbc驅動,kerberos認證的代碼塊與Connection實例化的代碼塊,耦合性不強,保證執行的時序性便可。(kerberos認證在前,Connection實例化在後),以下圖所示。php
代碼以下。html
// 先執行kerberos認證的代碼塊 // 1. login use keytab System.setProperty("java.security.krb5.realm", "XXX.COM"); System.setProperty("java.security.krb5.kdc", "kdcXXX"); Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); UserGroupInformation.setConfiguration(conf); UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab"); // 接着執行Connection實例化的代碼塊 try { Class.forName(driverName); Connection conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement(); String sql = "show databases;"; ResultSet rs = stmt.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString(1)); } } catch (Exception e) { e.printStackTrace(); }
對於impala-jdbc驅動,kerberos認證的代碼塊與Connection實例化的代碼塊,二者強耦合,除了保證執行的時序性(kerberos認證在前,Connection實例化在後),還要求在doAs函數,建立Connection,以下圖所示。
java
代碼以下所示。spring
// kerberos認證的代碼塊 // 1. login use keytab System.setProperty("java.security.krb5.realm", "XXX.COM"); System.setProperty("java.security.krb5.kdc", "kdcXXX"); Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); UserGroupInformation.setConfiguration(conf); UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab"); // 在UserGroupInformation的doAs函數中實現Connection的建立 // 2. create impala jdbc connection Class.forName(JDBCDriverName); conn = (Connection) ugi.doAs(new PrivilegedExceptionAction<Object>() { public Object run() { Connection tcon = null; try { tcon = DriverManager.getConnection(connectionUrl); } catch (SQLException e) { e.printStackTrace(); } return tcon; } }); // 3. execute query using conn
對比上述兩段代碼,當引入鏈接池技術來管理Connection時。對不一樣驅動分別說明之。sql
對hive-jdbc狀況,比較簡單,知足兩個代碼塊執行的時序性便可。即確保在鏈接池實例化前,執行kerberbos認證的代碼塊。具體實現方法:① spring bean中的depends-on標籤(見參考文獻[3])。② 配置Listener。見參考文獻[2])。
這種狀況,不是本文章的重點,這裏不對它具體展開。數據庫
考慮到Connection建立是鏈接池類內部的函數。而kerberos認證代碼塊是對Connection建立這一過程自己進行包裹。即kerberos認證的代碼塊,與鏈接池類內部的函數建立Connection的代碼塊,二者強耦合。以下圖所示。
windows
考慮到上述狀況,如何打開鏈接池類的封裝,對鏈接池類內部的getConnection函數加上kerberbos認證的邏輯?
換言之,對如何對一個類的方法進行加強?
最樸素的路子是繼承這個類,而後覆寫這個類中的目標加強方法。
以Druid鏈接池爲例,建立一個類繼承DruidSource,對全部getConnection相關的幾個函數重寫,把kerberbos認證相關的代碼塊嵌入到該函數裏面。這樣能夠經過kerberbos認證,並返回Connection。mvc
public class DruidDataSourceWrapper extends DruidDataSource { // 建立一個函數,指向父類的getConnection(long)方法 public DruidPooledConnection superGetConnection(long maxWaitMillis) throws SQLException { return super.getConnection(maxWaitMillis); } /** * 覆寫父類的getConnection(long)方法,在父類的getConnection(long)方法外面包裹上kerberbos認證的代碼塊 */ @Override public DruidPooledConnection getConnection(final long maxWaitMillis) throws SQLException { // kerberos認證的代碼塊 // 1. login use keytab System.setProperty("java.security.krb5.realm", "XXX.COM"); System.setProperty("java.security.krb5.kdc", "kdcXXX"); Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); UserGroupInformation.setConfiguration(conf); UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab"); // 在UserGroupInformation的doAs函數中實現Connection的建立 // 覆寫父類的getConnection(long)方法,在方法外面包裹上kerberbos認證的代碼塊 DruidDataSourceWrapper _this = this; Connection conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() { public Connection run() { Connection tcon = null; try { // 父類的getConnection(long)方法 tcon = _this.superGetConnection(maxWaitMillis); } catch (SQLException e) { e.printStackTrace(); } return tcon; } }); // 返回connection return conn; } }
在與spring框架集成時,在鏈接池相關的xml配置文件中,關於數據庫鏈接池,class類路徑指向咱們封裝的類路徑便可。app
<bean id="dataSource" class="com.tools.pool.DruidDataSourceWrapper"> <property name="driverClassName" value="com.cloudera.impala.jdbc41.Driver"/> <property name="url" value="your_url"/> <property name="username" value="your_username"/> <property name="password" value="your_password"/> </bean>
上述涉及到對一個類的函數功能進行加強,有點鏈接池類被final修飾,不能被繼承。有沒有其它的方法對不能繼承的類進行加強呢?答案是存在的,是裝飾者模式與動態代理模式。
舉個例子:c3p0鏈接池,比較適合裝飾者模式對getConnection函數進行加強。
對於Java中加強一個類的幾種方法,具體參考文獻[6]、[7]。框架
[1] https://blog.csdn.net/tlqfree... (windows環境 java jdbc 鏈接impala (kerberos認證) - 空谷幽蘭草堂 - CSDN博客)
[2] https://blog.csdn.net/zhanglu... (springmvc集成kerberos認證hive jdbc鏈接 - 張小竟 - CSDN博客)
[3] http://www.aboutyun.com/forum... (hive + kerberos spring 配置 DruidDataSource 數據庫鏈接池-Hive-about雲開發)
[4] https://www.cnblogs.com/zhish... (Spring depends-on介紹)
[5] https://stackoverflow.com/que... (authentication - Error when connect to impala with JDBC under kerberos authrication - Stack Overflow)
[6] https://blog.csdn.net/friday_... (Java中加強一個類的幾種方法 - friday_PJ的博客 - CSDN博客)
[7] https://www.cnblogs.com/xuzha... (對java方法進行功能加強的三種方法)
若是個人技術博客節約了你們的寶貴的時間,歡迎你們請我喝杯茶,^V^。