2009年10月29日星期四

JAVA WEB开发库简介与记录


DbUnit:
    DbUnit is a JUnit extension (also usable with Ant) targeted at database-driven projects that, among other things, puts your database into a known state
    between test runs. This is an excellent way to avoid the myriad of problems that can occur when one test case corrupts the database and causes subsequent
     tests to fail or exacerbate the damage.
    主要的作用:数据库的测试,维护数据库稳定。DBUnit的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的
    状态;
    教程:http://blog.csdn.net/yuezu1026/archive/2009/04/08/4055923.aspx

EnCache:
    Ehcache is a widely used java distributed cache for general purpose caching, Java EE and light-weight containers.
    主要作用:Hibernate的二级缓存,Hibernate有两种缓存一种是Session里面的一级缓存,再有就是第三方的二级缓存,这个必须手工配置,要不然是不会生效的,用Ehcache并不代表不操作数据库了,而是它会把
                    实体类在内存中放一个缓存, 当不修改数据库时,它就不用时行数据库操作了,比如说读取的操作,如果进行保存的话,他也会更新缓存的。
    配置简介:在Application.xml里的SessionFactory里加上如下:
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.use_query_cache">true </prop>
<prop key="hibernate.cache.use_second_level_cache">
true
</prop>
这是启用缓存,另外还需要在ClassPath下建立:
ehcache.xml这个文件,里面这样写就行了:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!-- enable second level cache  -->
<diskStore path="java.io.tmpdir" />
<defaultCache maxElementsInMemory="100" eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="180" diskPersistent="false"
diskExpiryThreadIntervalSeconds="120" overflowToDisk="false" />

<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="100" eternal="true" overflowToDisk="true" />

<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="100" eternal="false" timeToLiveSeconds="120"
overflowToDisk="true" />

<cache name="com.clove.cms.model.User" maxElementsInMemory="100"
eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="180"
overflowToDisk="false" />
</ehcache>
User,就是你的实体类了!
    二级缓存简介:http://www.javaeye.com/topic/18904

JAF(activation.jar):

    全称JavaBeans 激活框架 (Java Bean Activation Framework),主要用于动态找到正确的组件以处理任意但类型化了的数据的机制 。特别是,作为发现 API 来开发 JAF,以便使 GUI 开发人员能够为文档和图像数据动态地发现浏览器和编辑器。
    简介:http://www.abcjava.com/html/ziyuanxiazai/J2EE/2009/0905/752.html

ActiveIO-Core:

    API:http://www.jarvana.com/jarvana/view/org/apache/activemq/activeio-core/3.1.0/activeio-core-3.1.0-javadoc.jar!/index.html

Apache ActiveMQ:
     The most popular and powerful open source messaging and Integration Patterns provider.

Antlr:
    ANTLR(ANother Tool for Language Recognition)它是这样的一种工具,它可以接受词文法语言描述,并能产生识别这些语言的语句的程序。作为翻译程序的一部分,你可以使用简单的操 作符和动作来参数化你的文法,使之告诉ANTLR怎样去创建抽象语法树(AST)和怎样产生输出。ANTLR知道怎样去生成识别程序,语言包括 Java,C++,C#.

Cglib:

    cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime. See samples and API documentation to learn more about features.
    Spring和Hibernate都是用了Cglib。Cglib则依赖于ASM库。简介:http://www.javaeye.com/topic/98178
    API:http://cglib.sourceforge.net/apidocs/index.html

chardet.jar:   
    jchardet is a java port of the source from mozilla's automatic charset detection algorithm. The original author is Frank Tang. What is available here is the java port of that code. The original source in C++ can be found from http://lxr.mozilla.org/mozilla/source/intl/chardet/ More information can be found at http://www.mozilla.org/projects/intl/chardet.html
    jchardet是mozilla自动字符集探测算法代码的java移植。
    主页:http://jchardet.sourceforge.net/
    介绍:http://blog.csdn.net/the3gwireless/archive/2007/08/13/1740228.aspx

Commons BeanUtils:

    一个用于操作Java Bean的工具类库。
    简介:http://www.blogjava.net/rongxh7/archive/2009/06/22/283566.html
    官网:http://commons.apache.org/beanutils/

Commons Codec:
    Commons Codec provides implementations of common encoders and decoders such as Base64, Hex, Phonetic and URLs.
    Commons Codec 提供了通用编码和解码的实现,例如Base64、Hex、Phonetic和URLs。
    官网:http://commons.apache.org/codec/

Commons-Collections:

    Commons-Collections seek to build upon the JDK classes by providing new interfaces, implementations and utilities.
    Java Collection Framework之上的一个框架。
    主页:http://commons.apache.org/collections/

Commons-Configuration:
    Commons Configuration provides a generic configuration interface which enables a Java application to read configuration data from a variety of sources.
    Configuration parameters may be loaded from the following sources:
  • Properties files
  • XML documents
  • Windows INI files
  • Property list files (plist)
  • JNDI
  • JDBC Datasource
  • System properties
  • Applet parameters
  • Servlet parameters
    主页:http://commons.apache.org/configuration/

