Read Sean

Read me, read Sean.
posts - 508, comments - 655, trackbacks - 9, articles - 4

 

好了,来看我在Common Lang中最后要讲的一个包:org.apache.commons.lang.time。这个包里面包含了如下5个类:

 

DateFormatUtils – 提供格式化日期和时间的功能及相关常量;

DateUtils – CalendarDate的基础上提供更方便的访问;

DurationFormatUtils – 提供格式化时间跨度的功能及相关常量;

FastDateFormat – java.text.SimpleDateFormat提供一个的线程安全的替代类;

StopWatch – 是一个方便的计时器。

 

我们还是在一个例子中来看上述各个类的用法吧:

 

package sean.study.jakarta.commons.lang;

 

import java.util.Calendar;

import java.util.Date;

 

import org.apache.commons.lang.StringUtils;

import org.apache.commons.lang.time.DateFormatUtils;

import org.apache.commons.lang.time.DateUtils;

import org.apache.commons.lang.time.FastDateFormat;

import org.apache.commons.lang.time.StopWatch;

 

public class DateTimeUsage {

 

    public static void main(String[] args) {

        demoDateUtils();

        demoStopWatch();

    }

   

    public static void demoDateUtils() {

        System.out.println(StringUtils.center(" demoDateUtils ", 30, "="));

        Date date = new Date();

        String isoDateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(date);

        String isoTime = DateFormatUtils.ISO_TIME_NO_T_FORMAT.format(date);

        FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM");

        String customDateTime = fdf.format(date);

        System.out.println("ISO_DATETIME_FORMAT: " + isoDateTime);

        System.out.println("ISO_TIME_NO_T_FORMAT: " + isoTime);

        System.out.println("Custom FastDateFormat: " + customDateTime);

        System.out.println("Default format: " + date);

        System.out.println("Round HOUR: " + DateUtils.round(date, Calendar.HOUR));

        System.out.println("Truncate HOUR: " + DateUtils.truncate(date, Calendar.HOUR));

        System.out.println();

    }

   

    public static void demoStopWatch() {

        System.out.println(StringUtils.center(" demoStopWatch ", 30, "="));

        StopWatch sw = new StopWatch();

        sw.start();

        operationA();

        sw.stop();

        System.out.println("operationA used " + sw.getTime() + " milliseconds.");

        System.out.println();

    }

   

    public static void operationA() {

        try {

            Thread.sleep(999);

        }

        catch (InterruptedException e) {

            // do nothing

        }

    }

 

}

 

以下是运行结果:

 

======= demoDateUtils ========

ISO_DATETIME_FORMAT: 2005-08-01T12:41:51

ISO_TIME_NO_T_FORMAT: 12:41:51

Custom FastDateFormat: 2005-08

Default format: Mon Aug 01 12:41:51 CST 2005

Round HOUR: Mon Aug 01 13:00:00 CST 2005

Truncate HOUR: Mon Aug 01 12:00:00 CST 2005

 

======= demoStopWatch ========

operationA used 1000 milliseconds.

 

具体的调用细节和完整的API请参阅Commons LangJavadoc

 

 

posted @ 2005-08-01 13:19 laogao 阅读(7327) | 评论 (11)编辑 收藏

 

Jakarta Commons中,专门处理数学计算的类分别可以在两个地方找到:一是Commons Langorg.apache.commons.lang.math包中,二是在Commons Math这个单独的子项目中。由于后者主要是处理复数、矩阵等,相对使用比较少,在我的笔记中就只简单讲讲Commons Lang中的math包。对后者感兴趣的可以看看

http://jakarta.apache.org/commons/math/

 

org.apache.commons.lang.math包中共有10个类,这些类可以归纳成四组:

1- 处理分数的Fraction类;

2- 处理数值的NumberUtils类;

3- 处理数值范围的RangeNumberRangeIntRangeLongRangeFloatRangeDoubleRange类;

4- 处理随机数的JVMRandomRandomUtils类。

 

下面我举个例子分别说明上述四组的使用方法:

 

package sean.study.jakarta.commons.lang;

 

import org.apache.commons.lang.ArrayUtils;

import org.apache.commons.lang.BooleanUtils;

import org.apache.commons.lang.StringUtils;

