Eclipse Ganymede (Eclipse 3.4)版本出来很久了,一直没有在这个版本上搞定离线安装subclipse插件,不论是link,还是copy到dropins目录,却无法识别插件,今天在Mac上捣鼓时无意间问了Roy一句,他说3.4版本下的插件似乎不能有site.xml文件,否则好象会被认为在线安装。我随手删除掉site.xml,重新启动eclipse,居然装好了 :D

,

在Java中,有两种初始化块:静态初始化块和非静态初始化块。

静态初始化块:使用static定义,当类装载到系统时执行一次。若在静态初始化块中想初始化变量,那仅能初始化类变量,即static修饰的数据成员。
非静态初始化块:在每个对象生成时都会被执行一次,可以初始化类的实例变量。

非静态初始化块会在构造函数执行时,且在构造函数主体代码执行之前被运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.tiandinet.studyjava;
 
public class TestInitiateBlock {
 
    {
        System.out.println("In non-static initialization block!");
    };
 
    static {
        System.out.println("In static initialization block!");
    };
 
    public TestInitiateBlock() {
        System.out.println("In Constructor1!");
    }
 
    public void show() {
        System.out.println("In show()!");
    }
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        TestInitiateBlock ti = new TestInitiateBlock();
        ti.show();
    }
 
}

运行结果:
In static initialization block!
In non-static initialization block!
In Constructor1!
In show()!

,

虽然之前一直做PHP的开发,但一直没有用过memcache,仅是知道一些简单的原理。今天突然来兴趣,想试一下memcache,和PHP下的调用。

1. 安装memcached (服务器版本1.2.6)

服务器OS是RHEL5(Red Hat Linux Enterprise 5),之前已经装好LAMP环境,这是我们的一台测试服务器,LAMP均位于/opt/lamp下。准备将memcached安装在/opt/cache/memcached目录下。

memcached需要libevent(http://monkey.org/~provos/libevent/)的支持,所以需要先安装libevent,安装目录位于/opt/cache/libevent,下载最新版本的libevent(此例中为1.4.8),解压后进入源代码目录,进行配置和安装。

./configure --prefix=/opt/cache/libevent
 
make
 
make install

接着安装memcached,使用的版本是1.2.6,进入解压后的源代码目录,

./configure --prefix=/opt/cache/memcached --with-libevent=/opt/cache/libevent

–with-libevent指令指定libevent的目录

(阅读全文……)

, , ,

  在原项目中,对文件上传的处理并不是使用Spring的MultipartResolver,而是使用自定义的MultiPartFilter和HttpServletRequestWrapper结合来进行处理。

  MultiPartFilter是一个定义在web.xml中的<filter>,原理是通过判断HttpServletRequest中的contentType是否包含”multipart/form-data”,若代码中包含此字符品,则表明是一个File Upload请求,就使用JakartaMultiPartRequest来对HttpServletRequest对其进行包装。

  其代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MultiPartFilter extends GenericFilterBean {
 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
 
		HttpServletRequest request = (HttpServletRequest) servletRequest;
 
		String content_type = request.getContentType();
		if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
			JakartaMultiPartRequest jakartaMultiPartRequest = new JakartaMultiPartRequest(request,
					getFilterConfig().getInitParameter("saveDir"), Integer.valueOf(
							getFilterConfig().getInitParameter("maxUploadSize")).intValue());
 
			request = jakartaMultiPartRequest;
		}
 
		filterChain.doFilter(request, servletResponse);
    }
 
}

  JakartaMultiPartRequest类继承自HttpServletRequestWrapper,在其构造方法中,我们对Request进行分析,并且保存用户上传的文件,将文件名等信息放到Request的attribute中,从而在后续的代码中可以对上传的文件进行处理。

  但在后来客户进出的对产品图片处理的新需求中,因为JakartaMultiPartRequest的问题,没有办法满足我们的要求,所以考虑到使用Spring的MultipartResolver来进行上传处理,但之前的代码不能再进行改动,否则所有处理文件上传的Controller必须更改,代价很大。但如果在Spring中进行配置MultipartResolver的配置后,发现我们旧的文件上传代码都失效了,无法上传文件。

(阅读全文……)

, ,

折腾了两天,终于在JBoss Seam中搞定了JSF Converter。

在这个程序中,产品(Product)和分类(Category)是多对多的关系,关系维护方为产品,在创建产品时,允许选择多个分类,因为Product.categories是一个List属性,同时产品选择<select />标签也是由从Action中查询出来的所有Category的List,所以在页面上,需要在页面渲染、用户提交后的category进行转换。