Commons-DBCP:
    dbcp提供了数据库连接池;可以在spring,iBatis,hibernate中调用dbcp完成数据库连接,框架一般都提供了dbcp连接的方法;Tomcat中也提供了dbcp的jndi设置方法;
    Tomcat的dbcp配置:http://www.blogjava.net/ytl-zlq/archive/2009/04/14/265564.html
    使用例子:http://www.javaeye.com/topic/117225

Commons-digester:
    Many projects read XML configuration files to provide initialization of various Java objects within the system. There are several ways of doing this, and the Digester component was designed to provide a common implementation that can be used in many different projects.
    主页:http://commons.apache.org/digester/

Commons-fileupload:
    The Commons FileUpload package makes it easy to add robust, high-performance, file upload capability to your servlets and web applications.
    提供文件上传功能的库。
    主页:http://commons.apache.org/fileupload/

Commons-io:
    基本io库的封装,更方便。
    UserGuide:http://commons.apache.org/io/description.html

Commons-Lang:
    java.lang库的封装
    主页:http://commons.apache.org/lang/

Commons-logging:
    轻量级的日志库。
    主页:http://commons.apache.org/logging/

Commons-Net:

    Jakarta Commons Net implements the client side of many basic Internet protocols.
    支持的协议有:
  • FTP/FTPS
  • NNTP
  • SMTP
  • POP3
  • Telnet
  • TFTP
  • Finger
  • Whois
  • rexec/rcmd/rlogin
  • Time (rdate) and Daytime
  • Echo
  • Discard
  • NTP/SNTP
    主页:http://commons.apache.org/net/

Commons-pool:

    Pool provides an Object-pooling API, with three major aspects:
  1. A generic object pool interface that clients and implementors can use to provide easily interchangable pooling implementations.
  2. A toolkit for creating modular object pools.
  3. Several general purpose pool implementations.
    被DBCP库依赖。
    主页:http://commons.apache.org/pool/

DOM4J:

    dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX and JAXP.
    xml分析处理的库。
    主页:http://www.dom4j.org/

Fast InfoSet(FastInfoSet.jar):
    Fast Infoset (or FI) is an international standard that specifies a binary encoding format for the XML Information Set (XML Infoset) as an alternative to the XML document format. It aims to provide more     efficient serialization than the text-based XML format.
    Fast Infoset(FI)是一个国际通用标准的XML的二进制格式。用于提高XML文档的传输速度,相比于基于文本的XML格式二进制的XML文件传输更快。
    FastInfoSet库就是二进制格式XML的开源实现。
    主页:https://fi.dev.java.net/

IText:
   
iText is an ideal library for developers looking to enhance web- and other applications with dynamic PDF document generation and/or manipulation. iText is not an end-user tool.
    iText是一个的理想工具库,用于增强web开发和其他需要动态的生成或修改PDF文档的程序。iText通常不用于终端。
    主页:http://www.lowagie.com/iText/

IText-RTF:
    itext-RTF是一个itext的增强库。用于将Rich Text Files输出到PDF文件中,那些Rich Text File可以被RTF viewer所编辑观看,例如:MS office或Open Office
    UserGuide:http://itextdocs.lowagie.com/tutorial/rtf/index.php#rtfpackage

IText-RUPS:

    RUPS的缩写是Reading/Updating PDF Syntax。RUPS允许你看和操作PDF文档的内部结构。

Jakarta-ORO:
    Jakarta-ORO是最全面以及优化得最好的正则表达式API之一,Jakarta-ORO库以前叫做OROMatcher,是由Daniel F. Savarese编写,后来他赠给Jakarta Project。
    主页:http://jakarta.apache.org/oro/
    例子:http://oaklet.javaeye.com/blog/232969

JasperReports:
     JasperReports is the world's most widely used open source reporting engine.
    著名的报表引擎。
    主页:http://jasperforge.org/plugins/project/project_home.php?projectname=jasperreports

Javassist:
    和cglib一样也是用于编辑维护java bytecode的库。更简单。
    主页:http://www.csg.is.titech.ac.jp/~chiba/javassist/

JCommon:
    一个被JFreeChart使用的Java类库。主要功能有:        
  • configuration and dependency management code
  • a general logging framework
  • text utilities
  • user interface classes for displaying information about applications
  • custom layout managers
  • a date chooser panel
  • serialization utilities

JFreeChart:    
    JFreeChart is a free 100% Java chart library that makes it easy for developers to display professional quality charts in their applications.
    JFreeChart是一个100%的Java图表库,用于简化显示专业级的高质量图标。
    主页:http://www.jfree.org/jfreechart/

JSch:
    JSch是一个Java实现的SSH2协议。它可以实现连接到SSH2服务器的链接,并且使用端口映射、X11映射和文件传输。而且可以被集成到你的软件之中。

