另类加水印——根据明暗度分别加不同的水印

package image;       import java.awt.AlphaComposite;    import java.awt.Color;    import java.awt.Font;    import java.awt.Graphics;    import java.awt.Graphics2D;    import java.awt.Image;    import java.awt.image.BufferedImage;    import java.awt.image.ColorModel;    import java.awt.image.PixelGrabber;    import java.io.File;    import java.io.FileOutputStream;       import javax.imageio.ImageIO;       import com.sun.image.codec.jpeg.JPEGCodec;    import com.sun.image.codec.jpeg.JPEGImageEncoder;       public class WaterMark {           /**        * 获取指定矩形中的像素的矩阵        *         * @param imageSrc        * @param startX        * @param startY        * @param w        * @param h        * @return   … Continue reading "另类加水印——根据明暗度分别加不同的水印"

JavaRebel 1.2发布,充分支持Spring

JavaRebel是一个JVM插件(-javaagent),能够即时重载java class更改,因此不需要重新部署一个应用或者重启容器,节约开发者时间。它是一个Java EE和Java 独立应用的常用解决方案。最新的稳定版本JavaRebel代码加载包含一个Spring的插件,能重新加载Spring配置快速的促进生产力的发展,甚至更多。查看Screencast ,下载JavaRebel 和插件 。 这个稳定的JavaRebel主要致力于两个主题:稳定和可扩展性。下面是它与1.1版本的区别: core:增强了core的JavaRebel现在可以处理任何复杂的代码或容器。 SDK:您可以对应用程序和库的任何部分进行增值,无论您身在何处或怎么设置。SDk 为开放源代码。 JavaRebel插件:现在支持自定义的classloaders更容易,容器和框架只需登记一个小插件即可。 Eauinox OSGi容器,现在支持IBM WebSphere 和 Atlassian 混合插件。 查看完整的更新列表 或现在就开始下载JavaRebel。 我们已经准备了一个Screencast来说明Spring插件的功能。查看该插件的安装手册 ,了解更多的详情或现在就下载 。

一个体现Java接口及工厂模式优点的例子

     随着模式概念的普及,了解模式和使用模式的程序员越来越多,很多人在学习模式的时候,都会有这样一种疑惑:“有必要搞得这么复杂吗?”。的确,因为教程的例子过于简单化(这样方便读者学习),或者是作者选例子的时候并没有很好体现所讲模式的优点,很多情况下如果仅就其例子的问题来说,用模式是太复杂了。因此才导致这样的误解:“模式就是把简单的问题复杂化吗?”。当然不是,随着你开发实践的不断丰富,你终会发现模式强大威力,而且模式也并非贵族化的编程方式,它就是一些经过提炼了的解决问题的方法技巧。         通过学习模式,程序员开始告别过去准直线式的代码方式,模式开扩了我们的视野,强化了我们面向对象编程的思维方式。然而现在又出现了另一个普遍的问题,盲目应用模式。模式是问题的解决方案,先有问题才有模式,模式是依附于所要解决的问题的而生的。必须了解模式在很多情况下是以提高代码的复杂度为代价来增强灵活性、可复用性。如果在自已的代码中使用某一模式仅只提高了代码的复杂度,而其它方面收效甚微,或者某部份代码根本就不存在灵活性及高复用性的需求,那么我们就没有必要为使用模式而放弃更直观简单的代码写法。         一流的高手90%精力关注问题的解决方案,因为找到了好的解决方案,再写起代码会很轻松代码也简洁流畅,看这样的代码是一种享受和提高;二流的熟手90%精力关注代码实现,因为问题的解决方案并非最佳,实现的代码也会比较复杂;三流菜鸟记流水帐,90%精力在敲键盘,常常做了大半才发现行不通,回过头来再用90%的时间敲键盘,根本不会用到任何模式,写出来的代码的只有他自已才能看懂。做出来的软件也是支离破碎,做一丁点改动都要大费周折,而且你还不知道改动后会产生什么问题,大有住危房里的感觉。         在这里还是举一个滥用模式的例子吧。我曾参与过一个大集团公司OA系统的第二期开发,开发沿用原有代码架构并增加新的功能模块。文档很少我读原代码时就被它程序里的代码转来转去搞得头大如斗,最后读懂了:原代码架构总体采用工厂模式,而且是最复杂的抽象工厂模式。它把所有模块类都通过工厂生成还工厂套工厂,并且每一个模块类都有一个接口,每个接口也只有一个模块现实类,因为涉及权限控制还用了代理(proxy)模式。 读懂代码后我开始嵌入代码,发现每新增一个类,都要到六个Java文件中去增加相应代码,而在类中每增加一个方法,也要到它的接口等四个Java文件中去增加相应代码。天呀!!!记得当时我的小姆指常会不听使唤,就是因为频繁的使用Ctrl+C 、Ctrl+V,小姆指按着Ctrl键给累的。整个项目组苦不堪言,真烦透了。项目结束后我回顾发现:代理模式用得还对(现在针对权限这类横向控制有AOP编程这种新的解决办法了)但工厂模式在这里根本就是画蛇添足,不仅没有解决什么问题,反而增加代码复杂度和耦合性,降低了开发效率连维护难度都提高了。而且那种每个类简单的加一个接口的方式,更是没有道理,这让我很想说周星驰说过的一句话:“球~~~不是这么踢~~~~的,接口~~~不是这么用~~~的”。言归正传,我们先来看这样一个常见问题:某系统需要支持多种类型的数据库。用过Oracle、MSSQL等数据库的人都知道,它们的SQL编写方式都各有些不同。比如说Oracle的唯一标识自动+1字段用的是序列,MSSQL改一下字段属性就成了,还有各种各自特有的SQL用法。为了支持多数据库,难道我们要开发多套系统?当然NO。请看下面的解决方案。         即然数据库存在多种,我们可以将系统中所有对数据库的操作抽象出来,写成一个个方法组合到一个类中,有几种数据库我们就写几个这样的类。具体设计类图如下:     简要说明: OracleDataOperate、SqlserverDataOperate、MysqlDataOperate,分别代表Oracle、Sqlserver、Mysql这三种数据库的操作类。继承自AbstractDataOperate AbstractDataOperate是一个抽象类,包含了那些不同种类数据库都是一样代码的操作方法。继承自DataOperate DataOperate是上面说的数据操作类的统一接口,只有两个方法:取得一条记录、插入一条记录。 DataOperateFactory是一个工厂方法,统一用它的方法来得到数据库操作类的实例。 SampleClass是我们系统的某个功能模块的类。 People是一个实体类,代表一条记录。三个字段 oid唯一标识符、name姓名、date生日。   详细说明: 1、所有系统功能模块类只认DataOperat这个接口还不必管具体的实现类是OracleDataOperate还SqlserverDataOperate。DataOperate源代码如下: publicinterface DataOperate {     //根据记录的唯一标识取出一条记录     People getPeople(String oid);     //插入一条记录     boolean insertPeople(People people); }   2、AbstractDataOperate、OracleDataOperate、SqlserverDataOperate、MysqlDataOperate都是继承DataOperate接口的,没什么好说的,省略。   3、DataOperateFactory。我们看看工厂方法怎么写的。 publicclass DataOperateFactory {     publicstaticfinalint ORACLE = 0; … Continue reading "一个体现Java接口及工厂模式优点的例子"

使用JRockit Mission Control进行性能分析和调优

Mission Control是BEA JRockit JVM自带的一组以极低的开销来监控、管理和分析生产环境中的应用程序的工具。它包括三个独立的应用程序:内存泄漏监测器(Memory Leak Detector)、JVM运行时分析器(Runtime Analyzer)和管理控制台(Management Console)。BEA从JRockit R26版本就开始捆绑这个工具套件,目前最新的版本是3.0。最近我们使用其中的Runtime Analyzer对国内某著名行业解决方案进行性分析和调优。   JRockit Runtime Analyzer(JRA)是一个JVM分析器,是一个随需应变的“动态记录器”。它记录了Java应用程序和JVM在一段预定的时间内的详细记录。然后通过JRA应用程序对记录下来的文件进行离线分析。所记录的数据包括对方法的调用跟踪、错误的同步、锁定的分析,还有垃圾收集统计信息,优化决策以及对象统计信息和其他重要的应用程序/JVM行为。它的目的是让JRockit开发人员能够找到良好的方法来基于现实应用程序优化JVM,对于帮助客户在生产和开发环境中解决问题十分有用。   2.性能数据分析和调优   在本次项目中,操作|A和操作B的百人并发脚本执行完成的时间接近两分钟,因此我们使用JRA进行了2分钟(120秒)的记录。在GC常规信息中,我们发现在短短两分钟时间内,垃圾收集的总数高达365次,而由此造成的暂停时间有42.5秒之多。也就是说35%的执行时间是在做垃圾收集。   因为最大堆尺寸已经设置成1024M,对于32位操作系统上的Java应用已经是足够大了(在IA32构架下,由于操作系统给每个进程的最大内存寻址空间为1.8G,因此最大堆尺寸不能超过1.8G),因此堆的大小并不是造成频繁垃圾收集的原因。那么在高并发度的场景下,可能的影响因素很可能是Nursery大小。   Nursery 也称为新代,是指运行分代式垃圾收集器时,在堆中分配 新对象 的可用块区域。当 Nursery 变满时,会在新垃圾收集中单独对其进行垃圾收集。Nursery 大小决定了新收集的频率和持续时间。较大 Nursery 会降低收集的频率,但是会稍微增加每个新收集的持续时间。 Nursery 之所以具有价值,是因为 Java 应用程序中的大多数对象都是在新代中夭亡的。与收集整个堆相比,应首选从新空间中收集垃圾,因为该收集过程的开销更低,而且在触发收集时,新空间中的大多数对象均已死亡。在新收集过程中,JVM 首先确定 Nursery 中的哪些对象是活动的,此后将它们提升到旧空间,并释放 Nursery,供分配新的小对象使用。   Nursery的默认缺省值是10M/CPU,对于我们Clovertown服务器来说,只有20M。由于出现频繁收集的情况,那么我们推断是由于Nursery的默认值太低的原因。一方面在高并发用户的场景下,肯定是有大量的新对象产生,那么Nursery的空闲空间很容易就被耗尽。因此Nursery发生垃圾收集频率就会比较高。另一方面更短的垃圾收集间隔会使得新对象在Nursery的存活率提高因为很多新对象可能还没来得及使用完毕就已经发生垃圾收集。这样更多的对象会被提升到旧代,使得旧代的对象也会急剧增加,从而使得旧代发生垃圾收集的频率也增加。   因为JRockit JVM可以使用-Xns:<size>来设置Nursery的尺寸,我们要在保证垃圾回收停顿时间(garbage collection-pause)尽可能短的同时,尽量加大Nursery的尺寸,这在创建了大量的临时对象时尤其重要。推荐值是最大堆尺寸的10%,因此我们在JRockit的运行时参数上添加了 –Xns100m。再次运行脚本后,JRA收集的信息显示GC暂停时间骤降到15.3s,次数也有所减少,降到296:   Nursery大小 20M(默认值) 100M GC暂停时间 42.5s 15.3s 垃圾收集的总数 365 296 … Continue reading "使用JRockit Mission Control进行性能分析和调优"

resin clustering

本文主要讲述resin的clustering,简单明了。由于条件限制,只使用一台服务器,运行多个resin来实现clustering,如果多台服务器,只要修改相应的ip地下就可以了。   步骤1: 配置好resin.conf,至少可以把web应用运行起来。   步骤2: 执行:cp resin.conf resin-web.conf   resin.conf作为clustering的配置文件; resin-web.conf为作web-tier的配置文件;   修改resin.conf 把app-tier中的<http address=”*” port=”80″/> 修改为       <!–http address=”*” port=”80″/–>   在<!– define the servers in the cluster –>下面增加servers(ip和端口可以自行修改)  <server id=”a” address=”192.168.1.65″ port=”6800″/> <server id=”b” address=”192.168.1.64″ port=”6801″/>   修改resin-web.conf 在<!– define the servers in the cluster –>下面增加servers(ip和端口可以自行修改)  <server id=”a” address=”192.168.1.65″ port=”6800″/> <server id=”b” address=”192.168.1.64″ port=”6801″/>   把web-tier中的 … Continue reading "resin clustering"

使用JRockit作为Eclipse的Java VM

早些天写了一篇关于调整Eclipse启动的blog,目的还是希望提升Eclipse(包括启动时)的总体性能。 今天,尝试了一下使用BEA JRockit来作为Eclipse的JVM,同时使用JRockit来编译所有的项目。 安装JRockit: 1. 从BEA下载最新的JRockit。 JRockit据说是Wintel平台下最快的Java编译器(以前还有IBM的JDK和Jike,IBM JDK现在是WebSphere的一部分,而最先支持增量编译的Jike已经贡献给Eclipse了,BEA也将会把JRockit贡献给Eclipse。 天下归一啊)。 BEA的JRockit主页在这里,从这里下载最新的JRockit 5.0(我下载的是R26.4.0),大约75MB。 2. 安装JRockit非常容易,不停的”Next”即可。 安装完以后,可以把JAVA_HOME设置为JRockit(可选项)。 配置Eclipse: 1. Eclipse启动参数。 其实就是像前一篇所说的那样,在Eclipse启动参数里面修改-vm的值,使用JRockit来启动Eclipse。比如我修改为: C:\Java\eclipse\eclipse.exe -vm C:\java\jrockit-R26.4.0-jdk1.5.0_06\ bin\javaw.exe -vmargs -Xms256m -Xmx512m -XXsetgc:singleparpar -XXcompactratio:1 2. 在Eclipse里面,安装JRockit,即在Installed JRE中添加JRockit,并设置为默认。 这样,就可以用JRockit来编译项目了。 至于性能: Eclipse(我的Eclipse是v3.2 Callisto,含所有的插件,以及Crystal Report, SWT Designer, PowerDesigner,Mylar, FindBugs等插件)启动的时候,比使用Sun JDK 1.5要快一些(但不是快很多很多,毕竟Sun JDK 1.5的性能已经提升了),大约能有10-15%的改进吧。 我的工程一共有95个plug-in项目和1个Web项目。 之后,我可能会尝试一下把JRockit用到Glassfish的服务器上,看看效果如何。 【参考文章】Running BEA Workshop/Eclipse with JRockit 5.0 Technorati : Eclipse, JRockit … Continue reading "使用JRockit作为Eclipse的Java VM"

Lucene Query Parser

Lucene Query Parser 翻译这篇文章的初衷是希望能更系统的理解Lucene的用法,同时试试自己的翻译水平:) 原文:http://jakarta.apache.org/lucene/docs/queryparsersyntax.html 概述 虽然Lucene提供的API允许你创建你自己的Query(查询语句),但它同时也通过Query Parser(查询分析器)提供了丰富的查询语言。 这个页面提供的是Lucene的Query Parser的语法介绍:一个可通过用JavaCC把一个字符串解释成为Lucene的查询语句的规则。 在选择使用被提供的Query Parser前,请考虑一下几点: 1、如果你是通过编写程序生成一个查询语句,然后通过Query Parser分析,那么你需要认真的考虑是否该直接利用Query的API构造你的查询。换句话说,Query Parser是为那些人工输入的文本所设计的,而不是为了程序生成的文本。 2、未分词的字段最好直接加到Query中,而不要通过Query Parser。如果一个字段的值是由程序生成的,那么需要为这个字段生成一个Query Clause(查询子句)。Query Parser所用的Analyzer是为转换人工输入的文本为分词的。而程序生成的值,比如日期、关键字等,一般都由程序直接生成(?)。 3、在一个查询表单里,通常是文本的字段应该使用Query Parser。所有其他的,比如日期范围、关键字等等,最好是通过Query API直接加入到Query中。一个有有限个值的字段,比如通过下拉表单定义的那些,不应该被加到查询字串中(后面会分析到),而应该被添加为一个TermQuery子句。 分词 一个查询语句是有分词和操作符组成的。这里有两种类型的:单个的分词和短语。 一个单一分词就是一个简单的单词,比如”test”或”hello”。 一个短语就是一组被双引号包括的单词,比如”hello dolly”。 多个分词可以用布尔操作符组合起来形成一个更复杂的查询语句(下面会详细介绍)。 注意:用于建立索引的分析器(Analyzer)将被用于解释查询语句中的分词和短语。因此,合理的选择一个分析器是很重要的,当然这不会影响你在查询语句中使用的分词。 字段 Lucene支持字段数据。当执行一个搜索时,你可以指定一个字段,或者使用默认的字段。字段的名字和默认的字段是取决于实现细节的。 你可以搜索任何字段,做法是输入字段名称,结尾跟上一个冒号 “:” , 然后输入你想查找的分词。 举个例子,让我们假设Lucene的索引包含两个字段,标题和正文,正文是默认字段。如果你想标题为 “The Right Way” 并且正文包含文本 “don’t go this way”的记录的话,你可以输入:   title:”The Right Way” AND text:go  或者   title:”Do it right” … Continue reading "Lucene Query Parser"

Google Guice Example

最近在研究Google 的 Guice,感觉用起来挺简单的,入门应该比Spring要容易的多,这也许是因为Guice刚刚出世,很功能还没有完善吧,但据说Google内部已经在用了,我想再过一段时间取Spring而代之也不是没有可能,至少也能跟Spring平分天下吧。 下面是一个简单的小实例 1.业务逻辑接口 package com.hawkunion.guice; /** * * @author 杜庆明 */ public interface Work {      public void sayHello(String userName); } 2.实现接口的业务逻辑 package com.hawkunion.guice; /** * * @author 杜庆明 */ public class WorkImpl implements Work{          public void sayHello(String userName) {          System.out.println(“Hello! 欢迎你:”+userName);      }     } 3.要用到业务逻辑的类 package com.hawkunion.guice; import … Continue reading "Google Guice Example"

linux下crontab时间的格式说明

cron 配置计划任务的书写格式 说明:第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;第七段应该定义的是:执行的命令和参数。 注:其中用户名可是省略,用户名定义的是程序用哪个用户来执行,比如mysql服务器,我们可以定义成以mysql用户来启动、停止、重新 启动,这时要写上用户名;不过对于cron来说意义不是太大,因为每个用户都有自己的cron配置文件。有些程序的启动必须用到root用户,这时我们就 可以修改root用户的cron配置文件就行了。在每个用户的配置文件中,不必指定用户名。 我们可以把计划任务写在全局性配置文件中,如果您想把一个计划放入全局性配置文件中,就得改发行版所对应的cron全局配置文件,比如Fedora 5的全局性配置文件是/etc/crontab文件; 每个用户也能定义自己的cron配置文件,用crontab -e 命令来定义; 举一例:让机器在每天8点30分重新启动; 关于时间格式中有7个字段。我们可以直接更改或者添加,当然这是系统任务调用。举个例子,比如我在每天的早上8点30分重新启动机器,就可以在/etc/crontab中加入下面的两句,第一句就是注释了。以#号开始,后面写一个自己能知道这是什么任务的备注; # reboot OS30 8 * * * root /sbin/reboot 第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;第七段应该定义的是:执行的命令和参数。 对比上面的例子就知道,30是不是分钟??8是不是小时?如果有*代表的地方,表示全部,也就是说,每个月,每天,每星期都要执行。root 表示用root用户执行,命令是/sbin/reboot ,也就是说,系统在每天 8点30分重新启动; 我们可以把每天8点30分重新启动的计划任务写入cron全局性配置文件中,也可以定义在root用户自己的cron配置文件中。如果定义在 root自己的配置文件,请用root身份来执行 crontab -e 来修改配置文件;crontab -e 进入修改配置文件的过程,其实和vi的用法一样.

64位linux编译软件注意事项

  64位的linux编译软件时最好指定/usr/lib64目录以提高系统性能   ./configure LDFLAGS=-L/usr/lib64 An attempt to link the coNCePTuaL run-time library on one x86-64 Linux platform aborted with the following error:      /usr/lib/libpopt.so: could not read symbols: File in wrong formatAn attempt on another x86-64 Linux platform aborted with a similar error:      /usr/lib/libpopt.so: could not read symbols: Invalid operationThe problem on both platforms turned … Continue reading "64位linux编译软件注意事项"