import org.apache.commons.lang.math.DoubleRange;

import org.apache.commons.lang.math.Fraction;

import org.apache.commons.lang.math.NumberUtils;

import org.apache.commons.lang.math.RandomUtils;

import org.apache.commons.lang.math.Range;

 

public class LangMathUsage {

 

    public static void main(String[] args) {

        demoFraction();

        demoNumberUtils();

        demoNumberRange();

        demoRandomUtils();

    }

 

    public static void demoFraction() {

        System.out.println(StringUtils.center(" demoFraction ", 30, "="));

        Fraction myFraction = Fraction.getFraction(144, 90);

        // Fraction myFraction = Fraction.getFraction("1 54/90");

        System.out.println("144/90 as fraction: " + myFraction);

        System.out.println("144/90 to proper: " + myFraction.toProperString());

        System.out.println("144/90 as double: " + myFraction.doubleValue());

        System.out.println("144/90 reduced: " + myFraction.reduce());

        System.out.println("144/90 reduced proper: "

                + myFraction.reduce().toProperString());

        System.out.println();

    }

 

    public static void demoNumberUtils() {

        System.out.println(StringUtils.center(" demoNumberUtils ", 30, "="));

        System.out.println("Is 0x3F a number? "

                + StringUtils.capitalize(BooleanUtils.toStringYesNo(NumberUtils

                        .isNumber("0x3F"))) + ".");

        double[] array = { 1.0, 3.4, 0.8, 7.1, 4.6 };

        double max = NumberUtils.max(array);

        double min = NumberUtils.min(array);

        String arrayStr = ArrayUtils.toString(array);

        System.out.println("Max of " + arrayStr + " is: " + max);

        System.out.println("Min of " + arrayStr + " is: " + min);

        System.out.println();

    }

 

    public static void demoNumberRange() {

        System.out.println(StringUtils.center(" demoNumberRange ", 30, "="));

        Range normalScoreRange = new DoubleRange(90, 120);

        double score1 = 102.5;

        double score2 = 79.9;

        System.out.println("Normal score range is: " + normalScoreRange);

        System.out.println("Is "

                + score1

                + " a normal score? "

                + StringUtils

                        .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                .containsDouble(score1))) + ".");

        System.out.println("Is "

                + score2

                + " a normal score? "

                + StringUtils

                        .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                .containsDouble(score2))) + ".");

        System.out.println();

    }

 

    public static void demoRandomUtils() {

        System.out.println(StringUtils.center(" demoRandomUtils ", 30, "="));

        for (int i = 0; i < 5; i++) {

            System.out.println(RandomUtils.nextInt(100));

        }

        System.out.println();

    }

 

}

 

以下是运行结果:

 

======== demoFraction ========

144/90 as fraction: 144/90

144/90 to proper: 1 54/90

144/90 as double: 1.6

144/90 reduced: 8/5

144/90 reduced proper: 1 3/5

 

====== demoNumberUtils =======

Is 0x3F a number? Yes.

Max of {1.0,3.4,0.8,7.1,4.6} is: 7.1

Min of {1.0,3.4,0.8,7.1,4.6} is: 0.8

 

====== demoNumberRange =======

Normal score range is: Range[90.0,120.0]

Is 102.5 a normal score? Yes.

Is 79.9 a normal score? No.

 

====== demoRandomUtils =======

75

63

40

21

92

 

以上就是Commons Langmath包通常的用法。提一下NumberUtils.inNumber(String)方法,它会正确判断出给定的字符串是否是合法的数值,而我在前面的笔记中提到的StringUtils.isNumeric(String)只能判断一个字符串是否是由纯数字字符组成。Commons Langmath包的各个类都还有很多实用的方法,远不止我在例子中用到的这些,如果你感兴趣,参照一下Commons LangJavadoc吧。

 

 

posted @ 2005-08-01 13:18 laogao 阅读(3955) | 评论 (3)编辑 收藏

 

在前面的专题文章中,我们一起过了一遍org.apache.commons.lang包,接下来我们继续看org.apache.commons.lang.builder这个包。在这里面我们可以找到7个类,用于帮助我们实现Java对象的一些基础的共有方法。这7个类分别是:

 

CompareToBuilder – 用于辅助实现Comparable.compareTo(Object)方法;

