My studying notes for Java,Ruby,Ajax and other any interesting things.

星期五, 五月 01, 2015

关于gradle和maven库的集成

最近重新学习java,第一步是搞定编译工具,便于后面项目的快速上手,于是简单调研了一下构建工具。

在08年的时候,maven2还比较盛行,但是更多的是ant,因此心里很是怀念ant的时代。没想到一调查,发现ant已经基本上退出了竞争行列,很少项目直接使用ant来build项目了,更多的是使用maven3,以及一个新星:gradle。由于对maven之前掌握就不是很好,大概知道它基于契约,可以做包管理,可以有集中仓库,但是对它一堆的xml的配置深恶痛绝,于是从来没有仔细学会过maven。

看了一下gradle,语法相对简洁,使用groovy来编写的,构建过程也比maven貌似要快一些,尤其在intelj idea中的集成也比较给力。于是就准备认证学习一下gradle,并尝试推广在公司内部使用,看能否代替现在的Maven。

遇到一个问题,maven有强大的包管理工具,gradle更多只是一个构建工具,本身并不提供包管理功能。但是gradle比较强大,支持maven的库,可以在build.gradle中设置使用maven的仓库来实现包管理。

使用maven仓库

在gradle的编译配置文件中,可以使用如下语法定义使用maven库:

repositories
{
    mavenLocal()
    mavenCentral()
    maven
    {
        url 'http://mvn.xxx:8081/nexus/content/groups/public'
    }
}

这里面有几种选择:
  • mavenLocal : 只能使用本地的仓库,默认到~/.m2/repository/ 进行寻址,如果找不到则提示无法找到对应的包和库
  • mavenCentral:中央库,默认寻找~/.m2/repository 来寻找包文件,如果找不到就发起请求向中央服务器获取包文件,按照gradle官方说明,应该是从~/.m2/settings.xml中获取中央库url,但是实际测试的时候发现,貌似忽略了~/.m2/settings.xml,而是直接使用了 http://repo1.maven.org/maven2/ 这个中央仓库,就会导致下载速度非常慢;
  • maven{url xxx} 这种方式可以让gradle在下载包的时候使用指定的本地中央服务器来进行下载

这三者的顺序最好是:

local maven{local server} mavenCentral

这样按顺序寻址,先在本地文件系统查找,如果找不到就到本地server查找,然后再去外部server进行下载。
关于mavenCentral的配置,按道理来将会根据settings.xml寻址,但是我修改了我能够改动的所有settings.xml,都未能如意,并设置了maven_home变量,仍然无效。看来需要stackoverflow问问了。


Gradle编译依赖

Gradle在库包依赖环节中设置的比较灵活,可以依赖于group,单个包,大体上都是:group,包名,版本号
大体定义语法如下:
dependencies {
    compile group: 'foo', name: 'foo', version: '0.1'
}
可以简化如下:
dependencies {
    compile 'foo:foo:0.1','foo:foo2:0.1',
}


Gradle有几种依赖的定义:
  • runtime:运行的时候依赖的包
  • compile:编译的时候依赖的包
  • testRuntime:运行测试用例需要的包
  • testCompile:编译测试代码需要的包
  • default:默认需要的包
  • archives:打包的时候需要打入的一些包

吐槽
这些语法相对maven来讲还是容易了很多。但是无论怎样,要查找依赖的库的版本,包名总是一件很痛苦的事情。在很早以前,没有包集中管理的时候,都是直接到官方网站去下载,存放在本地的目录里面,增加到classpath中,让开发和编译的时候都很容易通过。由于有了,集中管理,不再去官方网站下载,但是库里面有多少包,版本是什么样的都很麻烦才知道。

幸好,在eclipse里面相对容易查找版本文件,也有人闲极无聊,写了一个findmaven.net,可以根据类名查找你的包,并提供版本名称,方便查看代码的同时可以很容易cp到gradle和maven的配置文件中来。

懒人改变世界,此言不虚。

印象笔记,你的工作空间。下载印象笔记

星期三, 十二月 24, 2014

doit.im体验小记

