背景:
在hive中编写udf时,我们可能会加载外部的配置文件,可以将配置打到Jar中 ,或者读取mysql配置,或者将配置放在hdfs上。 在使用hiveCli客户端时也可以通过add file 添加资源,然后直接 new FileInputStream(“fileName”)就能加载到 ,最后这种add file 的方式测试下来只能在hiveCli客户端先能读到配置,在beeline 中无法读取到,jar或者mysql 这两种方式在这里不讨论,主要记录下配置放在hdfs 时的处理方式 。
代码
1.首先我们在这里实现udf 时采用的是 GenericUDF 接口
2.重写实现以下方法
3.这里是为了实现可以自定义或者动态传入hdfs上配置文件的路径,而不是写死在Jar中,如下中 sensword.file.path 是通过 -hiveconf 传递进来的,或者可以在开启beeline 后 自行 set sensword.file.path=xxx,这里有一点需要注意的是hive 在set 自定义变量时需要做一些单独的配置,否则在set或者-hiveconf时将会报错,另外还需要注意的是 自定义的变量 不要使用 hive开头 即不能是:hive.sensword.file.path ,这里在set时hive 是禁止的(会报错 not exists 类似的信息):
//这里重写configure 方法 通过此方法 获取到自动注入的 MapredContext 类
//通过context 我们可以获取到外部传入的配置即:-hiveconf 传入的变量值
//注意:hivevar在这里是不会获取的
@Override
public void configure(MapredContext context) {
this.context = context;
}
//这里主要是对函数进行初始化 定义函数返回值类型等
//在这里我们可以使用上面拿到的context 来获取传入的hiveconf值,但是这里有一点要注意 configure 方法只有在
//启动mr 任务时才会被调用,因此 在一些不会启动mr的情况下,这个地方也是获取不到传入的变量的,因此下面的代码中
//会有判空,在为空情况下会使用hive 的sessionState来获取当前传入的变量,这里也要注意在mr情况下 sessionState
//是为空的 ,因此这两部分结合起来正好可以实现在mr 与非mr 模式下的参数获取
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
String path = SENS_FILE_HDFS;
if (context != null) {
//启动mr 任务时
JobConf jobConf = context.getJobConf();
path = jobConf.get("sensword.file.path", SENS_FILE_HDFS);
} else {
//sessionstate 非mr情况下
SessionState sessionState = SessionState.get();
if (null != sessionState) {
HiveConf conf = sessionState.getConf();
path = conf.get("sensword.file.path", SENS_FILE_HDFS);
}
}
logger.info("==>sensword file path: " + path);
.......省略其他无关代码
}
//加载配置文件
//注意此处不要对fileSystem 进行关闭
//这里猜测是跟当前mr 任务共用了相同的fileSystem instance, 这里在new Configuration时不需要传入hive-site.xml 等配置,
//会从当前环境中进行加载
protected void buildSensWordSetFromHdfs(String path) throws HiveException {
try {
fileSystem = FileSystem.get(new Configuration());
FSDataInputStream open = fileSystem.open(new Path(path));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(open));
String line = null;
while (null != (line = bufferedReader.readLine())) {
sensWord.add(line.trim().toLowerCase());
}
bufferedReader.close();
open.close();
} catch (IOException e) {
throw new HiveException(e.getMessage());
}
}
//这里对资源进行释放 ,切忌不要把close 放在初始化方法中,否则hive 不会输出任何结果也不会报错
@Override
public void close() throws IOException {
fileSystem.close();
}
转载请注明: https://blog.csdn.net/sinat_23257429/article/details/121830265