EqualsBuilder – 用于辅助实现Object.equals()方法;

HashCodeBuilder – 用于辅助实现Object.hashCode()方法;

ToStringBuilder – 用于辅助实现Object.toString()方法;

ReflectionToStringBuilder – 使用反射机制辅助实现Object.toString()方法;

ToStringStyle – 辅助ToStringBuilder控制输出格式;

StandardToStringStyle – 辅助ToStringBuilder控制标准格式。

 

我们知道,在实际应用中,其实经常需要在运行过程中判定对象的知否相等、比较、取hash、和获取对象基本信息(一般是产生log日志)。然而实现这些compareToequalshashCodetoString其实并非那么直截了当,甚至稍有不注意就可能造成难以追踪的bug,而且这些方法手工维护的话,比较繁琐,也容易出错。于是Commons Langbuilder这个包中提供了上述辅助类,为我们简化这些方法的实现和维护。

 

来看一个例子:

 

package sean.study.jakarta.commons.lang;

 

import java.util.Date;

 

import org.apache.commons.lang.builder.CompareToBuilder;

import org.apache.commons.lang.builder.EqualsBuilder;

import org.apache.commons.lang.builder.HashCodeBuilder;

import org.apache.commons.lang.builder.ToStringBuilder;

import org.apache.commons.lang.builder.ToStringStyle;

 

public class BuilderUsage {

 

    public static void main(String[] args) {

       

        Staff staff1 = new Staff(123, "John Smith", new Date());

        Staff staff2 = new Staff(456, "Jane Smith", new Date());

       

        System.out.println("staff1's info: " + staff1);

        System.out.println("staff2's info: " + staff2);

        System.out.println("staff1's hash code: " + staff1.hashCode());

        System.out.println("staff2's hash code: " + staff2.hashCode());

        System.out.println("staff1 equals staff2? " + staff1.equals(staff2));

 

    }

 

}

 

class Staff implements Comparable {

 

    private long staffId;

    private String staffName;

    private Date dateJoined;

 

    public Staff() {

    }

 

    public Staff(long staffId, String staffName, Date dateJoined) {

        this.staffId = staffId;

        this.staffName = staffName;

        this.dateJoined = dateJoined;

    }

 

    public int compareTo(Object o) {

        int res = -1;

        if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

            Staff s = (Staff) o;

            res = new CompareToBuilder()

                    .append(dateJoined, s.getDateJoined())

                    .append(staffName, s.getStaffName()).toComparison();

        }

        return res;

    }

 

    public boolean equals(Object o) {

        boolean res = false;

        if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

            Staff s = (Staff) o;

            res = new EqualsBuilder()

                    .append(staffId, s.getStaffId())

                    .isEquals();

        }

        return res;

    }

 

    public int hashCode() {

        return new HashCodeBuilder(11, 23).append(staffId).toHashCode();

    }

 

    public String toString() {

        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

                .append("staffId", staffId)

                .append("staffName", staffName)

                .append("dateJoined", dateJoined)

                .toString();

    }

 

    public Date getDateJoined() {

        return dateJoined;

    }

 

    public void setDateJoined(Date dateJoined) {

        this.dateJoined = dateJoined;

    }

 

    public long getStaffId() {

        return staffId;

    }

 

    public void setStaffId(long staffId) {

        this.staffId = staffId;

    }

 

    public String getStaffName() {

        return staffName;

    }

 

    public void setStaffName(String staffName) {

        this.staffName = staffName;

    }

}

 

以下是运行结果:

 

staff1's info: sean.study.jakarta.commons.lang.Staff@190d11[

  staffId=123

  staffName=John Smith

  dateJoined=Sat Jul 30 13:18:45 CST 2005

]

staff2's info: sean.study.jakarta.commons.lang.Staff@1fb8ee3[

  staffId=456

  staffName=Jane Smith

  dateJoined=Sat Jul 30 13:18:45 CST 2005

]

staff1's hash code: 376

staff2's hash code: 709

staff1 equals staff2? false

 