显示时,我们以Category.id为<option />的value值,而Category.title为label。

Entity如下(省略setter和getter):

Category.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entity
@Table(name = "category")
public class Category extends BaseEntity {
 
	@Id
	@GeneratedValue
	@Column(name = "id", unique = true, nullable = false, length = 10)
	private Integer id;
 
	@Column(name = "title")
	@NotNull
	@Length(min = 4, max = 64, message = "{invalid.length}")
	private String title;
 
	@ManyToMany(mappedBy = "categories")
	private List<product> products = new ArrayList</product><product>();
}
</product>

(阅读全文……)

, ,

  享元模式的宗旨:通过共享来为大量的细粒度对象提供有效支持。
  避免大量拥有相同类型的小类(细粒度,小类中的不可变部份)的开销(如耗费内存),使所有客户代码共享一个实例(元类)。

  怎么使用?(以人力资源系统中的公司员工为例):
  一般来说,在需要对某个员工进行访问的时候,我们都会new一个员工类,如果两个客户代码同时访问同一个员工,则会产生两个相同(或部份相同)的同一员工实例,这样,对于一个员工来说,内存中就可能有该员工的多个实例存在,如果一个企业有10000个员工,那内存中实际的员工实例可能就不止10000个。在这种情况下,我们就可以用享元模式来解决这个问题。

(阅读全文……)

, ,

  模板方法模式的目的就是在一个方法中实现一个算法,并将算法中某些步骤的定义推迟,从而使得其他类可以重新定义这些步骤。

  在编写一个方法的时候,考虑到算法的某些步骤可能会有不同的实现方式,我们可能会首先定出算法的框架。这样,在定义方法的时候,我们可以将某些步骤定义为抽象方法,或者是将它们定义为存根方法,也可以将它们定义为某个单独接口中的方法,这就是模板方法模式的实现。
  模板方法的典型例子就是排序。java.util.Collections类将sort()方法定义为一个模板方法,而将其中的比较交给用户来实现,sort()方法所接受的List中的对象需要实现Comparator接口,这就是将实际算法推迟并交给其它类来实现的模板方法模式。

(阅读全文……)

, ,

  并不是能创建并返回一个新的对象的方法都是工厂方法模式的实例。
  工厂方法模式不仅要求有一个能够创建新对象的方法,还要求能够使得客户代码无需了解应该具体实例化哪个类。工厂方法模式通常会包含有若干个类,这些类实现了相同的操作,返回了相同的抽象类型,然而,这些类的操作在内部实际上实例化了不同的类,不过这些类都实现了上述抽象类型。
  工厂方法模式的特征:
1. 该方法创建了一个新的对象
2. 该方法的返回类型为一个抽象类或接口
3. 有若干个类实现了上述抽象类或接口。

  比如我们要实现一个在线客户服务系统,若客服人员在线的时候,客户提交的问题将会直接传送给客服人员;若客服人员不在线,则将客户提交的问题发送至客服信箱。

(阅读全文……)

, ,

    观察者模式的宗旨:在多个对象之间定义一个一对多的关系,当一个对象状态改变的时候,其他所有的依赖于这个对象的对象能够得到通知,并自动更新。
    观察者模式在Swing中得到了广泛应用。当客户单击按钮时,程序中许多对象都会对此做出反应。在Swing中,关注Swing组件变化的类被称为“监听器”,这就是观察者模式的应用。

    为了支持观察者模式,Java类库中的java.util包中提供了Observable类和Observer接口。

    我们现在举一个例子来说明观察者模式。
    在网上商店的应用中,如果我们希望产品的名称被更改了后,系统会自动在控制台打印新名称,则就可以使用观察者模式。此时,产品类Product就需要继承Observable类,产品观察者类NameObserver则需要实现Observer接口。

(阅读全文……)

, ,

  单体模式的宗旨就是:使一个类只有一个实例。
  我们可以将类的constructor的可见性设置为私有来避免创建多个实例。当其他类调用该类的时候,我们可以利用getInstance()之类的方法来返回给调用者该类的实例。
  比如:

1
2
3
4
5
6
7
8
9
private Factory factory = null;
 
public static Factory getFactory() {
  if (factory == null) {
    factory = new Facotry();
}
 
return factory;
}

  上面的例子实现了单体模式,但如果在多线程环境中采用此方式,仍然可能产生多个实例,最好的办法,用synchronized来控制Factory实例的生成。

(阅读全文……)

, ,