HIVE使用java生成自定义(UDF)函数,并在hive命令中使用(包含使用加密包但是报验签失败:JCE cannot authenticate the provider BC)
创建一个maven项目(不要用springboot)
引入依赖
<!--添加hive依赖 --> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-exec</artifactId> <version>3.1.1</version> </dependency> <!--添加hadoop依赖 2.7.3--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.1.1</version> </dependency>
增加打包插件,因为我们这个jar最后要把用到的依赖都要打进去 所以要设置下
<!-- 打包配置 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <archive> <manifest> <mainClass></mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- 指定在打包节点执行jar包合并操作 --> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
编写自定义函数类
这里伪代码 输出长度
MyStrLengthUDF.java
import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; import org.apache.hadoop.io.Text; /** */ @Description(name = "my_str_length_udf", value = "", extended = "计算字符串的长度") public class MyStrLengthUDF extends GenericUDF { @Override public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { // 确保输入参数只有一个,并且是字符串类型 if (arguments.length != 1 || !arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE) || !((PrimitiveObjectInspector) arguments[0]).getPrimitiveCategory().equals(PrimitiveObjectInspector.PrimitiveCategory.STRING)) { throw new UDFArgumentException("my_str_length_udf() takes exactly one string argument"); } // 设置输出的ObjectInspector为字符串类型 return PrimitiveObjectInspectorFactory.writableStringObjectInspector; } @Override public Object evaluate(DeferredObject[] deferredObjects) throws HiveException { String str = deferredObjects[0].get().toString(); if (str == null) { return null; } //得出字符串的长度 并输出,这里为了演示 所以用的是输出字符串, return new Text(str.length()+""); } @Override public String getDisplayString(String[] strings) { return getStandardDisplayString("my_str_length_udf", strings); } }
可以在evaluate()方法中编写自己的逻辑
my_str_length_udf :这个是自定义函数的名称,就是我们 到时候执行hive的sql时候 使用的
然后执行打包命令
最后会生成这个文件 这个里面会含有我们依赖的依赖包
因为我们要在hive里面使用,我这里上传到hdfs中 ,根据自己的选择来
hdfs上传命令
hdfs dfs -put /home/udf-1.0-SNAPSHOT-jar-with-dependencies.jar /udf/
这个表示上传到/udf/路径中 根据自己的来
然后登录hive
一般是用 命令 然后输入一个可以创建自定义函数的用户
beeline
创建udf函数
(临时创建) 这种方式只对当前窗口有效
add jar /home/udf-1.0-SNAPSHOT-jar-with-dependencies.jar
CREATE TEMPORARY FUNCTION my_str_length_udf as 'com.hive.udf.MyStrLengthUDF';
永久函数
create function my_str_length_udf as 'com.hive.udf.MyStrLengthUDF' using jar 'hdfs:///udf/udf-1.0-SNAPSHOT-jar-with-dependencies.jar' ;
my_str_length_udf:这个就是上面代码里面的函数名
com.hive.udf.MyStrLengthUDF: 这里就是包路径 我们上面那个类的完整包路径
hdfs:///udf/udf-1.0-SNAPSHOT-jar-with-dependencies.jar:这个就是hdfs里面我们上传的jar的路径
执行之后打印ok 表示添加成功
可以使用hive的命令看是否添加了 查看所有自定义函数
SHOW FUNCTIONS;
可以找到我们加的就行 添加的时候没有指定数据库会自动添加 default. 这个前缀
接着使用hive命令 执行
例如
select my_str_length_udf("123")
然后结果
删除已经添加的udf函数
drop function default.my_str_length_udf;
default.my_str_length_udf:这个是函数名 之所以加上 default. 是因为我们没有指定数据库 大家根据查看函数找下名称
如果我们使用加密包bouncycastle加解密遇到JCE cannot authenticate the provider BC的解决办法
这是因为我们环境使用的是Oraclejdk 这种会对加密包进行验签,但是我们这种打包方式 会把加密包一起打到我们的jar中 破坏了原有的jar包 就会验签不通过
这时候把环境换成openjdk就可以了
但是如果环境jdk不能改
也可以把我们的加密包直接放到hive环境的依赖jar中,然后我们的udf包排除掉加密包 让他直接读取hive环境的加密包 这样也是可以的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-04-23 JAVA中使用JSONPath.eval()取值路径中存在中划线(短横线)'-'
2021-04-23 Xshell连接Ubuntu服务器连接不上 显示拒绝了密码
2019-04-23 Centos上传下载命令