这些builder使用起来都很简单,new一个实例,append需要参与的信息,最后加上toComparisonisEqualstoHashCodetoString这样的结尾即可。相应的,如果你不需要这样级别的控制,也可以使用利用反射机制的版本自动化实现需要的功能,如:

 

    public int compareTo(Object o) {

        return CompareToBuilder.reflectionCompare(this, o);

    }

 

    public boolean equals(Object o) {

        return EqualsBuilder.reflectionEquals(this, o);

    }

 

    public int hashCode() {

        return HashCodeBuilder.reflectionHashCode(this);

    }

 

    public String toString() {

        return ReflectionToStringBuilder.toString(this);

    }

 

尤其当我们在项目中不希望过多的参与到对这些对象方法的维护时,采用Commons提供的利用反射的这些API就成了方便而相对安全的一个方案。

 

 

posted @ 2005-07-30 15:38 laogao 阅读(6067) | 评论 (0)编辑 收藏

 

处理文本对Java应用来说应该算是家常便饭了,在1.4出现之前,Java自身提供的API非常有限,如StringStringTokenizerStringBuffer,操作也比较单一。无非就是查找substring、分解、合并等等。到1.4的出现可以说Java的文字处理上了一个台阶,因为它支持regular expression了。这可是个重量级而方便的东东啊,缺点是太复杂,学习起来有一定难度。相较而言,Jakarta Commons提供的StringUtilsWordUtils至今还维持着那种简洁而强大的美,使用起来也很顺手。来看一个例子:

 

package sean.study.jakarta.commons.lang;

 

import org.apache.commons.lang.StringUtils;

 

public class StringUtilsAndWordUtilsUsage {

 

    public static void main(String[] args) {

       

        // data setup

        String str1 = "";

        String str2 = " ";

        String str3 = "\t";

        String str4 = null;

        String str5 = "123";

        String str6 = "ABCDEFG";

        String str7 = "It feels good to use Jakarta Commons.\r\n";

       

        // check for empty strings

        System.out.println("==============================");

        System.out.println("Is str1 blank? " + StringUtils.isBlank(str1));

        System.out.println("Is str2 blank? " + StringUtils.isBlank(str2));

        System.out.println("Is str3 blank? " + StringUtils.isBlank(str3));

        System.out.println("Is str4 blank? " + StringUtils.isBlank(str4));

       

        // check for numerics

        System.out.println("==============================");

        System.out.println("Is str5 numeric? " + StringUtils.isNumeric(str5));

        System.out.println("Is str6 numeric? " + StringUtils.isNumeric(str6));

       

        // reverse strings / whole words

        System.out.println("==============================");

        System.out.println("str6: " + str6);

        System.out.println("str6 reversed: " + StringUtils.reverse(str6));

        System.out.println("str7: " + str7);

        String str8 = StringUtils.chomp(str7);

        str8 = StringUtils.reverseDelimited(str8, ' ');

        System.out.println("str7 reversed whole words : \r\n" + str8);

       

        // build header (useful to print log messages that are easy to locate)

        System.out.println("==============================");

        System.out.println("print header:");

        String padding = StringUtils.repeat("=", 50);

        String msg = StringUtils.center(" Customised Header ", 50, "%");

        Object[] raw = new Object[]{padding, msg, padding};

        String header = StringUtils.join(raw, "\r\n");

        System.out.println(header);

 

    }

}

 

输出的结果如下:

 

==============================

Is str1 blank? true

Is str2 blank? true

Is str3 blank? true

Is str4 blank? true

==============================

Is str5 numeric? true

Is str6 numeric? false

==============================

str6: ABCDEFG

str6 reversed: GFEDCBA

str7: It feels good to use Jakarta Commons.

 

str7 reversed whole words :

Commons. Jakarta use to good feels It

==============================

print header:

==================================================

%%%%%%%%%%%%%%% Customised Header %%%%%%%%%%%%%%%%

==================================================

 

从代码中我们可以大致了解到这个StringUtils类简单而强大的处理能力,从检查空串(对null的情况处理很得体),到分割子串,到生成格式化的字符串,使用都很简洁,也很直截了当。

 

 

posted @ 2005-07-30 11:37 laogao 阅读(5015) | 评论 (0)编辑 收藏

 

