Git服务器之Gerrit的搭建及第一次使用注意事项

公司的代码托管打算由SVN迁移到Git,刚好老大让老夫全权负责这个事(感谢老大信任),老夫根据自己使用Git的经验,选择了Gerrit作为服务器,下面介绍一下老夫搭建Gerrit服务器的过程及第一次使用时需要注意的事项,如果以前没有用过Git可以参考老夫之前写的这篇文章和这篇文章。 环境准备 ①. Linux,Gerrit需要Linux环境,至于是哪个发行版本就不重要了,ubuntu还是centos随意; ②. JDK,这个怎么安装就不说了,Java程序猿都会,就是不会网上一搜一堆,不做赘述; ③. MySQL,其实这个非必须,Gerrit自带的有H2数据库,但没法老夫就是喜欢MySQL; ④. nginx,作为认证和反向代理服务器; ⑤. Maven, 在安装的过程中会下载一些jar文件; ⑥. Git,这个忘了是不是必须的了,但还是装上吧,反正也不多,大家可以自己试一下需不需要(欢迎留言指出); 数据准备 ①. 自己去Gerrit的官网:http://gerrit-releases.storage.googleapis.com/index.html,下载一个合适的版本,就是一个war包,这也就是我们为什么需要先装JDK的原因,需要说明的是Gerrit的1.X版本是Python写的,2.X改成了Java,变成了一个war包; ②. 为Gerrit创建一个数据库,库名您随意,最好有意义,例如就叫reviewdb 开始安装 开始安装之前,有人建议专门为Gerrit创建一个用户用户运行Gerrit,并且禁止登陆,这里从简,如果你非要这么做可以这么做: adduser gerrit2 passwd –delete gerrit2 然后以gerrit2运行安装,老夫就从简了,直接敲一下命令: java -jar gerrit-xxx.war init -d review gerrit-xxx.war就是你之前下载的war包,review是一个路径,就是安装到这下面,你可以随意定义,敲完这个命令,就进入一下交互(你的可能不太一样),在里面我加了一些注释: Gerrit Code Review xxx 选项中大写字母为默认选项,如使用默认选项回车即可 Create ‘/home/review’ [Y/n]? Git Repositories gerrit用于存储git仓库的目录,相对于根目录review #就是之前-d后面的路径 Location of Git repositories [git]: SQL Database Database server type [h2]: mysql #数据库选mysql Server hostname [localhost]: Server port [(mysql default)]: Database name [reviewdb]: Database username [root]: root’s password : confirm password : User Authentication 使用HTTP认证,OPENID需要服务器连接互联网,还可以使用LDAP认证服务 Authentication method [OPENID/?]: http #这里建议选http Get username from custom HTTP header [y/N]? SSO logout URL : Email Delivery gerrit发送邮件设置,可以使用本地或远程SMTP服务器, 只要在smtp服务器上有帐号即可。 SMTP server hostname [localhost]: #这里我并没有选择邮件发送服务器和其他的配置,不知道为什么也可以发邮件 SMTP server port [(default)]: #事实上发邮件是必须的,有知道为什么,可以告知,谢谢 SMTP encryption [NONE/?]: SMTP username [root]: root@localhost.localdomain’s password : confirm password : Container Process 使用root用户运行gerrit Run as [root]: Java runtime [/usr/lib/jvm/java-7-openjdk-amd64/jre]: Copy gerrit-2.8.1.war to /home/review/bin/gerrit-xxx.war [Y/n]? Copying gerrit-2.8.1.war to /home/review/bin/gerrit-xxx.war SSH Daemon gerrit自带的ssh服务,与服务器自身的ssh服务无关,监听默认端口即可 注意:如要使用低于1024的特权端口,需authbind授权,否则ssh会绑定端口失败 Listen on address [*]: Listen on port [29418]: Gerrit Code Review is not shipped with Bouncy Castle Crypto v144 If available, Gerrit can take advantage of features in the library, but will also function without it. Download and install it now [Y/n]? Downloading http://www.bouncycastle.org/download/bcprov-jdk16-144.jar … OK Checksum bcprov-jdk16-144.jar OK Generating SSH host key … rsa… dsa… done HTTP Daemon 这里使用nginx反向代理gerrit,所以只在loop接口监听即可。 如果使用域名访问gerrit,最好将规范URL设置为域名形式,发送校验邮件时会使用到 Behind reverse proxy [y/N]? y Proxy uses SSL (https://) [y/N]? Subdirectory on proxy server [/]: Listen on address [*]: 127.0.0.1 Listen on port [8081]: Canonical URL [http://127.0.0.1/]: Plugins 选装插件 Install plugin download-commands version v2.8.1 [y/N]? Install plugin reviewnotes version v2.8.1 [y/N]? Install plugin replication version v2.8.1 [y/N]? Install plugin commit-message-length-validator version v2.8.1 [y/N]? Initialized /home/review Executing /home/review/bin/gerrit.sh start Starting Gerrit Code Review: 因为为ssh服务选在了低于1024的端口,且没有authbind端口授权,所以会出现如下错误,高于1024端口不会。 FAILED error: cannot start Gerrit: exit status 1 Waiting for server on 127.0.0.1:80 … OK 服务器上没有X,所以使用浏览器打开连接失败 Opening http://127.0.0.1/#/admin/projects/ …FAILED Open Gerrit with a JavaScript capable browser: http://127.0.0.1/#/admin/projects/ 到了这里只能说好了一半,如果你直接通过域名访问,会报一个认证失败的错误,错误就不贴了,大家自己看看就知道了 需要说明的是,以上这些配置,也可以通过修改:review/etc/gerrit.config 进行修改,修改之后重启就好了 ...