JSTL:
    JSTL标签库。

JTA:
    Java事物管理API(Java Transaction API),是一组java接口用于描述J2ee框架中事务管理器与应用程序,资源管理器,以及应用服务器之间的事务通讯。
    主页:http://java.sun.com/javaee/technologies/jta/index.jsp

Log4j:

    一个十分著名的重量级日志库。
    主页:http://logging.apache.org/log4j/1.2/index.html

JavaMail(mail.jar):
    邮件库。
    主页:http://java.sun.com/products/javamail/

Apache Neethi
    提供了一个使用Web Service Policy(WS-Policy是指Web服务策略框架规范)的通用库。
    主页:http://ws.apache.org/commons/neethi/index.html

Java Persistence API(JPA    persistence.jar):
    Java持久化API。提供了一个用于对象关系映射的(object-relational mapping)POJO的持久化模型。JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 JPA的总体思想和现有Hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
  • ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
  • JPA 的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
  • 查询语言,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
    简介:http://lqw.javaeye.com/blog/246807

pinying4j:
    用于将中文转换成拼音的库。
    主页:http://pinyin4j.sourceforge.net/html/installation.html

Apache POI:
    用于处理Microsoft Format Files的Java API。
    主页:http://poi.apache.org/

SAAJ:
    用于提供创造和创建SOAP消息的API库。
    主页:https://saaj.dev.java.net/
    SOAP消息定义:http://www.zxbc.cn/html/20080313/32398.htmlhttp://en.wikipedia.org/wiki/SOAP

SNMP4J:
    是一个SNMP协议的API库。
    主页:http://www.snmp4j.org/

JSP(tm) Standard Tag Library(standard.jar):
    是JSTL的一个实现。
    主页:http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html

Quartz:

    quartz是一个作业调度框架。使用它就可以设置在什么时候或隔多久执行一个任务。当然功能不止如此。
    主页:http://www.opensymphony.com/quartz/
    入门教程:http://hi.baidu.com/showco/blog/item/569e64d9e852e32f11df9bb0.html/cmtid/8976b000635d918ce850cd6d

Derby:
    是Apache DB的子项目,一个关系数据库的开源实现,完全使用Java实现。
    主页:http://db.apache.org/derby/

xbean-spring:
    用于简化spring的xml配置bean的库。
    简介:http://www.jroller.com/habuma/entry/spring_simplified_with_xbean

ojdbc.jar:
    Oracle数据库的JDBC驱动。

pager-taglib:

    一个jsp页面tag标签库。
    简介:http://jsptags.com/tags/navigation/pager/pager-taglib-2.0.html#examples

Geronimo:
    Apache Geronimo 是一个模块化的符合 Java™ 2 Platform, Enterprise Edition (J2EE) 规范的应用服务器平台,它基于使用控制反转(Inversion of Control,IoC)的架构解耦组件和服务以构建企业级应用程序和服务。

SLF4J:
    The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end-user to plug in the desired logging framework at deployment time.
    SLF4J为多种日志库提供了一种简单的操作或抽象,例如:java.util.logging,log4j和logback。它允许终端用户在部署时,以插件的形式添加需要的功能到框架中。
    主页:http://www.slf4j.org/

Spring&&Hibernate:
    太有名了,不说了。













[心情]今天好伤感

今天好伤感,想起了以前的事。小学、高中的事。

可能是与今天听的音乐有关,很伤感!

2009年10月28日星期三

趣事

鉴于北航出现了甲流患者,我突然感觉到甲流是如此的近,所以我决定响应号召去药店买个口罩,防止甲流。进店之后,店员已经全副武装。有两位女士在买药,我就走向店员问"这有口罩卖吗?"

突然,旁边买药的女士惊恐的往后退了三步,躲到另一位女士的身后。那眼神仿佛在看死神似的。我一下就无语了!虽然是人之常情但是动作实在太大了,全店都注意到了...

2009年10月15日星期四

[转]什么是UUID

UUID就是Universal Unique IDentifier的缩写,它是一个128位,16字节的值,并确保在时间和空间上唯一。
它是把硬件地址、时间以及随机数结合在一起,来确保其唯一性的。

一般情况下,生成算法用计算机网卡的地址和一个60位的timestamp生成,时间是以100ns为时间间隔。
例如,一台300PL 6862的计算机,主板集成的网卡的MAC地址为00-04-AC-2E-B7-DC,而UUID的最后六个字节也会是0004AC2EB7DC

[note]两篇不错的文章:超酷的JavaScript 图像液态效果和基于资源的HTTP Cache的实现介绍

都来自JavaEye:

超酷的JavaScript 图像液态效果

基于资源的HTTP Cache的实现介绍

2009年10月13日星期二

[转]一个类似淘宝固定工具条的效果

 
 

Sent to you by M.Zhou via Google Reader:

 
 

via WEB前端开发 by 愚人码头 on 10/10/09

在淘宝的列表页上有个列表排序的工具条,这个工具条默认显示是正常的,如图