数组是我们经常需要使用到的一种数据结构,但是由于Java本身并没有提供很好的API支持,使得很多操作实际上做起来相当繁琐,以至于我们实际编码中甚至会不惜牺牲性能去使用Collections API,用Collection当然能够很方便的解决我们的问题,但是我们一定要以性能为代价吗?ArrayUtils帮我们解决了处理类似情况的大部分问题。来看一个例子:

 

package sean.study.jakarta.commons.lang;

 

import java.util.Map;

import org.apache.commons.lang.ArrayUtils;

 

public class ArrayUtilsUsage {

 

    public static void main(String[] args) {

 

        // data setup

        int[] intArray1 = { 2, 4, 8, 16 };

        int[][] intArray2 = { { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 } };

        Object[][] notAMap = {

                { "A", new Double(100) },

                { "B", new Double(80) },

                { "C", new Double(60) },

                { "D", new Double(40) },

                { "E", new Double(20) }

        };

 

        // printing arrays

        System.out.println("intArray1: " + ArrayUtils.toString(intArray1));

        System.out.println("intArray2: " + ArrayUtils.toString(intArray2));

        System.out.println("notAMap: " + ArrayUtils.toString(notAMap));

 

        // finding items

        System.out.println("intArray1 contains '8'? "

                + ArrayUtils.contains(intArray1, 8));

        System.out.println("intArray1 index of '8'? "

                + ArrayUtils.indexOf(intArray1, 8));

        System.out.println("intArray1 last index of '8'? "

                + ArrayUtils.lastIndexOf(intArray1, 8));

 

        // cloning and resversing

        int[] intArray3 = ArrayUtils.clone(intArray1);

        System.out.println("intArray3: " + ArrayUtils.toString(intArray3));

        ArrayUtils.reverse(intArray3);

        System.out.println("intArray3 reversed: "

                + ArrayUtils.toString(intArray3));

 

        // primitive to Object array

        Integer[] integerArray1 = ArrayUtils.toObject(intArray1);

        System.out.println("integerArray1: "

                + ArrayUtils.toString(integerArray1));

 

        // build Map from two dimensional array

        Map map = ArrayUtils.toMap(notAMap);

        Double res = (Double) map.get("C");

        System.out.println("get 'C' from map: " + res);

 

    }

 

}

 

以下是运行结果:

 

intArray1: {2,4,8,16}

intArray2: {{1,2},{2,4},{3,8},{4,16}}

notAMap: {{A,100.0},{B,80.0},{C,60.0},{D,40.0},{E,20.0}}

intArray1 contains '8'? true

intArray1 index of '8'? 2

intArray1 last index of '8'? 2

intArray3: {2,4,8,16}

intArray3 reversed: {16,8,4,2}

integerArray1: {2,4,8,16}

get 'C' from map: 60.0

 

这段代码说明了我们可以如何方便的利用ArrayUtils类帮我们完成数组的打印、查找、克隆、倒序、以及值型/对象数组之间的转换等操作。如果想了解更多,请参考Javadoc

 

 

posted @ 2005-07-30 11:36 laogao 阅读(3577) | 评论 (0)编辑 收藏

 

我们首先来看org.apache.commons.lang包,这个包提供了一些有用的包含static方法的Util类。除了6Exception类和2个已经deprecated的数字类之外,commons.lang包共包含了17个实用的类:

 

ArrayUtils – 用于对数组的操作,如添加、查找、删除、子数组、倒序、元素类型转换等;

BitField – 用于操作位元,提供了一些方便而安全的方法;

BooleanUtils – 用于操作和转换boolean或者Boolean及相应的数组;

CharEncoding – 包含了Java环境支持的字符编码,提供是否支持某种编码的判断;

CharRange – 用于设定字符范围并做相应检查;

CharSet – 用于设定一组字符作为范围并做相应检查;

CharSetUtils – 用于操作CharSet

CharUtils – 用于操作char值和Character对象;

ClassUtils – 用于对Java类的操作,不使用反射;

ObjectUtils – 用于操作Java对象,提供null安全的访问和其他一些功能;

RandomStringUtils – 用于生成随机的字符串;

SerializationUtils – 用于处理对象序列化,提供比一般Java序列化更高级的处理能力;

StringEscapeUtils – 用于正确处理转义字符,产生正确的JavaJavaScriptHTMLXMLSQL代码;

StringUtils – 处理String的核心类,提供了相当多的功能;