October 17, 2015 · 4 min · 833 words · Bridge Li

Bug之我见

作为一个工作两年多的程序猿,可以说每天都在和bug打交道,一方面我们在源源不断的创造bug,另一方面我们又致力于消灭一个又一个被我们创造出来的bug。有人说,话不可绝对,否则就是错了,那么说句话的人有没有意识到他这句话就是绝对的呢?是不是也是错的呢?借用他这句话的意思,那么他说的这句话肯定也是错的,事实上也确实就是错的,因为在软件编程界有一句话:世界上没有bug的系统是不存在的,这句话可以说是绝对的正确的。那么世界上没有bug的系统既然是不存在的,那么这么多系统是怎么被上线又运行良好的呢?这就要从什么是bug,bug的严重程度,优先级说起。 首先要说明的是,老夫是一个程序猿,作为一个软件开发者,对bug的理解肯定没有相关的QA人员理解深刻,所以难免有错误,既然如此老夫为什么又要越俎代庖写下这篇文章呢?因为老夫工作的这两年里,深深地感觉有相当一部分QA,对bug的理解并没有那么的深刻,所以老夫希望能够根据自己工作的经验、自己对bug的理解写出来,以期能够抛砖引玉,希望有识之士给予指点,好了,下面我们就开始从什么是bug说起。 一. 什么是bug bug,在IT公司里,每天都会听到这个词,那么什么是bug呢?或者说什么不是bug呢?在IT公司里面,有一部分人员是专职的QA,那么是QA说这是bug就是bug的吗?因为他们最喜欢的提bug了,他们的工作也是提出软件中的各种bug,还是程序猿说这不是bug就不是bug了呢?因为程序猿最不喜欢听到的一句话也许就是:某某系统或者功能又出bug了吧。我想肯定都不是,因为如果QA说是bug就是bug的话,因为QA也可能对需求理解的并不充分或者说理解错误;但如果程序猿说不是bug就不是bug的话,那么世界上的所有系统将不会有bug,又何谈世界上没有bug的系统是不存在的呢?下面老夫给出自己的理解: 系统说明书上有而系统上却没有这个功能; 系统有这个功能,但是所表现出来的和软件需求说明书上的不一样; 系统说明书上没有,而系统上却有这个功能; 我想①和②大家都能理解的,就不举例说明了,但③可能有些人不能理解,需求说明书上没有,程序猿会做?当然不是不可能的,例如登陆的时候,需求说明上并没有验证码这一项,而程序猿根据自己的经验,很多系统都有,自作主张加上了,那么是不是一个bug呢?肯定是的,理解了什么是bug之后,我们看看bug的严重程度。 二. bug的严重程度 严重程度的英文是:Severity,一般来说不同公司对bug严重程度的是分级是不同的,但一般是根据系统是否符合产品说明书以及缺陷对于现阶段测试的影响而定义的,这里只给一个一般性的说明,一般来说bug可分一下五级: 紧急(Crash) 一般是:不能执行正常基本流程,或者重要功能没有实现,使系统崩溃或资源严重不足。无法正常更正的问题。 例如:由于程序所引起的死机、非法退出、程序中断、死循发生死锁、数据通讯错误、功能与需求严重不符、异常退出、重要功能未实现等等 需要说明的是:一般紧急问题需要版本立即处理,处理后立即发版本。 非常高(Major) 高一般是:影响其他模块功能不能正常操作,导致一些流程无法进行。 如:小功能没有实现、系统所提供的功能或服务受明显的影响、非法操作数据溢出、一般的数值计算错误 非常高的问题可视情况延迟处理,处理后需发版本,方便后期测试。 高(Minor) 一般是:用户常操作的基本功能没有实现,存在合理的更正办法,用户可进行基本操作。 如:界面错误、格式错误、简单的输入限制未放在前台进行控制、小流程、功能错误 紧急、非常高、高等级的Bug的修改直接影响到产品能否合格的交付。 中(Trivial) 中一般是:操作者使用不方便,但是不影响功能的实现。可改善的功能。数据边界不合理。 如:辅助说明描述不清楚、显示格式不规范、系统处理未优化(性能)、长时间操作未给用户进度提示、提示或页面文字规范、操作时未给用户提示、个别不影响产品理解的错别字、文字排列不整齐等一些小问题、使操作者不方便,操作失误可能导致严重问题出现、浏览器、系统、数据兼容性 低(Nice to Have) 低一般是:易用性和建议性的功能 如:不影响使用的瑕疵、更好的实现方式。 需要说明的是,bug的严重程度一般应由测试人员定级 三. bug的优先级 bug的优先级的英文是:Priority,bug优先级应根据发版需求、公司要求、bug发生率和bug严重程度来划分。主要用于提示研发同事即时修复bug,使版本能按照预期发布,和严重程度一样,也分一下五级: 紧急(Urgent) 立即修复的bug,他阻止相关开发人员的进一步开发活动,立即进行修复工作;阻止与此密切相关功能的进一步测试 非常高(Very High) 本版本必须修复的bug 高(High) 必须修改,不一定马上修改,但需确定在某个特定里程碑结束前须修正 中(Medium) 时间允许应该修复的bug或可以暂时存在的bug 低(Low) 可不修复的建议,可以一直存在的问题 四. bug的严重程度和优先级的关系 看了bug的严重程度和优先级之后,我们再说说他们之间的关系?当时我和同事再说这个问题的时候,他们都认为这还用说,bug严重高的优先级也一定高啊!事实是这样的,事实上他们之间并没有关系,严重级别的bug不一定优先级别高;优先级别高的bug也不一定严重级别高。因为优先级别和暂时发版的模块密切相关,但是bug严重程度与暂时发版无关,另外Bug的优先级别和公司要求也有关,如电子商务网站,那么界面优化用户体验对于公司就很重要;虽然界面上的问题并不影响使用,所有严重级别不高,但优先级却非常高;而有些系统只是内部使用,界面优化就不那么重要了;还有一些网站只是数据正确性要求比较高,界面和操作要求不高等等。这些都是严重程度很低,优先级却不一定的例子,最后再给大家说一个windows的记事本的bug,大家可以新建一个记事本在里面输入:“联通”俩字保存退出,再打开看看,这个严重程度够大了吧?但微软却一直并没有修,说明了什么问题?类似的例子还有很多,大家可以自己想想:什么的bug严重级别很高,优先级也很高,什么的bug严重级别很高,优先级却很低,什么样的bug严重程度很低,优先级却很高,什么样的bug严重程度很低,优先级也很低。