tb1

,当滚动条往下拖动到该工具条的时候,改工具条就会始终固定在浏览器的顶部,就是position:fixed效果。

如图:

tb2

在当滚动条往上拖动的时候就会恢复原样,(可能表述不清楚,大家上淘宝自己去看吧。)

以前很讨厌这个效果,不习惯。最近感觉这样的工具条效果还真不错。所以今天尝试的自己弄了一个效果。

主要实现思路:在拖动滚动条的时候比较滚动条卷掉的高度和该工具条元素的Y坐标的值,如果滚动条卷掉的高度大于该工具条元素的Y坐标的值,那么将该工具条元素设置成position:fixed。

查看丑陋的demo:http://www.css88.com/demo/fixedbar/fixedBar.html

这个效果不支持ie6,因为ie6不支持position:fixed,暂时的委屈ie6用户,我恨ie6。


 
 

Things you can do from here:

 
 

2009年10月12日星期一

[转]spring的国际化

标题准确来说应该是“使用Spring中的IoC功能来实现我们所开发项目系统的国际化”,国际化不是针对IoC的,而是针对你开发的整个系统。

如果你使用过Eclipse的国际化,或者用过Eclipse的“外部化字符串”向导(Eclipse主菜单:源代码->外部化字符串),那么对Spring提供的国际化功能应该是非常容易理解,两者基本一样,或者说各种Java程序的国际化方式都基本一样。

先谈谈Eclipse国际化的两个组成部分:*.properties的资源文件、获取资源文件内容的Message类。

Spring则和Eclipse的处理类似:资源文件两者是一样的,不同语言的翻译放在不同的资源文件里,连起名规则都一样;EclipseMessage类要自己写(代码通用,复制以前项目的即可,或用Eclipse的向导生成一个也行),Spring则已经有写好的Message类,我们在IoCxml文件里注册一下即可使用(也可以实现SpringMessageSource接口,自己来写一个Message类,代码并不复杂,不过这没什么必要,用Spring提供的就行了)。

无论是EclipseMessage类,还是Spring的自带的Message类,或是我们自己写一个Message类,都是使用JDKjava.util.ResourceBundle类来实现*.properties文件的读取。

3.2  简单实例

假设我们有如下程序,程序的作用是打印出一个字符串

package cn.com.chengang.spring;

public class MessageTest {

    public static void main(String[] args) {

        String str = "ChenGang";

        System.out.println(str);

    }

}

现在,我们要让这个程序能够根据使用者的语言情况输出不同的字符,比如:对英文使用者输出“ChenGang”,对中文使用者输出“陈刚”,对台湾使用输出“��”等等。这个需求的实现方法如下:

1、创建一系列的资源文件

cn.com.chengang.spring包下创建以下文件:

1messages.properties(默认:英文),内容仅一句,如下

chengang=Giles

chengang”是键值,Giles是要输出的英文字符串

2messages_zh_CN.properties(简体中文)

chengang=\u9648\u521A

\u9648\u521A”是UNICODE码,对应的中文是“陈刚”

3messages_ zh_TW.properties(繁体中文)

chengang=\u9673\u525B

\u9673\u525B”对应的中文是“��”

 

附注:由于中文是要转换成UNICODE码,在编辑和阅读上有诸多不便,如果是用EclipseIDE,则有一个编辑资源文件的插件jinto,下载网址是http://www.guh-software.de/,用它打开的资源文件如下图所示,可以看到三个资源在一个界面反映了出来。

如果你不用Eclipse,而是用EditplugsJDK的方式来编程(现在还有这样的原始人吗?),你也可以用JDK自带的native2ascii.exe程序来将中文字串转成UNICODE码。Ant中还提供了一个相应的任务:<native2ascii encoding="GBK" src="${src}" dest="${build}"/>,其中GBK是一个中国的字符集。

 

2、修改bean.xml

Spring自带的org.springframework.context.support.ResourceBundleMessageSource类注册到bean.xml中,这个类的作用是获取资源文件的内容,注册到IoCbean.xml文件中是为了自动获得此类的对象(Spring做了一些简化编程的处理)。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

       <bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>

       <bean id="American" class="cn.com.chengang.spring.American"/>

       <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

              <property name="basenames">

                     <list>

                            <value>cn.com.chengang.spring.messages</value>

                     </list>

              </property>

       </bean>

</beans>

代码说明:

l           id="messageSource" 的设置是不变的、必须的。

l           ResourceBundleMessageSourceSpring的一个Message类。这里还有一个选择,用ReloadableResourceBundleMessageSource类,此类可以提供不用重启即可重新加载资源文件的特性(前者对资源文件只加载一次)。对于那种有热修改资源文件的需求,后者比较合适,只是后者在效率上有可能有损耗,因为至少要多一些检查资源文件是否改变的代码(这只是我的猜测,我没有仔佃去读这段的源码)。

