在使用sbt-assembly打包的时候遇到失败。报的错误信息如下: 疑惑了好久。 后来在StackOverflow找到了说明。这个问题是scalaVersion导致的。sbt在build应用的时候会使用scalaVersion这个配置项指定的scala版本执行构建。然而sbt0.13自己是用scala2.10构建的,同样sbt.13的插件也是用scala2.10构建的。如果应用的scalaVersion不是2.10,使用sbt的插件的时候就有可能报上面的这个错。可以简单将build.sbt中的scalaVersion删除,然后再使用sbt assembly就能看到问题解决了。 不过这样并不是最好的解决方案。这个问题的根源是因为我添加sbt-assembly插件的时候是将assembly.sbt放在了根目录下。如果将assembly.sbt这个文件放在应用的project目录下就可以避免这个错误。或者将添加sbt-assemble插件的语句放到./project/plugins.sbt中也是可以的。引用sbt-assemble插件的语句如下: 这个问题纯粹是因为阅读文档不仔细导致的。官网上说的很清楚。以后需要注意。 ########
[阅读更多...]-
使用sbt-assembly提示unresolved dependency
-
HBase Shell整理
简单整理了下HBase Shell的常见命令。 version 查看HBase版本。 status 查看HBase集群的状态。 create 创建表。建表时需要指定表名及列族的名称。 list 列出HBase中创建的所有表的信息。在当前的HBase中创建了两个表,分别是test和test2。 describe 查看某个表的表结构。使用时表名需要用括号括起来。 这个命令也可以使用简写的“desc”来代替。 disable和enable 用来启用禁用表。通常和表结构调整命令或者删除命令一起使用。 is_disabled和is_enabled 用来查看是否已经禁用或启用表。 put 向表里写数据,格式是:put ‘表名’, ‘行键’, ‘列族:限定符’, ‘值’。 get 从表中取一行数据,格式是:get ‘表名’, ‘行键’。 结合上面的put命令,我们可以看出hbase数据更新的方式就是向表里put新的记录。 scan 扫描全表。查看表里的全部数据。 alter 用来调整表结构。 执行前先看一下目标表test2的结构: 表中目前只有一个列族“cf2”,使用如下命令来新增列族“cf1”: 执行结果如下: 使用如下命令来删除列族“cf2”: 执行结果如下: 使用如下命令改变列族“cf1”单元数目: 执行结果如下: count 查看表中有多少条记录,格式是:count ‘表名’: delete 删除指定行键和列族的命令。hbase的删除并不是立刻删除,而是将要删除的记录标记为可以删除,而后在下一次region合并分裂时将标记为删除的记录删除。 命令格式为:delete ‘表名’, ‘行键名’, ‘列族名’, [时间戳]。 执行结果: 可以看到虽然执行了删除命令,但是记录没有被立即删除掉。 deleteall 删除整行数据的命令。 删除命令格式:deleteall ‘表名’, ‘行键名’。 执行示例如下: truncate 删除表中的全部记录。命令格式:truncate ‘表名’。 执行示例如下: 在执行过程中看到truncate表前不需要执行disable命令,truncate命令在执行前就自动执行disable了。 exists 检查表是否存在。命令格式如下:exists ‘表名’。 执行示例如下: drop 删除表的命令。命令格式:drop ‘表名’。 drop前需要先disable。 执行实例: 更新(update) hbase没有提供更新命令。hbase的更新是通过put新的数据覆盖旧的数据来完成的。 hbase是通过行键、列族、时间戳这三个维度来作为数据的唯一性的标准的。所以要更新数据只需要put一条这个维度都一致的数据即可。 参考文档 HBase的数据的update: http://punishzhou.iteye.com/blog/1266341 ######################
[阅读更多...] -
解决Gson 处理Map将整型处理为浮点型的问题
gson一直是我用着非常得心应手的json处理工具。但是最近遇到了一个坑,就是在处理java.util.Map型json字符串的时候会把整型转为浮点型。 示例程序如下: 执行结果如下: 原因在于json的语法中关于数值只有一个number类型,而不会去判断这个number具体是整型是浮点型还是长整型。而Gson处理的时候也确实是偷懒了,统一将之视为浮点型。可以在Gson的ObjectTypeAdapter类中看到: 在case NUMBER这一行可以看到,数值型的数据都被处理为Double型的值。此外因为这里使用的Map的value类型是Object,在示例代码中就涉及到了Integer、Double和String。所以也不能使用TypeToken这样的解决方案。使用TypeToken的方式如下,适用于有明确的泛型说明的情况: 其它的解决方案也简单:1. 使用其他的json库,比如jackson和fastjson,亲测过,都没有这种问题;2. 添加自定义模块,修改这个问题。 详细说明下方案2。Gson支持添加自定义解析方案,可以使用GsonBuilder的registerTypeAdapter和registerTypeHierarchyAdapter。前者只针对设置的类进行序列化及反序列化,后者可以对设置的类及其子类进行序列化。可以添加的解析类的类型包括JsonSerializer、JsonDeserializer和TypeAdapter这三个接口的实现类。下面是一个使用自定义的JsonDeserializer方案: 这个方案也是有局限性的,只适用于Map的key和value都是数值型和字符串的情况(也可以添加对boolean的支持)。对于复杂的Map结构就有些无力了。 此外另一个方案是根据ObjectTypeAdapter自定义TypeAdapter。这个我也试过,功能支持还算可以,它解析json的方式是分层实现的。不过如果目标是具体类还可以,对于抽象类或接口的适用性就差一些。因为关键是json最外层的解析,如果是json对应的是对象的话,也就只能封装成一个目标类型对象或其超类对象。 先就这样。 #############
[阅读更多...] -
Hello Akka
Akka是一个工具,用来在JVM上构建高并发、分布式、容错的事件驱动的应用。Akka支持java和scala两种语言。Akka最强大的一个特性是使用了并发Actor模型。 这一次本文会同时使用java和scala来进行说明。 示例代码 下面是一个非常简单使用akka的的例子。 java(做了折叠): scala(做了折叠): 在上面的例子中定义了一个Greetor Actor,这个Actor可以获取最新的greeting消息,并对两种行为作出响应:设置一个新的greeting字符串;返回最新的greeting字符串。 接下来会详细解释下这个例子。 定义消息类 Actor并没有提供让开发者调用的公共API。它是通过Actor处理的消息来提供公共API的。消息可以是任意类型(java中指的是继承了Object的类,在scala中指的是继承了Any的类)的对象。也就是说我们可以使用包装类来发送直接类型的消息,也可以发送一些数据结构比如数组或者集合类的对象。然而因为消息是Actor的公共API,所以定义消息类的时候需要保证消息类的名称有一定的语义,或者在指定领域内有意义,尽管有时仅仅是将已有的类简单封装了下。不过这样可以构建简单易懂的Actor系统,在调试的时候也可以更容易一些。 在代码中我们定义了三个消息类: WhoToGreet,重新定义新的greeting消息; Greet,向Actor请求最新的消息; Greeting,返回最新的greeting消息。 在示例中这三个消息类定义在外部类HelloAkka中。这里要注意在消息对象中保存的消息应该是不可变的,否则的话就可能会出现两个不同的Actor共享状态的危险,这违反了Actor模型的设计原则。 虽然在这个示例中我们没有使用远程连接,但是在定义消息类时实现序列化是个好习惯——这样我们使用akka扩展到多个节点时就不需要再回过来修改代码。 消息类的定义: 下面是使用scala定义消息类的代码。scala的case类和case对象对Actor消息的支持非常好,因为它们本就是不可变的且支持模式匹配(这在对Actor接收的消息进行匹配时很有用)。使用case类的另一个好处就是其默认支持序列化。 定义Actor Actor是Akka的执行单元。Actor是面向对象的,因为它也封装了状态和行为。但是它要比Java或Scala中的普通对象有更强的隔离性。Actor模型禁止两个或多个Actor间共享状态的行为。一个Actor观察另一个Actor的状态的方式就是向其发送一条消息来请求状态。Actor是非常轻量级的——它只受到内存的限制。每个Actor只会消耗几百个字节的内存,这意味着在一个应用中可以轻松地创建数百万个并发的Actor。Actor模型强大的隔离原则以及事件驱动模型(稍后会说到)和位置透明等特性让我们可以用直观的方式轻松解决并发问题和伸缩性问题。 在java中创建Actor类需要继承抽象类UntypedActor并实现onReceive方法。使用scala也是差不多的方式,需要继承Actor trait并实现receive方法。在onReceive方法中定义了Actor的行为,在这个方法中Actor可以对它收到的不同的消息做出不同的反馈。一个Actor可以有或者说是通常都会有状态。访问或者是改变一个Actor的状态是完全线程安全的,因为这受到Actor模型的保护。 现在开始创建一个Greeter Actor,并使用一个变量greeting作为这个Actor的状态。greeting代表获取的最新定义的greeting消息。在Greeter的onReceive方法里面我们添加了一些行为用来对Greet和WhoToGreet两种消息分别作出反馈。先来看Java的实现: 代码中定义的Actor继承了抽象类UntypedActor,意味着其接收的消息是没有类型约束的,如代码中就是Object。此外也有类限制的Actor,不过目前暂时不关注这些。通常使用的Actor都是没有类型约束的。 暂时先不要考虑代码中定义的getSender()、tell(…)和getSelf()等API。稍后说到发送和响应消息时会详细解释这些API。 现在再看一下scala的实现。如代码中所示,scala case类的模式匹配的特性可以很大程度地简化Actor的receive方法。不过除此以外的内容还是还是和java版本很相似的: 有没有注意到scala版本的Greetor和java版本的一处不同:在scala版本的代码中并没有将未知类型的消息传递给unhandled方法。在scala中这不是必需的,因为scala将receive方法的行为解释为一个偏应用函数,也就是说匹配不上的语句会被默认为不处理,并由Akka自动将之传递给unhandled()方法。 另外一个不同就是Scala版本中继承的trait是Actor,而非是UntypedActor。因为这是scala的API,而不是Java的API,尽管二者本质上是同一种Actor。 创建Actor 到现在我们已经说过了如何创建Actor和消息。接下来我们会说一下如何创建Actor的实例。在Akka中创建Actor实例不能像平常一样直接使用new关键字,需要通过一个工厂来创建。这个工厂也不会直接返回一个目标Actor的实例,而是返回一个指向Actor实例的ActorRef对象。使用ActorRef看起来像是隔了一层,但是却增加了许多功能和灵活性。比如说位置透明:在相同语义的情况下,ActorRef表示的正在运行的实例既可以是在当前进程下也可以是在远端机器上。也就是说,位置并不重要。这也意味着,如果需要的话,可以在运行时改变Actor的位置或者调整应用的拓扑结构来优化系统。ActorRef这种间隔带来的另一个特性是使用“let it crash”模型来进行故障管理:系统可以主动crash故障的Actor并重启以实现自我治愈。 Akka中的这个工厂是ActorSystem。ActorSystem在某种程度上类似于Spring的BeanFactory,它也可以作为所有Actor的容器,执行管理这些Actor的生命周期等工作。可以通过一个名为actorOf的工厂方法创建Actor实例。这个方法需要一个Props的配置实例和一个名称。Actor(和ActorSystem)的名称在Akka中很重要,可以在查看Actor信息和在配置文件中添加配置时使用它们。因此完全有必要花些时间为Actor和ActorSystem起一个好名称。 下面是用java写的代码: scala的代码也没有太多不同: 现在我们已经创建了一个Greeter Actor的运行实例。接下来我们要看一下如何与之进行通信。 告诉Actor去做一些事情 和Actor的所有通信都是通过异步消息传递完成的。这也是如何使Actor做出反应以及事件驱动的方式。Actor不会主动做任何事情,除非它被通知做某事。开发者可以通过发送消息通知Actor做某些事。异步发送消息意味着发件方不会坚持等待接收方处理完消息。相反的,发件方只是将消息发送到接收方的收件箱里,然后就可以自由地去做一些比等待接收方处理消息更重要的事情了。接收方的收件箱本质上是一个队列,且是有序的。这保证了同一个Actor发送的多条消息的排序会被保留,不过却有可能会与另一个Actor发送的消息交治。 你可能会想知道当一个Actor在不处理任何消息时会做些什么事情。会做一些其他的具体的工作么?其实不会,此时Actor处于完全暂停的状态,它不会消耗除了内存以外的任何资源。就像牵线木偶一样。 我们可以通过传递消息到ActorRef的tell方法中告诉Actor去做一些事情。这个方法将消息放到Actor的收件箱以后就会立即退回。 java代码: scala代码: 使用scala还可以写得更简洁一些: 这里使用的“!”是一个绑定操作。 向Actor做出回复 发件方的自引用 在上面的代码里,没有等待Actor作出回复。有时候通信不是简单地单向通信模式,而是倾向于请求应答模式。这时一个直接的方式是添加一个对发件方的引用作为消息的一部分,以便接收方可以通过这个引用发送回复给发件方。这是一个常见的情况,它由Akka直接支持。对于发送的每一条消息,开发者都可以选择是否传递发件方的引用(Actor对应的ActorRef)。如果是从一个Actor内发送消息,那么就可以用过该Actor的自引用访问到这个Actor的ActorRef。然而请注意,不应该这样使用。在Java中可以通过getSelf()访问自引用,在scala中则可以通过self()方法。 java代码: scala的代码就会简单一些了。scala有一个隐式参数列表的特性,它允许自动透明地将参数传递给方法。我们在向另一个Actor发送消息时,可以利用这个特性自动传递对发件方的引用。 下面这段代码如果是在Actor A内部调用的,会在发送消息时将Actor A的ActorRef作为消息的发件方一起传递出去: 如果选择在tell方法中不传递对发件方的引用,或者说是忘记了,就会默认使用一个被称为“dead-letter”的Actor的引用。“dead-letter”是所有未处理的消息的结尾标识,可以使用Akka的事件总线( Event Bus )来订阅这种消息。 引用发件方 发件方的引用将会在接收方Actor处理消息时可用。因为每条消息都有一个与之唯一配对的发件方引用,也就是说接收方处理的每条消息的发件方引用是一直在变化的。因此,如果开发者出于某种原因想要在处理消息后继续使用某个特定的发件方引用,就需要保证持有它——可以考虑将之保存在一个成员变量或类似的结构中。要访问发件方引用,在java中可以使用getSender()方法,在scala中则可以直接使用sender: scala代码如下: 使用收件箱 当前大部分实际应用的Actor应用都会使用不止一个Actor。Actor模型的发明者,Carl Hewitt,最近在一个采访中说道:“One Actor is no Actor. Actors come in systems”。这是很重要且富有智慧的一个评论。要真正利用Actor模型,就应该使用大量的Actor。Actor编程中的每一个难题都可以通过添加更多的Actor来解决——通过将这个难题拆分成更细的子任务并将之委托给新的Actor。 为了简单起见,我们在这个示例中只使用了一个Actor。这意味着如果我们是从主程序与这唯一的一个Actor进行通信,我们就没有发件方,因为我们没有从另一个Actor的内部发送消息。幸运的是Akka提供了一个很好地解决方案:Inbox(收件箱)。 Inbox允许开发者创建一个“actor-in-a-box”。也就是说在Inbox中可以包含一个傀儡式的Actor,通过这个傀儡Actor可以向其他Actor发送消息并接收它们的回复。可以使用Inbox.create()方法创建一个Inbox实例,并使用inbox.send()方法从中发送消息。Inbox内置的傀儡Actor会把收到的所有消息放到一个队列里面,而后可以使用inbox.receive()方法将消息取出来。如果取消息的时候队列为空,那么调用的receive方法将会阻塞——直到有一条消息可以取出位置。很简单是吧。 开发者应该都知道:阻塞非常容易影响性能和扩展性,使用阻塞应当慎之又慎。我们在这实例中使用阻塞方法是因为它可以简化消息流,方便大家理解Actor模型。 现在我们将通过编写Greeter Actor的驱动程序代码来结束这篇文章。 java版本: scala版本: 就这样! 参考文档 http://www.lightbend.com/activator/template/hello-akka
[阅读更多...] -
需要class,interface或enum
引入github上的一个项目后在编译时收到了“需要class,interface或enum”这样的错误。就像下图: 图片是我随便找的,不过错误是一样的。 这样的错误通常是由编码问题导致的,只需要修改文件编码或项目编码就可以了,然而随之而来的另一个问题就是代码中的中文可能会丢失。后来找的解决方案是这样的,在pom中指定项目编码: 还有就是在编译时指定编码格式,具体怎么做也忘了,请自行百度或谷歌吧。
[阅读更多...] -
URI has an authority component
在sbt的repositories中添加了本地的maven仓库,像这样子: 不过在执行时收到了如下的错误提示: 修改起来也比较简单,只需要这样设置即可: 在file://后面多添了一个斜杠。
[阅读更多...]