September 27, 2015 · 1 min · 50 words · Bridge Li

Blog迁移记

以前老夫的Blog是在西部数码买的空间,转眼一眼就到期了,幸好一朋友免费赞助的一空间,然后就把自己的Blog迁移过去了,下面就总结一下自己的迁移经验,以供需要的朋友或者自己将来再次迁移只用,先说明,老夫用的是典型的LAMP环境,另外Linux环境的Ubuntu。 LAMP环境,Linux最好弄了,你买空间的时候,选择Linux,并选择发行版本就完了,下面开始从A说起 一. A(Apache) 1.安装apache2 安装命令: sudo apt-get install apache2 启动/停止/重启apache2: service apache2 start/stop/restart 卸载apache2 之前卸载重新安装后找不到apache2.conf配置文件,测试使用以下方式卸载后可用。 (1) sudo apt-get –purge remove apache2 sudo apt-get –purge remove apache2.2-common sudo apt-get autoremove (2) (关键一步)找到没有删除掉的配置文件,一并删除 sudo find /etc -name "\*apache\*" -exec rm -rf {} ; sudo rm -rf /var/www 二、M(MySQL) 安装MySQL sudo apt-get install mysql-server 修改MySQL的默认字符集 登陆进去之后查看字符集: show variables like ‘%character%’; 默认字符集不是UTF-8,不符合我们的要求。则需要修改。修改过程如下: 使用如下命令,打开MySQL的配置文件: vim /etc/mysql/my.cnf 在[client]下添加如下一行代码: [client] default-character-set=utf8 在[mysqld]下添加如下两行代码: [mysqld] character-set-server = utf8 init_connect=’SET NAMES utf8′ 保存后退出,然后重启MySQL: ...

September 5, 2015 · 1 min · 133 words · Bridge Li

Git开发最佳实践