l           basenames”是不变的、必须的。它是ResourceBundleMessageSource的一个属性,在源代码中的定义是“private String[] basenames;”,可见它是一个字符串数组。

l           cn.com.chengang.spring.messages”是把资源文件的位置传入到basenames属性中。注意:三个资源文件只需要将共同的主名(红色字体)传入:messages.propertiesmessages_zh_CN.propertiesmessages_zh_TW.properties

 

3、使用。修改MessageTest类,如下

package cn.com.chengang.spring;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MessageTest {

    public static void main(String[] args) {

        ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");

        String str = ctx.getMessage("chengang", null, null);

        System.out.println(str);

    }

}

代码说明:

1main方法里

l           第一句取得bean.xml文件的配置信息。

l           第二句从资源文件里得到键值chengang对应的字符串。

l           第三句将字符串打印出来,结果是打印的是“陈刚”,说明读取的是messages_zh_CN.properties资源文件。

2ctx.getMessage("chengang", null, null);有三个参数:

l           第一个是资源文件的键值;

l           第二个是资源文件字符串的参数,由于本字符串没有参数,所以用一个null(后面给出了一个用到字符串参数的实例);

l           第三个是一个java.util. Locale类型的参数。参数为null,则表示根据使用者的语言环境来选择Locale,因为我用的是中文版的windows,所以在取字符串时它自动选择了messages_zh_CN.properties资源文件。
   
这其中还有一个控制点在JVMJVM会根据当前操作系统的语言环境进行相应处理,我们可以通过在JVM启动参数中追加“-Duser.language=zh_TW”来设定当前JVM语言类型,通过JVM级的设定,也可以实现自动切换所使用的资源文件类型。
   
所以这里面的控制语言的方式有三种:从最低层的操作系统的Locale设定,到更上一层的JVMLocale设定,再到程序一级的Locale设定。

3.3  资源文件的其他使用方式:

package cn.com.chengang.spring;

import java.util.Locale;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

import org.springframework.context.support.ResourceBundleMessageSource;

public class MessageTest {

    public static void main(String[] args) {

        ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");

        String str = ctx.getMessage("chengang", null, null);

        System.out.println(str); //输出“陈刚”

        /*

         * 使用了messages.properties

         */

        str = ctx.getMessage("chengang", null, new Locale(""));

        System.out.println(str);//输出“Giles

        /*

         * 使用了messages_zh_CN.properties

         */

        str = ctx.getMessage("chengang", null, new Locale("zh", "CN"));

        System.out.println(str);//输出“陈刚”

        /*

         * 使用了messages_zh_TW.properties

         */

        str = ctx.getMessage("chengang", null, new Locale("zh", "TW"));

        System.out.println(str);//输出“��”

        /*

         * 使用了messages_zh_TW.properties,从这里可见资源文件的起名可以很随意,

         * 比如我们建立一个messages_123.properties,在传参数时候就可以这样:

         * new Locale("123"),一样也可以取出messages_123.properties中的值

         */

        str = ctx.getMessage("chengang", null, new Locale("zh_TW"));

        System.out.println(str);//输出“��”

        /*

         * 当找不到相应的资源文件时,使用了messages_zh_CN.properties

         */

        str = ctx.getMessage("chengang", null, new Locale("abcd"));

        System.out.println(str);//输出“陈刚”

         /**

         * 不通过IoC注册,直接使用ResourceBundleMessageSource类的写法。

         */

        ResourceBundleMessageSource s = new ResourceBundleMessageSource();

        s.setBasename("cn.com.chengang.spring.messages");

        str = s.getMessage("chengang", null, null);

        System.out.println(str);//输出“陈刚”

    }

}

代码说明:

前面说过控制语言的方式有三种:从最低层的操作系统的Locale设定,到更上一层的JVMLocale设定,再到程序一级的Locale设定。我认为最佳的方法是在程序一级进行控制:定义一个统一的Locale静态变量,然后整个系统中只使用这一个变量,以后就可以通过界面操作设置此Locale变量的值,让用户来选择他所需的软件语言。而且我们也可以将此静态变量设成null值,来自动选择资源文件。

另外,Locale里也定义了一些常量,我们可以直接使用而不必去new一个Locale对象,如:“Locale.ENGLISH”。

 

3.4  再一个实例

这个实例演示了如何使用多个资源文件,以及如何使用字符串参数

1)在cn.com.chengang.spring包下再创建一个资源文件messagesOther_zh_CN.properties

chengang.info=\u9648\u521A\uFF0C\u7F51\u540D\uFF1A{0}\uFF0C\u82F1\u6587\u540D\uFF1A{1}\uFF0CBlog\uFF1A{2}

其中UNICODE字符串对应的中文是:“陈刚,网名:{0},英文名:{1}Blog{2}”,这个字符串一共有三个参数。

2)修改 bean.xml文件