SystemUtils – java.lang.System基础上提供更方便的访问,如用户路径、Java版本、时区、操作系统等判断;

Validate – 提供验证的操作,有点类似assert断言;

WordUtils – 用于处理单词大小写、换行等。

 

接下来我准备用两个例子来分别说明ArrayUtilsStringUtils的常见用法。

 

 

posted @ 2005-07-30 11:35 laogao 阅读(3735) | 评论 (0)编辑 收藏

 

java.lang这个包的作用类似,Commons Lang这一组API也是提供一些基础的、通用的操作和处理,如自动生成toString()的结果、自动实现hashCode()equals()方法、数组操作、枚举、日期和时间的处理等等。目前这组API的版本是2.1,下载地址如下:

 

http://apache.justdn.org/jakarta/commons/lang/binaries/commons-lang-2.1.zip

http://apache.justdn.org/jakarta/commons/lang/source/commons-lang-2.1-src.zip

 

其中后一个是源代码。

 

这一组API的所有包名都以org.apache.commons.lang开头,共有如下8个包:

 

org.apache.commons.lang

org.apache.commons.lang.builder

org.apache.commons.lang.enum

org.apache.commons.lang.enums

org.apache.commons.lang.exception

org.apache.commons.lang.math

org.apache.commons.lang.mutable

org.apache.commons.lang.time

 

其中的lang.enum已不建议使用,替代它的是紧随其后的lang.enums包。 lang包主要是一些可以高度重用的Util类;lang.builder包包含了一组用于产生每个Java类中都常使用到的toString()hashCode()equals()compareTo()等等方法的构造器;lang.enums包顾名思义用于处理枚举;lang.exception包用于处理Java标准API中的exception,为1.4之前版本提供Nested Exception功能;lang.math包用于处理数字;lang.mutable用于包装值型变量;lang.time包提供处理日期和时间的功能。

 

由于Commons的包和类实在很多,不可能一个一个讲了,在接下来的专题文章中我就只分别过一下langlang.builderlang.mathlang.time这几个包和常见的用法,其他的我们可以在用到时临时参考一下Javadoc。位置就在安装路径的

…\commons-lang-2.1\docs\api\index.html

 

 

posted @ 2005-07-29 18:10 laogao 阅读(4999) | 评论 (0)编辑 收藏

 

Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的。在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta Commons就是这样的一个框架。如果你至少参与了一个中型规模的Java项目,那么我想有超过一大半的机会你都接触和使用到了Jakarta Commons,不管你自己有没有察觉。就我所知,除了Apache Jakarta其他许多开源框架之外,不少所谓的商业框架其实内部有些模块是借用Commons的,甚至有一些完全就是对Commons的类进行了简单的封装。如果真的没有接触过也不要紧,当你看到它时,你自然会被它的简单而强大所吸引。

 

要提高Java编程水平,一条可以走的路就是学习优秀的开源框架。这又要分两个层面:应用层面和源码层面。从应用来说,开源的框架大都可以给你带来生产力和/或代码质量的大幅提升;从源码来说,Java开源框架,尤其是那些大型的优秀的框架,其源码对广大Java爱好者来说都是一笔巨大的财富,你可以从中学到许多课本上学不到的东西:编码习惯、代码组织、注释、文档、如何用Java解决实际问题、特定问题的算法,等等。而这些对于我们的作为软件开发者的实际工作而言,相当有意义。

 

熟悉Jakarta Commons的朋友可能会觉得现在是不是有点过时,因为有很多功能在J2SE 5.0中已经包含了。其实这个问题看你怎么去看,一方面,J2SE 5.0毕竟是刚出现不久的Java版本,实际应用中,很多时候我们需要把代码兼容等级维持在1.3或者1.4,所以很多5.0的功能我们暂时还不能放开手脚去使用;另一方面,鉴于Jakarta在一定程度上反映了一线Java开发人员的实际需求,而目前5.0已经采纳了其中许多特性,我们当然也有理由相信未来的Java版本还会继续参照Jakarta Commons的内容。有这么一套开发源码、免费使用、商业友好的优秀API作为Java自带API的补充,何乐而不为呢?

 

我打算在近期陆续做一些Jakarta Commons的学习笔记放上来,供大家参考。

 