回头想想老夫工作已两年余了,在这两年里面有一年半是用Git作为代码版本控制工具的,自从接触到Git,老夫可以说很快就成为了其一个脑残粉,被Git的易用性的强大功能所吸引,上周和我们team的小伙伴们分享了一下老夫以前Git的使用心得(当然分享的效果很不理想,实在是失误),还好老大赏识,让老夫结合自己之前的使用经验整理一个Git的开发规范流程,以供公司项目由SVN迁移到Git之后,大伙统一规范开发,刚好老夫也愿意趁此机会,整理一下自己的思路,结合自己以前使用经验,放在自己的Blog上,以供所有看到这篇文章的小伙伴参考,且大言不惭,定为:Git开发最佳实践。需要说明的是看这篇文章的人,老夫默认为对Git已经有了一定的基础,如果没有请看老夫之前写的这篇文章。 其实老夫窃以为Git的开发规范其实最重要的就是Git的分支管理,而分支又分远程分支和本地分支,本文将从远程应该存在哪些分支、本地应该存在哪些分支、为什么要存在这些分支、在这些分支上应该有哪些操作、这些分支的作用以及这些分支的生命周期一一说明。 一、远程 远程分支是由于我们开发人员在和同组小伙伴相互合并代码而生的,如果不是这我们可以不要远程分支,在远程应该存在三种类型的分支:master分支、feature分支和hotfix分支,记着这里说的是三种类型的分支而不是三个分支,下面将对此三种类型的分支一一解释。 master分支 首先说master分支的生命周期,master分支是生命周期最长的分支,他诞生于项目一开始,结束语项目的废弃,也就是master分支的生命是同步于项目的,只要项目存在就有这个分支; master分支上的操作:因为我们所有的操作都只能是在本地,所以远程分支实际上是可以认为没有任何操作的; master分支的作用:master分支①、是新建项目的默认分支,它不存在也就不存在项目,②、master分支上始终只能是最新的经过测试的可以正常跑的代码,③、每一个里程碑式的版本(可以理解为上线版本)都必须在此分支上打版本号,并注明为什么打此版本号,以供运维上线和将来万一回滚之用,同样也是我们查询我们每一次上线版本历史记录的依据; 为什么要有master分支:同步项目生命而默认而存在的,不可能没有,也不能没有。 feature分支 feature分支是功能分支,开发新功能的时候创建,所以feature分支永远应该(记得是应该)是依托于最新版本的master上分支的代码而建立的,该master可以是远程master也可以是本地master分支,后面我会说明原因; feature分支的生命周期,feature分支生命周期应该是仅次于master分支的,他在我们开发新功能的时候创建,在我们完成新功能(即完成了测试等一系列流程,可以上线了)的时候生命终止,为避免远程分支太多太乱,可以删除; feature分支上的操作:上文已经说过远程分支实际上是可以认为没有任何操作的; feature分支的作用:就是我们基于最新代码开发新功能而用,仅此而已; 为什么存在feature分支:一言以蔽之,基于我们开发新功能时不相互影响,具体来说虽然没有此分支也是可行的,但如果不存在该分支,可能的后果,team中A开发了一个新功能,直接提交到了master上,测试人员在测试中,此时team另一个成员B开发了另一个新功能也提交到了master上,并且测试也已经完成,需要紧急上线,但由于master上有A提交的未经测试的代码,上线就会存在风险,如果不上线,大家都懂得,故必须存在此分支。 注:feature分支是开发新功能的时候创建的,所以如果我们同时开发多个新功能,那么远程就会同时存在多个feature分支 hotfix分支 hotfix分支可以理解为线上代码出现紧急bug时,为修复此bug为紧急建的一个分支,因为是为修复线上系统出现的紧急bug而生,所以其也应该是依托于最新版本的master分支上的代码而建立的。 hotfix分支因为是为修复紧急bug而生,那么其生命周期是随bug的出现而出现,随bug的修复而终止; hotfix分支也是远程分支,同样可以认为没有任何操作; hotfix分支的作用,自然就是修复线上系统出现的紧急bug而生; 至于为什么存在该分支,看了上面就不用多说了吧; 好了,远程的三种类型的分支说完了之后,我们就应该说本地存在哪些分支了 二、本地 本地是我们开发人员在本地为开发各种新功能、修各种bug而建的分支,我们开发人员所有的操作可以认为都是在这些分支上,同样和远程存在多个分支一样,本地也会存在多种类型的分支:master分支、feature分支、hotfixe分支和dev分支,同样这里说的是四种类型的分支而不是四个分支,下面同样对这些分支一一说明。 master分支 不错,不仅只有远程有master分支,本地也有一个master分支和远程对应,其的出现也是在我们clone远程分支时而默认出现的,既然本地master是和远程master分支对应的,所以他的生命周期也是显而易见的; 在这里也可以解释一下,远程feature和hotfix为什么既可以基于远程master分支而建,也可以是基于本地的,因为本地的master分支是和远程对应的; 本地master分支上的操作:在本地master分支只允许出现四种操作:pull、push、merge、rebase,其余的一律不允许出现,记着这个要求还是非常高的,另外他pull的是远程master分支上的代码,push也是把本地master分支上的代码推送到远程master分支上,而merge和rebase当然是merge和rebase的feature分支了; 本地master的作用:1. 除非本地没有代码,否则本地就会出现该分支,但不出现又有什么意义呢,2. 合并其他已经开发完成的feature分支,然后把这些代码一并推送到远程master分支上,3. 在本地master分支上新建tag,并把这些tag推送到远程,供运维上线; 为什么存在该分支,也不用说了吧。 feature分支 同样本地feature分支是和远程feature分支对应,在我们开发新功能的时候,不可能只有一个远程的分支,而本地没有,因为如果本地没有的话,我们又怎么开发呢,所以这就是为什么存在本地feature分支; 看了存在本地feature分支之后,本地feature分支的生命周期也就出来了,和远程feature分支是一样的; 本地feature分支的操作:在本地feature分支上,原则上只允许存在:pull、push、merge、rebase,记着这是原则上,并没有本地master分支的要求高,在本地feature分支行如果有其他操作也是可以的,但之所以这么要求只要出现这四种操作,是为了将来和同组的小伙伴合并代码方便,如果不这么做代码也是能合并的,但如果一旦出现冲突,合并起来会稍麻烦。 需要说明的,本分支push到的是远程feature分支,pull的也是远程feature分支,而merge和rebase的是基于其建的dev分支的代码 hotfix分支 有了本地master分支和本地feature分支的说明,所以聪明人肯定猜出来了,本地hotfix分支也是和远程hotfix分支是对应的,那么生命周期自然相同; 相信从上面的说明中,和这些分支名字上我们就可以看出,hotfix和feature分支本质上是一样的,仅仅是feature分支是开发的一个大功能,需要多人协作多天才能完成,而hotfix大多都是一些比较紧急的、需要立马修复的一个小功能而已,所以在他上面的操作一个是和feature分支一样的,存在的原因自然是为了修复线上紧急bug而存在的。 dev分支 说完了以上三种类型的分支,下面就是最常见的dev分支了,他是没有一个分支和远程对应的,他也是我们开发中日常操作的一个分支; 根据上面的说明,无论是开发一个新功能还是修复一个紧急bug是,都会在本地建一个对应的分支,而在这些分支上只允许出现那四种操作,所以其他的操作就只能在这个分支上了,也就是说,我们在开发一个新功能的时候,我们应该基于本地的feature分支创建一个dev分支,在这上面开发我们的新功能,开发完成后合并到本地feature分支上,然后推送到远程feature分支上,供测试人员进行测试,测试人员对该新功能测试完成后,合并到本地master分支上,最后一并推送到远程master分支上,打tag,上线。 说完了,远程、本地应该有哪些分支,这些分支的作用、生命周期之后,下面列出一些要用到的几个重要的命令 三、分支管理用到的几个最重要的命令 本地master分支推送到远程,也就是创建远程分支 feature git push origin master:feature 注意此命令的“冒号”前后不要加空格,否则会报错。当然也可以用下面的命令,也是我习惯的命令,先在本地基于 master 分支创建 feature 分支,然后把本地 feature 分支推送到远程,也就是现在 master 分支上执行第一个命令,会创建本地并切到 feature 分支上,然后在本地 ferture 上执行第二个命令 git checkout -b feature git push origin feature:feature 当然创建远程 feature 分支,除了用命令外,还可以是用 Gitlab 和 gerrit 的 web 界面创建 ...