因为basenames属性是一个数组,当然也就可以接收多个资源文件设定。具体修改如下面的红字部份

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

       <bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>

       <bean id="American" class="cn.com.chengang.spring.American"/>

       <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">

              <property name="basenames">

                     <list>

                            <value>cn.com.chengang.spring.messages</value>

                            <value>cn.com.chengang.spring.messagesOther</value>

                     </list>

              </property>

       </bean>

</beans>

 

3)修改MessageTest类,加入几行使用的代码

        String[] strArgs = new String[3];

        strArgs[0]="混北民工";

        strArgs[1]="Giles";

        strArgs[2]="http://blog.csdn.net/glchengang";

        str = ctx.getMessage("chengang.info", strArgs, null);

        System.out.println(str);

打印出来的结果就是:“陈刚,网名:混北民工,英文名:GilesBloghttp://blog.csdn.net/glchengang

 

3.5  国际化的实践建议

l           建议一个包对应一个资源文件。不要整个系统都使用一个资源文件来翻译,这样单个文档的体积就太大了,不利于维护;当然,也不必一个类对应一个资源文件,这样资源文件又太多了。

l           建议资源文件和其翻译类/包在同一目录下。不过,如果是要将软件打成一外JAR包或WAR包,建议把资源文件分离出来,这样可以修改资源文件,而不必再次打包。

l           建议字符串项的键值上加上其所在的类名。比如:上面的chengangchengang.info最好是取名成MessageTest.chengangMessageTest.chengang.info。这样查找使用此键值的类会方便很多。

[note]Spring注解入门两篇

使用 Spring 2.5 注释驱动的 IoC 功能

使用 Spring 2.5 基于注解驱动的 Spring MVC

2009年10月11日星期日

[note]生活计划

前几日看Heroes的最新一季,克莱尔的新室友总是说:"Everyone has a plan!"。刚想起来自己也应该有个计划,这样生活学习比较有动力。

下一步关注的一些库和语言,年底之前要完成的目标:

required:
Spring库的熟练掌握
Rhino库的学习
Linux C的初步学习

optional:
写自己的JS引擎
学习五线谱