一直以来,使用Evernote作为GTD工具,大概做法是:
1、每天早上上班开始制作计划,格式模板如下,将当天需要完成的事情,按照时间四象限来进行归类整理,列出计划来;
2、每天中午和下午下班前进行记录,记录每天大概做的事情,以及时间消耗;
3、将当日重点事件进行回顾,并将备注信息记录下来,得到的每天总结大概如下:
使用这个流程已经将近有2年了,但是近期总结的时候发现有几个问题:
1、缺少按周、按月的回顾,因为任务和记录已经按照Note进行分日记录了,不便于回顾做了哪些事情;
2、长期任务的管理不好做,如果一个任务(比如读书)跨度比较长,就不容易安排到每日计划中来;
3、没有GTD的inbox过程,因此不方便快速添加和处理任务;当然,也可以通过Email的方式使用@#的title表示法来进行添加任务,但是终究不是专业GTD软件,这块儿不是很nice

于是开始调研新的GTD工具,看了一下有几个不错的,比如Omifoucs、GTD等,最后选择了doit.im,因为在Mac、Android、iOS三端都有很好地client,同步起来很方便,同时也支持中国和国际化的存储(虽然我最后选择了国外,不知道会不会有GFW的风险),做的也比较用心和精致。

下载地址:
http://doit.im mac retina和android的client都可以在其中下载并安装。

有一个tutorial,告诉怎么去使用这个软件,如激活邮箱,创建父子任务,Finish一个任务等。简单体验了一下,感觉还是不错的。
按照标准的GTD流程:
1、收集:inbox,可以通过邮件、手机快捷添加、mac下面的快捷键cmd+n快捷创建任务,其中最为称道的是在android的快捷添加,在任务栏中随时浮现,非常方便;
通过email添加inbox事项时候并没有很好地支持标记语法,比如:
这个在android下面可行,在mail的subject中输入则不可以;
在mac下面创建一个任务的详情:
都比较简单,project相对来说是一个分类,context是做这件事情的环境,比如公司,家里,路上等,优先级比较简单,tags估计主要用于分类和查找。repeat和reminder则相当于将日历的功能放进来,这个存疑,一般情况下mail和canlendar的集成会更加紧密。

2、计划:这个相对比较简单,对于inbox的任务可以快捷方便的拖入对应的项目和日程安排中

3.完成:只需要在手机或者mac app下面选中其中的checkbox,任务自动会标记为已完成。如果想要让doit.im帮你记录时间的话,则在任务详情页中输入花费的小时和分钟,最后系统会自动计算出来该任务的总时间。

快捷方式如下:

目前费用价格是100元/年,感觉还能够接受,刚注册使用可以免费使用1个月的收费权限,然后就变成免费了,免费有个致命缺点是每天只能同步1次。

GTD起来吧,附一张图:

Evernote,你的工作空间。下载Evernote

星期三, 十二月 17, 2014

关于PHP的匿名函数

在阅读一个PHP程序的时候,发现有很多地方都有重复的代码:
/* {{{ getXiaoquBaseInfoByCityPinyin 获取小区基本信息 */
    /**
     * 获取小区基本信息
     * @param  string $city    城市domain
     * @param  string $pinyin  小区拼音
     * @return array           小区信息数组
     */
    public function getXiaoquBaseInfoByCityPinyin($city, $pinyin) {
        try {
            //xiaoqu_xiaoqu
            $xiaoquModel = PlatformSingleton::getInstance('XiaoquXiaoquXiaoquModel');
            $result = $xiaoquModel->getXiaoquInfoByCityPinyin($city, $pinyin);

            $data = array(
                'errorno'  => ErrorConst::SUCCESS_CODE,
                'errormsg' => ErrorConst::SUCCESS_MSG,
                'data' => $result,
            );
        } catch (Exception $e) {
            $data = array(
                'errorno'  => $e->getCode(),
                'errormsg' => $e->getMessage(),
            );
        }
        return $data;
    } //}}}
    /* getXiaoquStatInfoByXiaoquId 获取小区统计信息 {{{ */
    /**
     * 获取小区统计信息
     * @param  int    $xiaoquId 小区id
     * @param  array  $fields   要查询的列
     * @return array
     */
    public function getXiaoquStatInfoByXiaoquId($xiaoquId, $fields=array()) {
        try {
            $model = PlatformSingleton::getInstance('XiaoquStatXiaoquModel');
            $xiaoquIds = array($xiaoquId);
            $result = $model->getXiaoquStatInfoByXiaoquId($xiaoquIds, $fields);
            $data = array(
                'errorno'  => ErrorConst::SUCCESS_CODE,
                'errormsg' => ErrorConst::SUCCESS_MSG,
                'data' => $result[0],
            );
        } catch (Exception $e) {
            $data = array(
                'errorno'  => $e->getCode(),
                'errormsg' => $e->getMessage(),
            );
        }
        return $data;
    } //}}}