August 16, 2015 · 1 min · 188 words · Bridge Li

工作流Activiti5入门(上)

刚工作的时候曾经用Activiti5,但由于当时介于水平,对Activiti5并没有很深的理解,而且知识也没有形成一个体系,前一段时间偶然发现传智播客公布了一个关于Activiti5的教学视频,自己跟着看了一下,感觉有很多收获,所以打算写几篇博文,整理一下,以供将来如有需要的话可以查阅,今天记下学习的前一部分,称为Activiti5上。 一. Activiti5开发环境搭建和配置 开发环境搭建 Activiti5开发一个工作流系统,首先肯定是要搭建环境的,关于搭建环境老夫窃以为这篇文章:http://www.zhengmenbb.com/archives/98.htm,写的很不错,这篇文章不仅写了怎么搭建环境,还有一个小小的例子,大家可以先看一下,看了这篇文章,我相信大家搭建好环境不是问题,因为就是装一个插件而已,很简单。 配置 现在的任何框架几乎都要和spring相整合,否则几乎可以说是玩不转,所以我们的Activiti5要想流行起来也不能例外,下面我们先看看他们怎么整合的。 spring的整合肯定要引入spring的jar包,这个老夫默认大家都会了,如果不会的话,我相信也不会看到这篇文章,至于Activiti5要引入那些jar文件,可以参考这个 (1). 部分pom文件 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>5.11</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>5.11</version> </dependency> 我们可以先把最基本的引入,如果不够肯定会报classnotfoundexception,到时候我们就知道缺少哪个了,老夫的原则是能少引入绝不多引入,原因一是怕冲突,二是文件大小和启动速度 (2). 和spring集成的配置文件activiti.cfg.xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!&#8211; 连接数据的配置 &#8211;> <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/itcast0711activiti?useUnicode=true&characterEncoding=utf8"></property> <property name="jdbcUsername" value="root"></property> <property name="jdbcPassword" value="root"></property> <!&#8211; 没有表创建表 &#8211;> <property name="databaseSchemaUpdate" value="true"></property> </bean> </beans> 这个集成文件简单吧?对,就是这么简单,至于spring等其他的配置文件啊,log的配置文件就不多说了,接下来我们要开始Activiti5的实战:开始写代码。 二. Activiti5实战 Activiti5实战,所以第一步肯定是画图,但装好了环境之后,其实上面那篇文章是有怎么画图的,所以画图这个就先讲怎么花了,大家可以画一个最简单的练手,本文作为一个入门教程,也不会涉及到那些复杂的图,所以第一步,咱直接开始启动流程定义。 因为Activiti5所有的操作都和ProcessEngine相关,所以所有的操作都和ProcessEngine相关,我们就先获取这个对象,当做第0步吧: ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 部署流程定义 部署流程定义,有两种,1. 从zip部署,也就是把我们的流程图压缩成zip,然后上传到项目的根目录,部署流程。 ...