有关Jakarta的最新动态和详细信息,可以参考:

http://jakarta.apache.org/commons/index.html

 

 

posted @ 2005-07-29 12:59 laogao 阅读(4444) | 评论 (0)编辑 收藏


在Artima Developer上看到一则关于Jonathan Schwartz提到的Sun计划将其所有软件免费提供以促进使用Sun技术的社区发展的消息,有兴趣的看看原文吧:

http://www.artima.com/forums/flat.jsp?forum=270&thread=120325

posted @ 2005-07-27 17:48 laogao 阅读(448) | 评论 (1)编辑 收藏


昨天看了Brad Pitt和Angelina Jolie合演的新片:Mr. & Mrs. Smith。说实在的,我原本对这部片子的期待并不高,一方面我猜想这是just another Hollywood movie而已,另一方面女主演Jolie的风格好像并不是我欣赏的风格,尤其是看了电影公司如何用她糟踏了我曾经一度是我的偶像的Lara Croft之后。然而,事实并非我想象的那样糟,甚至完全相反,大大超出我的预期不说,还相当让我喜欢。

说到这里我插一点题外话:国内的进口电影片名翻译总是那么不能忠实原著,如果你想不出一个"信、达、雅"的中文名称,索性就直译一个"信"的就好,总比一个完全不沾边的名字强上百倍。在电影院和路边的宣传海报上出现的中文片名是:"史密斯行动",而在网上我们看到大陆之外的中文国家、地区通常都采用了"史密斯夫妇"这个忠于原文的中文片名。在中国大陆,最典型的一个例子就是"Enemy At the Gates",我们翻译成"决战中的较量",而其它地区都是"兵临城下",一相比较,孰优孰劣立见分晓。

话说回来,这部片子虽然也充满了Hollywood和商业的味道,但是并不让人反感,至少我不觉得排斥。这部片子演员够级别,剧本写得也好,美工和动作特效的处理也很到位,毕竟是2005年的新片大片。总的来说,这部片子够性感、够幽默、够夸张、够暴力美学。

贴一张海报和一张很多地方都引用到的剧照:
mrandmrssmith3.jpg

mrandmrssmith02.jpg

posted @ 2005-07-26 09:37 laogao 阅读(419) | 评论 (0)编辑 收藏


这个是上个月照的了,由于一直没时间整理,就搁在一边。今天心血来潮又翻出来,发现这一张虽然很随意,但是感觉还不错:

Perfume.jpg

全部的光源就是一盏40W的台灯,器材为Canon EOS 5、SIGMA 28-70 EX 2.8,Fujifilm 200负片,2.8光圈,1/30秒,手持拍摄。后期底扫后调整过色阶,分别按黑、白、灰三处取样。

posted @ 2005-07-25 13:20 laogao 阅读(375) | 评论 (0)编辑 收藏

  

J2EE应用中有一些常见的毛病和错误的观念,按照时下流行的说法,叫反模式。稍不注意,我们自己也会犯,所以大概整理一下,一个是备忘,也是供需要的朋友参考:

 

1- EJB不叫J2EE

EJB一直发展到今天的2.1仍然被广为诟病,它提供了很多时候我们并不需要的东西,而且我们在很多情况下一旦选用EJB就没有其他的方式不去使用那些笨重的功能。但是很多所谓范例让我们有一种错觉,好像不用EJB就不是J2EE应用。有一些折中的方案是使用Session Façade模式,Entity Bean采用BMP + 本地接口,然后提供一层无状态的Session Bean,采用远程和本地接口,这样的设计模式,我想,多半是出于无奈。如今,甚至我们经常都能看到不使用EJB的言论,炒得很火的Spring则为这种完全不用EJB开发J2EE项目提供了实际的、强有力的佐证。

 

2- 过度分层

J2EE这个规范肤浅的来看,就是为我们定义了很多“层”,然后还有很多分工明确的“角色”,加上J2EE的蓝本应用程序就分了很多“层”,以至于大家都觉得J2EE的应用就应该是很多层的,其实不然,需要具体情况具体分析。

 

3- 频繁的往返调用