一个类有740多行,大量相同的代码,如上面绿色部分都是重复的,感觉应该有办法改进。于是想了解PHP中是否有匿名类或者模板方法的做法。
在java中,一般可以这样来做:
public class A{
   public static void execute(B b){
       try{
            var xxx = b.dosth();
            fmt xxxx;
            return xxx;
       }catch(Exception e){
            deal exception;
       }
   }
}
public interface B {
   public abstract void dosth();
}
public class Test{
    public static void main(String[] argv){
         var xxx = A.execute(new B(){
            public void dosth(){ dosth reallly;}
         }
    }
}
上面代码,先定义了一个A的模板方法类,其execute方法中接受一个接口B的入参b,并在execute方法中调用了b的dosth方法来完成,execute方法本身提供了变量初始化xxx,和异常包装。在调用的时候(粉色代码)实际上使用了匿名内部类,动态的初始化了一个B的对象,并直在代码片段的时候完成了实现。

这个方法需要注意:
1、如果new B(){public void dosth()}里面要用到局部变量,需要将变量定义为final,不可修改,避免出现上下文依赖关系;
2、B的接口dosth的返回值将直接在excute方法中使用,而方法Test中处理的函数可能是个性的,有可能出现类型转换,通常做法是直接使用Object作为返回类型;

对PHP不熟悉,于是参照这个调查了一下php的匿名函数,发现匿名函数是在5.3以后才支持的,于是可以简单得到这样的代码:
[code]
<?php
class A
{
   public static function warpException($fun)
   {
        $astr = "string from warp Exception";
        return $fun($astr);
   }
}
class B
{
   public function methodB($bstr)
   {
        $fun = function($mystr) use($bstr)
        {
          return $mystr.':'.$bstr;
        };
        $bstr="str modified";
        $result = A::warpException($fun);
        return $result;
   }
}

class C
{
   public function methodC($bstr)
   {
        $bstr="str modified";
        $result = A::warpException(function($mystr) use($bstr)
        {
          return $mystr.':'.$bstr;
        });
        return $result;
   }
}

$b = new B();
$re = $b->methodB("this is just a test");
echo $re,"\n";
echo $b->methodB("new Test"),"\n";
$c = new C();
echo $c->methodC("this is just a test"),"\n";

[/code]
其中使用了PHP的匿名函数,如绿色部分。需要注意:
1、PHP5.3以后才支持匿名函数,尚未大规模推广,使用要注意坑;
2、实际上匿名函数就是闭包;
3、在使用的时候要注意use局部变量,避免出现变量变化以后内容不同;
4、在use的时候实际上已经对变量进行了一次值拷贝,后面如果有任何对变量的修改并不会发生变化。上述代码运行结果:
➜  php>  php AnyClassTest.class.php
string from warp Exception:this is just a test
string from warp Exception:new Test
string from warp Exception:str modified

此外,如果你使用的代码没有升级到5.3以后,可以使用__call进行封装,如:


Evernote,你的工作空间。下载Evernote

星期一, 九月 30, 2013

jstorm从源码构建

 
前置条件:(linux下面安装见前面文档)
java
maven
1.将jstorm从github中clone出来:

2.修改pom.xml,以避免zookeeper的cdh3u0版本无法找 到:
       <repository>
          <id>central2</id>
          <name>libs-release</name>
          <url>https://repository.cloudera.com/artifactory/libs-release</url>
        </repository>
增加:utf8支持,避免本地编码的warning
   <properties>
        <powermock.version>1.4.11</powermock.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

3.然后根据deploy文件进行执行:mvn clean mvn package assembly:assembly

途中会有warning提示:
[WARNING] Assembly file: /home/xxxx/code/java/jstorm/target/jstorm-jstorm is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment.
[WARNING] NOTE: Currently, inclusion of module dependencies may produce unpredictable results if a version conflict occurs.
[WARNING] The following patterns were never triggered in this artifact exclusion filter:
o  'com.alipay.dw:jstorm-client'
o  'com.alipay.dw:jstorm-client-extension'

[WARNING] The following patterns were never triggered in this artifact exclusion filter:
o  'com.alipay.dw:jstorm-client'
o  'com.alipay.dw:jstorm-client-extension'
应该没有什么问题,主要是目录警告和模块依赖警告,在mvn3和mvn2有些区别?

4.package完毕后,会在target目录中生成一个tgz文件: jstorm-jstorm.tar.gz,可以用于部署:

结构如下:
`-- jstorm
    |-- bin --运行路径
    |   `-- jstorm
    |-- conf --配置目录
    |   |-- jstorm.log4j.properties
    |   `-- storm.yaml
    |-- jstorm-client-0.7.1.jar --客户端jar
    |-- jstorm-client-extension-0.7.1.jar --客户端扩展
    |-- jstorm-server-0.7.1.jar --服务jar
    |-- jstorm-ui-0.7.1.war--可以部署在tomcat中用于管理jstorm的运行
    `-- lib--第三方依赖的jar包

构建完毕需要在jstorm的目录中touch RELEASE文件,否则bin/jstorm在执行的时候会报告错误:
******************************************
The jstorm client can only be run from within a release. You appear to be trying to run the client from a checkout of Storm's source code.

You can download a JStorm release 
******************************************

安装zmq和jzmq:
zmq:
tar -xzf zeromq-2.1.7.tar.gz
cd zeromq-2.1.7
./configure
make
sudo make install
jzmq:
#install jzmq
git clone https://github.com/nathanmarz/jzmq.git
cd jzmq
./autogen.sh
./configure
make
sudo make install

建议使用2.1.7,避免导致各种兼容问题。

refer: https://github.com/nathanmarz/storm/wiki/Installing-native-dependencies


本邮件及其附件含有"赶集网"的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件!

This e-mail and its attachments contain confidential information from GanJi, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!

星期日, 九月 29, 2013

在centos中安装java

近期准 备将一些服务迁移到java环境中来,简单记录一些操作过程。

1.检查是否安装了openjdk,如果是的话,卸载重新安装oracle官方的jdk
java -version --查看java版本号
rpm -qa|grep java  查看rpm中安装的jdk版本信息
java-1.6.0-openjdk-1.6.0.0-1.40.1.11.11.el5_9
tzdata-java-2013c-1.el5
2.卸载默认安装的jdk信息,使用yum即可:
yum -y remove java-1.6.0-openjdk-1.6.0.0-1.40.1.11.11.el5_9
yum -y remove tzdata-java-2013c-1.el5
3.到oracle官方网站中下载jdk信息,通常使用tar.gz包进行安装:
可以通过uname -a查看自己的linux版本,可以下载32或者64位的jdk安装包
4.安装过程:
mkdir /usr/java
cp *.gz /usr/java
cd /usr/java
tar -xvzf jdk-7u13-linux-x64.gz
mv jdk1.7.0_13 jdk
          如果下载的是rpm包的话可以使用:rpm -ivh jdk-7u13-linux-x64.rpm 进行安装
5.修改profile:
vi /etc/profile 
加入:
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
export JAVA_HOME=/usr/java/jdk
export PATH=$JAVA_HOME:$PATH
export CLASSPATH=.;$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 

然后执行source /etc/profile,令其当前生效,输入java -version检查是否安装完毕


本邮件及其附件含有"赶集网"的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件!

This e-mail and its attachments contain confidential information from GanJi, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!

星期三, 四月 03, 2013

北京的樱花开了,美图共赏

From Evernote:

北京的樱花开了,美图共赏

北京的春天终于姗姗来迟,在一场大雪以后,温度开始回暖。数值开始发芽,花儿含苞欲放,正是北京最漂亮的季节。


同时向大家报告一下生活状态:

  1. 上周一个人去了玉渊潭公园,顺手拍了几张照片,发给大家,希望能够给您带来简单的快乐。

  2. 近期钱包丢了,身份证,银行卡啥的都在里面,一顿证件补办,忙的不亦乐乎。破财免灾,不过向老婆交代上面出了点小问题:里面有结婚照仅存的一张照片,意义非凡,且钱包是她送的。不过所幸老婆大人宽宏大量,在答应一个月购物不受限的情况下,宽宏大量的原谅了我...

  3. 参加了几个投资公司的管理培训,才觉得,做人简单比较容易,但是管人还是蛮不简单的。之前没发现的问题,在被培训的时候才发现都是问题。不知道是培训师把管理搞太复杂,还是我把管理想象太简单了。且不管了,细心观察,仔细学习总有可能用得到。

  4. 看资治通鉴,有不少关于人才的论断还是不错,改天抄过来大家分享;

  5. 有新同学问我,怎么才能简单,从一个男人的角度抄书回复:

    "  

    要担当、要谦敬、要沉潜、要诚信,四者做人要言。

    不浅薄、不浮躁、不寡信、不自傲,四者处世要言。

    平凡平淡,持一平常心。
    简朴简约,持一简单道。
       

    "或者换言之,你开心不费劲就是简单了。对我个人来说,每天早上自己煎个鸡蛋吃,就很高兴,这就是我的简单。

照片来了:

chrome中的一些好的扩展用于代替opera

From Evernote:

chrome中的一些好的扩展用于代替opera

一直以来,我都使用着opera,主要因为有几点:
1.速度快,号称地球上面最快的浏览器,pestro引擎强大的js和css解析能力;
2.html5的支持能力;
3.高可定制性:如单键快捷键,内置支持的鼠标手势,支持rss阅读等,自定义搜索,自定义书别名等;
4.集成性:比如查看页面所有链接并打开,将当前页面部分内容copy note并可以进行管理;
5.opera turbo,当速度很慢的时候开启,速度会变得很快,同时自动做了代理服务器;
当然,还有一些其他的,如内存占用小,几乎从不崩溃等..

但是最近opera转向webkit,看得出来其发展方向摇摆不定,更重要是放在mobile上面。为了让移动浏览体验提升,不得不抛弃了自己开发的Pesto引擎,转而投向webkit的怀抱。而google则最近宣称,将弃用webkit,转而投入兵力开发自己的引擎。

于是,我在想,如果opera在某天以后不再适合我(10多年的opera忠实粉丝..),也需我需要一个其他可以代替opera工作的浏览器。我的眼光看向了chrome,于是今天上午"实地考察"了一下,记录如下。

从单独的chrome本身来说,并没有特别出彩的地方。打开速度与opera相差不大,在很多tab的情况下,略胜于opera。但是设置界面确实比opera简洁太多,且均云端存储,无论你换了哪个电脑,均能自动同步设置。这一点,opera并没有同步设置,只是同步了书签和搜索等功能。缺点:
1.默认没有鼠标手势;
2.快捷键少得可怜;
3.代理设置居然是和ie共享,想要翻墙不容易;

听说都可以使用extension来解决,于是装了这些插件,然后基本上可以代替opera工作了:
1.smooth guesture,用于鼠标手势,基本上与opera的鼠标手势相当,但仅能支持chrome的菜单内容,灵活性和全面性不如opera;
2.shortcuts manager,一个日本人开发的,用于管理快捷键,可以完成opera中的各种快捷键设置功能,包括单键;常用的如:1,2切换tab,r,t,c设置刷新,打开,关闭tab等;
3.hosts管理工具,对开发同学来说比较重要,可以方便的切换测试环境等;
4.adblock,方便屏蔽页面中的各种广告,包括facebook页面的,尝试了一下,比opera的屏蔽更方便,当然,前提是你没有自定义css和js来实现;
5.proxy switchySharp,代理切换。chrome默认的代理管理是与ie浏览器共享的,实在不方便,而且经常不生效(原因不明),于是安装了goagent和proxy swtichy,这两个组合起来,翻墙无敌。


其他的,如one number,tab expose,Tweetshare 等都是增强型,也都还不错,居家必备。

整体来说,装了这些扩展以后,基本可以替换opera了,但是在书签别名(输入b打开百度,jr打开jira),自定义搜索上面还不能完全替换opera。因此,短期内还将继续使用opera,但同时关注chrome。chrome的插件功能还是蛮强大的,能够实现的事情太多了,相比起来opera的扩展简直就是玩具,很期待...

毕竟chrome的设计是按照操作系统来做的,不得不服啊..opera加油吧!