August 2, 2015 · 2 min · 355 words · Bridge Li

Dubbo和zookeeper入门实例

公司项目里用到了dubbo,感觉挺好玩,以前没有玩过,自己抽时间就小小研究了一下,今天记录一下自己的学习成果。 关于Dubbo和zookeeper是干嘛的,网上一搜一大堆所以就不多做介绍了,想了解的可以自己搜搜看,今天就只记录怎么跑一个最基本的Dubbo和zookeeper小示例程序是怎么跑起来的,当然虽然是一个demo,但和真实环境也是无差的哦。 一. 安装zookeeper 要想使用Dubbo,必须给Dubbo一个注册中心,当然这个注册中心不一定必须是zookeeper,也可以是redis等,但用zookeeper是一个相对比较好的方式,咱们暂且就这么办。 关于zookeeper的安装,老夫窃以为这篇文章写得非常棒,就不多赘述了,大家可以直接参考:http://blog.csdn.net/wxwzy738/article/details/16330253,看了这篇文章,大家立马就会就明白怎么一回事了,看过自知。 二. Dubbo实现 Dubbo的实现肯定是要靠自己写代码啦,我的代码使用maven编译的,引入的jar文件如下: 依赖的jar文件 <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <exclusion> <artifactId>spring</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.7.RELEASE</version> </dependency> 其中junit和spring-test大家肯定看出来是干嘛的了,为了跑测试,Dubbo分为生产者和消费者,接下来我们先看看生产者是怎么实现的 生产者的实现 ①. 配置文件applicationProvider.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!&#8211; Auto Scan &#8211;> <context:component-scan base-package="cn.bridgeli.provider" /> <!&#8211; Application name &#8211;> <dubbo:application name="hello-world-app" /> <!&#8211; registry address, used for service to register itself &#8211;> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!&#8211; expose this service through dubbo protocol, through port 20880 &#8211;> <!&#8211; <dubbo:protocol name="dubbo" port="20880" /> <dubbo:protocol name="dubbo" port="9090" server="netty" client="netty" codec="dubbo" serialization="hessian2" charset="UTF-8" threadpool="fixed" threads="100" queues="0" iothreads="9" buffer="8192" accepts="1000" payload="8388608" /> &#8211;> <!&#8211; Service interface Concurrent Control &#8211;> <!&#8211; <dubbo:service interface="cn.bridgeli.provider.service.ProviderService" ref="providerService"/> &#8211;> <!&#8211; 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类 &#8211;> <dubbo:annotation package="cn.bridgeli.provider.service" /> <!&#8211; Default Protocol &#8211;> <!&#8211; <dubbo:protocol server="netty" /> &#8211;> </beans> 注释很详细,不解释,就是dubbo和spring的集成 ...

July 26, 2015 · 3 min · 497 words · Bridge Li

Hadoop集群搭建及运行初步

一直以来对Hadoop都非常有兴趣,所以这一段时间研究可以下Hadoop集群的搭建,今天写一篇小文章,主要是当做自己的笔记,因为写Hadoop怎么搭建的太多了,好了废话不多说,下面开始正文 一、环境准备 系统环境 因为我个人比较喜欢Linux,另外很多资料都是基于Linux的,所以本文也不能例外,系统当然是Linux啦,开发是老夫最喜欢的Ubuntu,当然这个是看自己喜欢那个版本 安装JDK 运行Hadoop需要jre环境,所以如果你的机器没有装JDK,那么就装吧,Ubuntu可以用apt-get install安装,也可以到这个地方:http://www.oracle.com/technetwork/java/javase/downloads/index.html下载然后安装,我个人比较喜欢后一种,因为这么我们可以自己选择装到哪个地方,有利于我们自己配JAVA_HOME、CLASSPATH以及PATH,配置如下: vim /etc/profile 然后在里面添加: export JAVA_HOME=/home/jdk1.7.0_40 export CLASSPATH=".:$JAVA_HOME/lib:$CLASSPATH" export PATH="$JAVA_HOME/:$JAVA_HOME/bin:$PATH" 然后执行生效 source /etc/profile 我们可以任何目录下面测试JDK安装是否成功 实现SSH无密码登陆 因为hadoop namenode要悄悄的SSH到各datanode中去启动相应的JVM进程,所以必须实现namenode能无密码登陆到datanode所在机器 配置命令如下: sudo apt-get install ssh ssh-keygen -t rsa -P &#8221; -f ~/.ssh/id_rsa cat /home/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 可以用命令: ssh localhost 检查是否配置成功,如果有提示授权成功等字样,则表示配置成功。 二、安装Hadoop 环境准备好之后,就要开始安装Hadoop,Hadoop有很多版本,我们是以hadoop-1.2.1为基础,首先下载Hadoop,下载地址:http://www.apache.org/dyn/closer.cgi/hadoop/common/,下载之后我们把它copy到/home下,解压: tar -zxvf hadoop-1.2.1-bin.tar.gz 解压之后我们找到Hadoop的conf文件夹,下面我们的配置都将在这个文件夹下 首先要配置的文件是:hadoop-env.sh,我们打开这个文件,找到配置JVAV_HOME的那一行,把注释打开,写上我们安装的JDK的路径 配置core-site.xml,打开该文件,在文件中添加: <configuration> <property> <name>hadoop.tmp.dir</name> <value>/hadoop</value> </property> <property> <name>dfs.name.dir</name> <value>/hadoop/name</value> </property> <property> <name>fs.default.name</name> <value>hdfs://localhost:9000</value> </property> </configuration> 配置hdfs-site.xml,同样添加: <configuration> <property> <name>dfs.data.dir</name> <value>/hadoop/data</value> </property> </configuration> 配置mapred-site.xml,也是添加 <configuration> <property> <name>mapred.job.tracker</name> <value>localhost:9001</value> </property> </configuration> 下面我们同样需要配置hadoop_home,同样是打开 vim /etc/profile 在里面添加: ...

