对于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^。