[note]Java的两个关键字:synchronize和volatile

Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。
volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。
由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。
Synchronize修饰的变量或者方法在每次被线程访问时,都会先锁定此资源,然后操作,操作完成后解锁。与Volatile最大的不同在于锁定和解锁,保证了操作的原子性,而Volatile只能保证read-write等
原子操作的原子性,当三者混合执行时就会出错,如:
  1. public class TestRaceCondition {  
  2.     private volatile int i = 0;  
  3.   
  4.     public void increase() {  
  5.        i++;  
  6.     }  
  7.   
  8.     public int getValue() {  
  9.        return i;  
  10.     }  

i++这一步等于:i = i + 1;先read i,然后执行+操作,最后赋值更新。当多线程执行时,这些一个个操作之间夹杂着其他线程的操作,就会出现错误。

[转] Spring中的WebAppRootListener

这个listenr的作用就是监听web.xml中的配置para-name为webAppRootKey的值,比如我的web应用为tsts,那么我配置

这样一个

  1. <context-param>
  2.         <param-name>webAppRootKey</param-name>
  3.         <param-value>tsts.root</param-value>
  4.     </context-param>

,然后再配置这样一个监听器:

  1. <listener>
  2.         <listener-class> 
  3.             org.springframework.web.util.WebAppRootListener
  4.         </listener-class>
  5.     </listener>

。这个监听器就会在web上下文初始化的时候,调用webUtil的对应方法,首先获取到param-name对应的param-value ,然后,根据传递进去的ServletContext对象得到web的物理路径:String root = servletContext.getRealPath("/");

接着把这个param-value作为key,root作为value放到system中System.setProperty(key, root);

然后再web中可以用 System.get.....就可以得到web的跟目录的物理路径了。

之前我的做法是用一个filter,在filter的init中调用String root = servletContext.getRealPath("/");,然后再去设置对应一个常量类文件的属性。做法差不多,但是spring的做法更可以借鉴!

[转]spring学习笔记之DispatcherServlet源码解读

spring web MVC 框架,就像其他web MVC框架一样,是请求驱动,围绕一个核心的servlet设计,这个servlet把接收的请求(request)分别分发到不同的控制器并提供其他功能促进web应用的开发。而spring的DispatcherServlet做的事情更多。它完全整合了spring Ioc容器方便你使用spring所拥有的功能。

这幅图解释了spring web MVC DispatcherServlet对请求的处理流程。其实DispatcherServlet是采用了前端控制器(Front Controller)的设计模式,这种设计模式也被其他流行的web框架所采用。

DispatcherServlet层次类图

根据类图,知道DispatcherServlet实际上是一个Servlet,因为它继承于HttpServlet,所以它需要在web.xml定义,并且在web.xml定义需要通过DispatherServlet处理的请求的URL映射。

这是标准的J2EE servlet 配置方式。下面是一个例子:


  1. <web-app>  
  2.     <servlet>  
  3.         <servlet-name>example</servlet-name>  
  4.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  5.         <load-on-startup>1</load-on-startup>  
  6.     </servlet>  
  7.     <servlet-mapping>  
  8.         <servlet-name>example</servlet-name>  
  9.         <url-pattern>*.form</url-pattern>  
  10.     </servlet-mapping>  
  11. </web-app>  


       上面这个例子,所有以.form结尾的请求都会被名为example的DispaterServlet处理。这是使用spring MVC的第一步,一系列beans需要配置。

       在spring web MVC框架,每一个DispatcherServlet都有它自己的WebApplicationContext,这些 WebApplicationContext继承了一个根WebApplicationContextde定义的所有bean。这些被继承的bean可以 在具体的servlet中改写作用域,也可以在一个servlet实例定义新的局部的作用域bean。

       框架在启动初始化DispatcherServlet时,在WEB应用下的WEB-INF目录下寻找名为[servlet- name]-servlet.xml的文件,并创建定义的bean,这些bean如果同样在全局作用域中定义(名字相同),则覆盖全局bean.如在上一 例中,则会找WEB-INF/example-servlet.xml文件。当然,配置文件的路径可以通过servlet的参数配置。

       WebApplicationContext是普通的ApplicationContext的扩展,它增加了一些web应用需要的特性。比如,它解析 themes与ApplicationContext是不同的,因为它会关联到ServletContext。 WebApplicationContext绑定到了ServletContext,在你需要访问它时,只需要用RequestContextUtils 类的静态方法就可以找到它。

       DispatcherServlet有几个特殊的bean用来处理request请求和渲染适合的视图。这些bean包含在spring框架中,并可在WebApplicationContext像其他普通bean一样配置。在下面有更具体的介绍。

Bean类型

说明

Controllers

MVC架构的'C'

Handler mappings

主要负责预处理,后置处理等一系列执行处理和满足特定条件下的控制器的执行,比如URL匹配等

View resolvers

负责根据视图名称解析视图

Locale resolver

负责语言本地化

Theme resolver

负责根据应用使用解析主题,比如可以定制个性化版面

multipart file


resolver


负责在html页面提供文件上传功能

Handler exception resolver(s)

负责提供处理异常功能

DispatcherServlet服务启动,一个请求到特定的DispatcherServlet,这时Dispatcher开始处理请求。下面是DispatcherServlet处理请求的完整过程。

1.寻找WebApplicationContext并且在request作为一个属性绑定方便控制器和其他成员使用。默认的绑定KEY是  DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE.

2.本地化解析器绑定到request中。如果没有使用该解析器,则不作任何事情。

3.主题解析器绑定到request中。如果没有使用该解析器,则不做任何事情。

4.如果multipart resolver被指定,则request会检测它。如果找到,request被包装成MultipartHttpServletRequest方便之后的其他成员处理。

5.寻找合适的的处理模块。如果找到,该处理模块相关的执行链如预处理,后置处理和控制器等都会被执行为模块的渲染作准备。

6.如果一个模块返回,则会渲染一个视图。如果没有模块返回,就没有视图被渲染,因为请求可能已经处理完成。

处理请求过程中抛出异常,请求会启用在WebApplicationContext声明的异常处理解析器。在发生异常时,可以使用这些解析器定义用户的行为。

DispatcherServlet也支持返回last-modification-date。DispatcherServlet首先寻找一个合适的处理映射并检测这处理模块是否实现了LastModified接口。如果是,这个接口的方法long getLastModified(request)返回值给客户端。

你也可以定制DispatcherServlet,通过在web.xml或者servlet初始参数上添加上下文容器的参数。具体如下:

参数

说明

contextClass

实现了WebApplicationContext接口的类,用来初始上下文环境。如果没有指定,则默认XmlWebApplicationContext

contextConfigLocation

传递给context实例的字符串,说明哪里可以找到context。这个字符串可被逗号拆分从而支持多个contexts。

namespace

WebApplicationContext命名空间。默认是 [servlet-name]-servlet



现在再查看源码加深理解。

首先服务器如tomcat启动时,就会将web.xml定义的context的bean都会实例化。入口当然是

org.springframework.web.servlet.DispatcherServlet。 它是一个HttpServlet,所以必然会执行init()方法。我们查看根据上述的DispatcherServlet类图查看,发现 HttpServletBean才有init()方法。


  1. public final void init() throws ServletException {  
  2.         if (logger.isDebugEnabled()) {  
  3.             logger.debug("Initializing servlet '" + getServletName() + "'");  
  4.         }  
  5.         // Set bean properties from init parameters.  
  6.         try {  
  7.             PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  
  8.             BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);  
  9.             ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());  
  10.             bw.registerCustomEditor(Resource.classnew ResourceEditor(resourceLoader));  
  11.             initBeanWrapper(bw);  
  12.             bw.setPropertyValues(pvs, true);  
  13.         }  
  14.         catch (BeansException ex) {  
  15.             logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);  
  16.             throw ex;  
  17.         }  
  18.         // Let subclasses do whatever initialization they like.  
  19.         initServletBean();  
  20.         if (logger.isDebugEnabled()) {  
  21.             logger.debug("Servlet '" + getServletName() + "' configured successfully");  
  22.         }  
  23.     }  