June 28, 2015 · 1 min · 120 words · Bridge Li

MySQL优化初步

这一段时间看了学长推荐的一本书:《高性能MySQL》,感觉还不错,今天写一篇读书笔记,供自己和需要的人参考。 一、数据库优化简介 数据库优化的目的 ①. 避免出现页面访问错误,主要是数据库连接timeout产生页面5XX错误、由于慢查询造成页面无法加载和由于阻塞造成数据无法提交; ②. 增加数据库的稳定性,很多数据库问题都是由于低效的查询引起的; ③. 优化用户体验,流畅页面的访问速度、良好的网站功能体验 从哪几个方面对数据库优化 所谓一图胜千言,所以我们先看一下,下面这张图: 从这张图上,我们可以清晰的看到,我们优化的重点和代价,另外这几个方面我们分别可以做些什么呢? ①.在SQL及索引层面,首先是我们要写出一些结构良好的SQL和建立有效的索引 ②.数据库表结构,我们应该根据数据库的一些范式,减少冗余,建立一个利于查询的库表结构 ③.系统配置,例如TCP/IP的连接数、文件的打开数等等 ④. 硬件,包括内存、CPU等,IO设备等等 二、SQL语句优化 在SQL优化之前,我们首先肯定是要查询到哪些SQL需要优化,所以下面让我们先打开MySQL的慢查询日志 MySQL慢查日志的开启方式和存储格式 我们先看几个命令: show variables like &#8216;slow_query_log&#8217;; set global slow_query_log=on; set global slow_query_log_file=&#8217;/home/mysql/sql_log/mysql-slow.log&#8217;; set global log_queries_not_using_indexes=on; set global long_query_time=1; 这几条命令相信不用说,大家都能看得懂,需要说明的是最后一条的时间单位是“秒”,本例中意思是说大于“1秒”的都认为是慢查询,当然实际情况下“1秒”很多时候也是太长了,记录下来这些信息之后我们就可以分析和查看这些日志了,分析和查看MySQL的慢查询日志有两个常见的工具,分别是mysqldumpslow和pt-query-digest,第一个是MySQL官方提供的,第二个是一个商业软件,至于他们怎么用,这里就不多说了,找到这些用问题的SQL之后,我们就可以对这些SQL进行优化了,一般有问题的SQL主要是一下这些: ①. 查询次数多且每次查询占用时间长的SQL,通常是pt-query-digest分析的前几个查询; ②. IO大的SQL,注意pt-query-digest分析中的Rows examine项 ③. 未命中索引的SQL,注意pt-query-digest分析中Rows examine和Rows Send的对比 通过explain查询和分析SQL的执行计划 explain返回各列的含义 table: 显示这一行数据是关于那张表的 type: 这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和All possible_keys 显示可能应用在这张表中的索引。如果为空,没有可能的索引。 key: 实际使用的索引 key_len: 使用索引的长度,在不损失精确性的情况下,长度越短越好 ref: 显示索引的哪一列被使用了,如果可能的话,是一个常数 rows: MySQL认为必须检查的用来返回请求数据的行数 extra: 看到Using filesort和Using temporary的时候,查询就需要优化了,Using temporary需要MySQL常见一个临时表来存储结果,这通常发生在不同的列集进行ORDER BY上,而不是GROUP BY上 count()和max()的优化 max函数通常是查询最后一个数据,我们可以对max函数包含的列添加一个索引; count函数是用来计数的,我们只需要了解count(*)和count(id)的差别就好了,count(*)返回的是有多少行,count(id)返回的是id不为null的有多少行,所以这是有差别的 ...