EJB的看似简单造成我们经常忽略可能在使用过程中出现的远程调用,比如有时候为了更新一条记录,每个字段都是远程的去set,大大增加了不必要的开销,于是我们意识到在调用中使用DTO是一个建议遵循的方案。

 

4- 过度使用有状态的Session Bean

一般来讲,一个Session Bean实例,如果它是有状态的,那么它只对某个固定的用户服务,如果是无状态的,则可以满足不同用户的调用。这有点类似(只是有点类似)一个类的静态方法和非静态方法的区别。我们在实际应用中,应该尽量避免使用有状态的Session Bean,除非特别必要。我们可以把状态保留在Session Bean之外,如Web容器的session对象或者我们自定义的类中,而不是完全依赖有状态的Session Bean去帮我们做。

 

5- 过度会话

Web容器的session对象是个好东西,用起来也很方便和直截了当,这造成了我们很多人对它的滥用,什么东西都往里面放。这有两个突出的问题,一个是资源浪费;另一个,万一Web服务器崩溃,那些本来需要持久化的数据就丢失了。我们需要考虑好,哪些数据本可以用request的,哪些数据又是需要持久化到数据库的,等等,不能一味依赖session

 

6- 万能Servlet或者万能JSP

J2EE为我们提供了Web层丰富的技术选择,Servlet或者JSP都只是其中一种,虽然它很强大,但是也不应该由它一个来承担所有MVC三个部分的功能。现实中我们的Struts很好的规范了这个问题:Servlet负责调度,专门的Action负责处理逻辑,而JSP用于用户界面显示。JSPServlet本质上是同一个东西,只是从不同的角度来处理问题,它们各有所长,互为补充。

 

 

posted @ 2005-07-23 17:01 laogao 阅读(3273) | 评论 (0)编辑 收藏


眼看做了一年多的项目总算要上线了,自己也该计划一下项目结束以后要系统学习的东东,粗略地想了一下,应该包括下面这些:

Eclipse (SWT/JFace/PDE/RCP)
Hibernate
JDO
EJB 3.0 (以及Java EE 5 的其他部分)
Spring Framework
JSF
Tapestry
XML
MySQL
PHP
Linux

希望我还不算太贪心。

posted @ 2005-07-23 15:22 laogao 阅读(689) | 评论 (4)编辑 收藏


今天在JDJ上面看到一篇文章,说起一个在Java社区还算是比较新鲜的话题:XML Rich-Client,用XML替代传统的HTML作为服务器端返回给客户端的数据载体,它的基本思想有点类似微软的XAML,在Longhorn (Vista)中将要采用的一种界面配置技术,通过XML文档构建用户界面。

相信大家多少有这种感觉,在服务器端,Java是老大,而客户端则被MS牢牢控制着。.NET出来以后MS更是利用客户端(桌面)的优势向服务器端发起了猛攻,开发.NET应用越来越简单,功能也越来越强大。现在提的这个XML Rich-Client并不需要很深的Java以及OO的知识,只需修改XML即可改变UI,甚至可以是独立于特定语言和平台的(虽然文中没提,但是笔者认为这就像是Web Services一样,理论上是平台中立的),不需要在客户端下载安装。也许这就是未来Java在客户端同MS竞争的一个重要方向?

原文见:http://java.sys-con.com/read/111208_1.htm
关于XAML,可以参考:http://www.ondotnet.com/pub/a/dotnet/2004/01/19/longhorn.html

posted @ 2005-07-23 14:59 laogao 阅读(1176) | 评论 (0)编辑 收藏


经过一段时间试用TM,效果并不理想:

1- 可能是网络原因,TM的断线率同样很高,经常可以看见它在尝试重新登录,或者消息发送失败;
2- 不知道是Windows还是TM处理窗口的方式有问题,经常在你处理其他事务的时候,从你的当前窗口跳转到TM的窗口,导致你所在的窗口失去焦点,这在你用中文输入法时尤其让人不爽;
3- 偶尔TM会与我的金山词霸冲突导致系统死机。

看来要做一款好用而又大众接受的IM即时通讯软件想必不是那么容易的一件事吧。

posted @ 2005-07-13 15:49 laogao 阅读(493) | 评论 (2)编辑 收藏

仅列出标题
共34页: First 上一页 25 26 27 28 29 30 31 32 33 下一页 Last