在这个方法里最重要的是initServletBean()。它会调用FrameworkServlet下的initServletBean(),这个方法改写了HttpServletBean的initServletBean()。代码如下:

 
  1. protected final void initServletBean() throws ServletException, BeansException {  
  2.         getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");  
  3.         if (this.logger.isInfoEnabled()) {  
  4.             this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");  
  5.         }  
  6.         long startTime = System.currentTimeMillis();  
  7.         try {  
  8.             this.webApplicationContext = initWebApplicationContext();  
  9.             initFrameworkServlet();  
  10.         }  
  11.         catch (ServletException ex) {  
  12.             this.logger.error("Context initialization failed", ex);  
  13.             throw ex;  
  14.         }  
  15.         catch (BeansException ex) {  
  16.             this.logger.error("Context initialization failed", ex);  
  17.             throw ex;  
  18.         }  
  19.         if (this.logger.isInfoEnabled()) {  
  20.             long elapsedTime = System.currentTimeMillis() - startTime;  
  21.             this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +  
  22.                     elapsedTime + " ms");  
  23.         }  
  24.     }  

我们应该注意到这个方法有修饰符final,是不能子类重写的,这就体现了 “开-闭原则(open for extension,close for modification)”我们再看initWebApplicationContext()


  1. protected WebApplicationContext initWebApplicationContext() throws BeansException {  
  2.         WebApplicationContext wac = findWebApplicationContext();  
  3.         if (wac == null) {  
  4.             // No fixed context defined for this servlet - create a local one.  
  5.             WebApplicationContext parent =  
  6.                     WebApplicationContextUtils.getWebApplicationContext(getServletContext());  
  7.             wac = createWebApplicationContext(parent);  
  8.         }  
  9.         if (!this.refreshEventReceived) {  
  10.             // Apparently not a ConfigurableApplicationContext with refresh support:  
  11.             // triggering initial onRefresh manually here.  
  12.             onRefresh(wac);  
  13.         }  
  14.         if (this.publishContext) {  
  15.             // Publish the context as a servlet context attribute.  
  16.             String attrName = getServletContextAttributeName();  
  17.             getServletContext().setAttribute(attrName, wac);  
  18.             if (this.logger.isDebugEnabled()) {  
  19.                 this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +  
  20.                         "' as ServletContext attribute with name [" + attrName + "]");  
  21.             }  
  22.         }  
  23.         return wac;  
  24.     }  

FindWebApplicationContext() 方法是从 ServletContext 属性取 WebApplicationContext ,如果没有配置 ServletContext 属性的话,则返回 null 。这时,先取回根 WebApplicationContext,key 是 WebApplicationContext. ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE

 

createWebApplicationContext(parent) 方法是真正得到我们 DispatcherServlet 对应的 WebApplicationContext

 
  1. protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)  
  2.             throws BeansException {  
  3.         if (this.logger.isDebugEnabled()) {  
  4.             this.logger.debug("Servlet with name '" + getServletName() +  
  5.                     "' will try to create custom WebApplicationContext context of class '" +  
  6.                     getContextClass().getName() + "'" + ", using parent context [" + parent + "]");  
  7.         }  
  8.         if (!ConfigurableWebApplicationContext.class.isAssignableFrom(getContextClass())) {  
  9.             throw new ApplicationContextException(  
  10.                     "Fatal initialization error in servlet with name '" + getServletName() +  
  11.                     "': custom WebApplicationContext class [" + getContextClass().getName() +  
  12.                     "] is not of type ConfigurableWebApplicationContext");  
  13.         }  
  14.         ConfigurableWebApplicationContext wac =  
  15.                 (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(getContextClass());  
  16.         wac.setParent(parent);  
  17.         wac.setServletContext(getServletContext());  
  18.         wac.setServletConfig(getServletConfig());  
  19.         wac.setNamespace(getNamespace());  
  20.         wac.setConfigLocation(getContextConfigLocation());  
  21.         wac.addApplicationListener(new SourceFilteringListener(wac, this));  
  22.         postProcessWebApplicationContext(wac);  
  23.         wac.refresh();  
  24.         return wac;  
  25.     }  

 

在这个方法里,首先调用 getContextClass() 获取默认的 ContextClass, 就是 public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext. class

 
  1. ConfigurableWebApplicationContext  wac  =  
  2. (ConfigurableWebApplicationContext) BeanUtils. instantiateClass (getContextClass());   

这行代码就是利用 XmlWebApplicationContext 的无参数构造函数实例化 XmlWebApplicationContext 因为 XmlWebApplicationContext 实现了 ConfigurableWebApplicationContext 接口。接下来就是填充 XmlWebApplicationContext 的属性,这些属性部分在上面有提及过。这样在这个 WebApplicationContext 就可以使用了。