简介
JRuby是纯java软件开发定制定制实现的语言。JRuby使用ruby语法开发。软件开发定制定制不仅可以使用ruby类库,软件开发定制定制同时也可以使用java软件开发定制定制基础类库和第三方jar包。
软件开发定制定制的交互式命令行是通过jruby实现的,当我们输入hbase shell时,实际上最终执行的是org.jruby.Main,并以bin/hirb.rb作为参数,注意是根目录下bin目录中的hirb.rb,而不是hbase-shell中的irb/hirb.rb; 这个类来自jruby的包,作用是把ruby编写的代码转换成java字节码,进而能够运行在JVM中;
JRuby中调用Java
在接触JRuby前我使用过RJB(Ruby Java Bridge,),两者都提供在Ruby中调用Java的功能,仅在这点上来说,感觉它们差不多,其实JRuby的功能要强大的多。如果你只是想在Ruby中简单地调用一些Java代码,那可以考虑RJB。 要在JRuby中使用Java,先要声明程序中需要Java集成,有两种方法,一种用require 'java';另一种直接使用java::java.util.ArrayList这样的语法。无论是何种方法,都要保证所用的Java类在CLASSPATH中。
- require 'java'
- java::java.util.ArrayList
Java类的使用也有几种选择:
include_class已经标记为过时,使用最新的java_import
- java_import "java.util.HashMap"
- x = HashMap.new
- x.put("foo","bar")
调用System.out.println:
java.lang.System.out.println("Hello, world")
值得一提的是这里的”Hello, world”是Ruby的字符串,而非java.lang.String,JRuby会自动对一些类型进行转换,开发者无需自己动手。在Java中,方法和变量都用fooBar这样的形式,而Ruby中则是foo_bar,显然在代码中同时出现这两种形式会很不协调,JRuby很聪明地将Java中的fooBar转为了foo_bar,而常见的getter和setter,也简化为了成员属性的名称,foo是getFoo(),而foo=是setFoo()。用to_java()能将一个Ruby的数组转换为Java中的Object[],如果想要指定数组的类型可以这样:
- [1,2,3].to_java :float # new float[] {1,2,3}
- ["str", "str2"].to_java java.lang.String # new String[]{"str","str2"}
常用的symbol有以下几种::boolean、:byte、:char、:double、:float、:int、:long、:short、:object、:string、:big_decimal(:decimal)和:big_integer(:big_int)。
hbase shell 写入原生的数据类型
- create 'tb2','f2'
-
- put 'tb2','r1','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:short)
- put 'tb2','r2','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:int)
- put 'tb2','r3','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:long)
- put 'tb2','r4','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:string)
-
- put 'tb2','r3','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:Short)
- #put 'tb2','r3','f2',Bytes::toBytes(java.lang.Short::valueOf(10).to_java:Short)
检查插入的数据
- hbase(main):001:0> scan 'tb2'
- ROW COLUMN+CELL
-
- r1 column=f2:, timestamp=1642477231999, value=\x00\x0A
- r2 column=f2:, timestamp=1642477232021, value=\x00\x00\x00\x0A
- r3 column=f2:, timestamp=1642477232042, value=\x00\x00\x00\x00\x00\x00\x00\x0A
- r4 column=f2:, timestamp=1642477284377, value=10
- 5 row(s)
- Took 0.3607 seconds
- hbase(main):002:0>
Jruby扩展Java代码
对Java的扩展主要是用Ruby来实现接口和继承类。先来看下如何实现接口:
- class Compare
- import java.lang.Comparable
- def compareTo o
- this <=> o
- end
- end
如果要实现多个接口,import就可以了,对于未实现的方法,JRuby会把它交给method_missing。有一点要注意,compareTo在这里不能写成compare_to。 至于继承Java类就更容易了,几乎和继承Ruby类没什么区别:
- class MyStringBuffer < java.lang.StringBuffer
- def append(v)
- end
- end
StringBuffer类的append方法有多个overload的版本,接收多个不同类型的参数,它们都会被统一到这个唯一的方法上,理由嘛很好理解,不是吗? 除此之外,JRuby还为Java的集合类提供了很多扩展,让你能用Ruby的方式来操作Java集合。比方说,java.util.Map多了each方法、 []方法和[]=方法;java.lang.Comparable拥有了<=>方法;所有继承自java.util.Collection的类有了each、<<、+、-和length方法;java.util.List有了[]和[]=方法,还实现了sort和sort!方法。
Hbase shell扩展写法
- import org.apache.hadoop.hbase.client.Connection
- import org.apache.hadoop.hbase.client.ConnectionFactory
- import org.apache.hadoop.hbase.client.Table;
-
- conf = @shell.hbase.configuration
- con = ConnectionFactory.createConnection(conf)
- tb2 = TableName::valueOf("tb2")
- table = con.getTable(tb2)
-
- #short 类型的主键
- row = Bytes::toBytes(java.lang.Short::valueOf(10).to_java:short)
- p = org.apache.hadoop.hbase.client.Put.new(row)
- p.addColumn(Bytes::toBytes("f2"), Bytes::toBytes("v1"), Bytes::toBytes("v1"))
- p.addColumn(Bytes::toBytes("f2"), Bytes::toBytes("v2"), Bytes::toBytes("v2"))
- table.put(p)
-
- con.close
-
- #查看类的所有方法
- java.lang.String.methods
Shell 展示类型
默认情况下,通过hbase shell的scan或get等命令获取的中文内容都是16进制的,无法直观的查看数据。
其实hbase shell中是有方法将16进制中文转换成utf-8格式的中文的。
主要有两种方式:
使用FORMATTER => 'toString' 使用:toString
- hbase(main):002:0> scan 'tb2',{FORMATTER => 'toString'}
- ROW COLUMN+CELL
- d column=f2:v1, timestamp=1642408469271, value=v1
- d column=f2:v2, timestamp=1642408469271, value=v2
读取HDFS文件信息
- module HDFS
- require 'java'
- def self.list(conf=nil,uri= nil)
- fs = org.apache.hadoop.fs.FileSystem::get(uri,conf)
- path = org.apache.hadoop.fs.Path.new("/tmp")
- fs.listStatus(path).each do |i|
- puts i.to_s
- end
- end
- end
- conf = @shell.hbase.configuration
- uri =java.net.URI.new("hdfs://example:8020/")
- HDFS.list(conf.uri)