June 14, 2015 · 1 min · 206 words · Bridge Li

Java中常见的日期处理方法

在实际工作中日期是我们非常用的一种类型,其原因相信不用我说了大家都明白,今天就写一篇文章记录一下自己在工作中常用的日期处理 日期格式化 日期格式化,在工作中,很多时候我们拿到的日期的格式不是我们想要的,那么就需要我们把它格式化成我们想要的,那么怎么做呢? 举个例子:我们想格式化当日时间为:2015-05-31 22:05:30,就可以这么做: package cn.bridgeli.demo.date; import java.text.SimpleDateFormat; import java.util.Date; public class DateTest { public void testSimpleDateFormat() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String now = simpleDateFormat.format(date); System.out.println(now); } } 那么大家就可以根据自己的需要,去格式化大家想要的格式了,需要注意的一点是:我这里的“HH”是大写的表明是24时计时法,如果写成小写的“hh”,就变成12时计时法了。 获取当前的月份 我想有些人可能已经想到了,把上面的改成 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM"); 这个是能达到目的,但不够优雅,也不是官方所推荐的,也比较难以维护,下面我们看看标准的实现 package cn.bridgeli.demo.date; import java.util.Calendar; import java.util.Date; public class DateTest { public void testSimpleDateFormat() { Calendar calendar = Calendar.getInstance(); System.out.println(calendar.get(Calendar.MONTH)); } } 其实在JDK的早期版本中,Date类型是直接有genMonth()方法的,但由于Date类型比较简单,功能有限,所以后来JDK就把这个方法给废弃了(但为了兼容,目前还是可以用的),然后创造了Calendar,所以我们可以利用Calendar获取年份、月份、日期等等,具体可以查询JDK的API 获得当前周几 这个其实和上一个很类似,具体不多说了,大家查JDK的API中的Calendar就可以看到了 ...

May 31, 2015 · 2 min · 249 words · Bridge Li

持续集成(C I)工具Jenkins入门

这几天研究了一下持续集成(CI)工具Jenkins,感觉很强大,入门也很简单,今天就写一个入门的小例子,对于一般性的小项目足够用了,如果大家用到了更复杂的相信学会这篇文章之后,也一定能自己搞定了 安装 Jenkins是Java开发的,我们只需要到他的官网:http://jenkins-ci.org下载一个war包,扔到servlet容器(例如:tomcat)中,启动就可以了,和普通的war启动没什么差别,如果你还不会,那么你需要补J2EE的基础了。 安装插件 启动完成之后,是这样的, Jenkins自己已经帮我们安装了好多很好用的插件,但有些还是要我们自己装,例如:Git Client Plugin、Git Plugin,要安装这些,我们只需要点击左边的“系统管理” –> 管理插件 –> 可选插件,找到这两个插件装上就好了,装好插件下一步就是配置了 配置 配置,同样“系统管理” –> 系统设置,下面开始配置: ①. Maven Configuration配置 就是maven的settings文件的位置 ②. JDK配置 新增JDK,然后大家一看就应该懂了,尽量不要自动安装 ③. Git 也一样,就是Git的路径,需要注意的是:Git的路径一直要到bin下面的exe文件(Linux还没用过,所以不清楚,但我相信大家都懂得了) ④. Maven配置 这个和JDK的配置是一样的 ⑤. Maven项目配置 Maven仓库的地址,我选的是第三个Local to the workspace,其实无所谓 ⑥. Jenkins URL 就改成127.0.0.1吧,或者其他合适的,邮件地址就写自己的啦 ⑦. Git plugin 这个相信不用多说了,Git我们都配过 这些目前是必须的配置,其他的大家就根据需要或者自己的理解,要么不配也行 需要说明的是,我没有配ant,用到了可以自己配一下,一样的,配置完成后选择“保存”就好了 新建一个任务 这个大家都能找到在哪,然后进入到 填入Item名称,选择构建一个maven项目,点击“OK”到下一页,需要说明的: ①. 源码管理,这个也是最重要的,我选的是Git,这也是在一开始我安装那两个插件的原因,如果不安装那两个插件,是不会有Git这个选项的,然后键入要构建的项目的URL,点击“Add”,添加用户名和密码,切记一定要这么选择 其中Username是默认的,可以改,但Kind和Private Key强烈建议和我选的一样,否则可能会报代码拉不下来的错误,反正我是被这个错浪费了一天,然后这么选之后就对了,所以建议大家这么干,当然也可以自己选择其他的,大家可以试试。 ②. 构建触发器 Poll SCM、Build periodically这个是我们配置定时任务,也就是定时自动构建项目的,他们的区别: Poll SCM:定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来,然后执行构建动作。我的配置如下: \*/5 \* \* \* * (每5分钟检查一次源码变化) Build periodically:周期进行项目构建(它不care源码是否发生变化),我的配置如下: ...

May 24, 2015 · 1 min · 130 words · Bridge Li