一个简单的JSF 2.0例子

Posted by dohkoos on February 26th, 2009 (1,784 views)

开发环境:
JDK 1.6.0
Tomcat 6.0.18
Eclipse 3.4.1
Maven 2.1.0
m2eclipse 0.9.7
JSF 2.0.0

首先使用m2eclipse创建一个简单的maven项目。然后添加FacesServlet到web.xml中:

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>

接着,就是把JSF2的jar包加入pom.xml文件中:

<repositories>
    <repository>
        <id>maven2-repository.dev.java.net</id>
        <name>Java.net Repository for Maven</name>
        <url>http://download.java.net/maven/2/</url>
        <layout>default</layout>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-api</artifactId>
        <version>2.0.0-b09</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-impl</artifactId>
        <version>2.0.0-b09</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

再创建一个managed bean:

@ManagedBean(name="mainbean")
public class MainBean {

    public String getText() {
        return "Hello, JSF 2.0";
    }
}

还要创建一个视图:

<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>A simple JSF 2.0 example</title>
    </h:head>

    <h:body>
        <h:outputText value="#{mainbean.text}" />
    </h:body>
</html>

就这样,一个简单的JSF2例子就完成了。

看完这个例子后你可能会注意到上面并没有创建faces-config.xml这个文件。是的,这是因为这个例子实在是太简单了,以至于不需要faces-config.xml也可以:)

jsf2-example下载

Related Posts

在egit-0.3.1中使用Compare With Git Revision功能

Posted by dohkoos on August 28th, 2008 (681 views)

egit是一个Eclipse环境下的Git客户端插件,最新版本的egit已经提供了Compare With Revision功能,只是还没有注册到plugin.xml中。所以要使用该功能的话,我们必须自己动手在ui包中的plugin.xml中添加一些代码,即下面的红色部分
<objectContribution
        adaptable="true"
        id="org.spearce.egit.ui.fileFolderContributions"
        objectClass="org.eclipse.core.resources.IResource">
    <filter name="projectPersistentProperty"
        value="org.eclipse.team.core.repository=org.spearce.egit.core.GitProvider">
    </filter>
    <action
        class="org.spearce.egit.ui.internal.actions.CompareWithRevisionAction"
        id="org.spearce.egit.ui.internal.actions.CompareWithRevisionAction"
        label="%CompareWithRevisionAction_label"
        menubarPath="compareWithMenu/compareWithGroup"
        overrideActionId="org.eclipse.team.ui.compareLocalHistory"
        tooltip="%CompareWithRevisionAction_tooltip" />

</objectContribution>

另外,还要将CompareWithRevisionAction.java中run方法的第一条语句删除,否则会报StackOverflow异常
public void run(IAction action) {
    super.action(action);
    ...
}

Related Posts

垃圾收集机制(Garbage Collection)批判[zt]

Posted by dohkoos on February 6th, 2007 (506 views)

在Java版发表这篇文章,似乎有点把矛头指向Java了。其实不是,GC是所有新一代语言共有的特征,
Python, Eiffel,C#,Roby等无一例外地都使用了GC机制。但既然Java中的GC最为著名,所以天塌
下来自然应该抗着。

这篇短文源于comp.lang.java.programmer跟comp.lang.c++上发生的一场大辩论,支持C++和Java
的两派不同势力展开了新世纪第一场冲突,跟贴发言超过350,两派都有名角压阵。C++阵营的擂主是
Pete Becker,ACM会员,Dinkumware Ltd. 的技术副总监。此君精通C++和Java,开发过两种语言的
核心类库,但是却对C++狂热之极,而对于Java颇不以为然。平时谈到Java的时候还好,一旦有人胆
敢用Java来批判C++,立刻忍不住火爆脾气跳将出来,以坚韧不拔的毅力和大无畏精神与对手周旋,
舌战群儒,哪怕只剩下一个人也要血战到底。这等奇人当真少见!我真奇怪他整天泡在usenet上,
不用工作么?他的老板P.J. Plauger如此宽宏大量?Java阵营主角是一个网名Razzi的兄弟,另外有
Sun公司大名鼎鼎的Peter van der Linden助阵,妙语连珠,寸土必争,加上人多势众,一度占据优势。
C++阵营里大拿虽然很多,但是大多数没有Pete那么多闲工夫,例如Greg Comeau,Comeau公司老板,
每次来个只言片语,实在帮不了Pete多大忙。但是自从C++阵营中冒出一个无名小子,网名Courage(勇气),
发动对Java GC机制的批判,形势为之一变。C++阵营眼下处于全攻之势,Java阵营疲于防守,只能
招架说:“你们没有证据,没有统计资料”,形势很被动。

垃圾收集(GC)不是一直被Java fans用来炫耀,引以为傲的优点么?怎么成了弱点了?我大惑不解,定睛
一看,才觉得此中颇有道理。

首先,Java Swing库存在大量资源泄漏问题,这一点SUN非常清楚,称之为bugs,正在极力修正。但是看来
这里的问题恐怕不仅是库编写者的疏忽,可能根源在于深层的机制,未必能够轻易解决,搞不好要伤筋动骨。
不过这个问题不是那么根本,C++阵营觉得如果抓住对方的弱点攻击,就算是占了上风也没什么说服力。谁
没有缺点呢?于是反其道而行之,猛烈攻击Java阵营觉得最得意的东西,Java的GC机制本身。

首先来想一想,memory leak到底意味着什么。在C++中,new出来的对象没有delete,这就导致了memory
leak。但是C++早就有了克服这一问题的办法——smart pointer。通过使用标准库里设计精致的auto_ptr
以及各种STL容器,还有例如boost库(差不多是个准标准库了)中的四个smart pointers,C++程序员只要
花上一个星期的时间学习最新的资料,就可以拍着胸脯说:“我写的程序没有memory leak!”。

相比之下,Java似乎更优秀,因为从一开始你就不用考虑什么特殊的机制,大胆地往前new,自有GC替你
收拾残局。Java的GC实际上是JVM中的一个独立线程,采用不同的算法策略来收集heap中那些不再有
reference指向的垃圾对象所占用的内存。但是,通常情况下,GC线程的优先级比较低,只有在当前程序
空闲的时候才会被调度,收集垃圾。当然,如果JVM感到内存紧张了,JVM会主动调用GC来收集垃圾,获取
更多的内存。请注意,Java的GC工作的时机是:1. 当前程序不忙,有空闲时间。2. 空闲内存不足。
现在我们考虑一种常见的情况,程序在紧张运行之中,没哟空闲时间给GC来运行,同时机器内存很大,
JVM也没有感到内存不足,结果是什么?对了,GC形同虚设,得不到调用。于是,内存被不断吞噬,而那些
早已经用不着的垃圾对象仍在在宝贵的内存里睡大觉。例如:

class BadGc {

    public void job1() {
        String garbage = "I am a garbage, and just sleeping in your precious memory, " +
                  "how do you think you can deal with me? Daydreaming! HAHA!!!";
        ...
    }

    public void job2() {…}

    ...
    ...

    public void job1000() {…}

    public static void main(String[] args) {
        bgc = new BadGc();
        bgc.job1();
        bgc.job2();
        ...
        bgc.job1000();
    }
}

运行中,虽然garbage对象在离开job1()之后,就再也没有用了。但是因为程序忙,内存还够用,所以GC得
不到调度,garbage始终不会被回收,直到程序运行到bgc.job1000()时还躺在内存里嘲笑你。没辙吧!

好了,我承认这段程序很傻。但是你不要以为这只是理论上的假设,恰恰相反,大多数实用中的Java程序都有
类似的效应。这就是为什么Java程序狂耗内存,而且好像给它多少内存吃都不够。你花上大笔的银子把内存
从128升到256,再升到512,结果是,一旦执行复杂任务,内存还是被轻易填满,而且多出来的这些内存只是
用来装垃圾,GC还是不给面子地千呼万唤不出来。等到你的内存终于心力交瘁,GC才姗姗来迟,收拾残局。而
且GC工作的方式也很不好评价,一种方法是一旦有机会回收内存,就把所有的垃圾都回收。你可以想象,这要
花很长时间(几百M的垃圾啊!),如果你这时侯正在压下开炮的按钮,GC却叫了暂定,好了,你等死吧!另一
种方法,得到机会之后,回收一些内存,让JVM感到内存不那么紧张时就收手。结果呢,内存里始终有大批垃
圾,程序始终在半死不活的荡着。最后,GC可以每隔一段时间就运行一次,每次只回收一部分垃圾,这是现在
大部分JVM的方式,结果是内存也浪费了,还动不动暂停几百毫秒。难啊!

反过来看看C++利用smart pointer达成的效果,一旦某对象不再被引用,系统刻不容缓,立刻回收内存。这
通常发生在关键任务完成后的清理(cleanup)时期,不会影响关键任务的实时性,同时,内存里所有的对象
都是有用的,绝对没有垃圾空占内存。怎么样?传统、朴素的C++是不是更胜一筹?

据统计,目前的Java程序运行期间占用的内存通常为对应C++程序的4-20倍。除了其它的原因,上面所说的是一个
非常主要的因素。我们对memory leak如此愤恨,不就是因为它导致大量的内存垃圾得不到清除吗?如果有了
GC之后,垃圾比以前还来势汹汹,那么GC又有什么好处呢?

当然,C++的smart pointer现在会使用的人不多,所以现在的C++程序普遍存在更严重的memory leak问题。
但是,如果我奶奶跟舒马赫比赛车输掉了,你能够埋怨那辆车子么?

Related Posts

People who read this, also read...

[PB2J]PowerBuilder标识符 versus Java标识符

Posted by dohkoos on December 13th, 2006 (462 views)

在使用减号(-)、负号(-)、减1(--)运算符时,必须在这些符号的前面加上空格,原因在于PowerBuilder会把这些符号当成标识符的一部分。

PowerBuilder Java
必须以字母或下划线(_)开头 必须以字母、下划线(_)或美元符号($)开头
其余字符可以是字母、数字、下划线(_)、美元符号($)、
短横线(-)、号码符号(#),百分号(%)
其余字符可以是字母、数字、下划线(_)、美元符号($)
最长40个字符(实际最大长度可达99个),中间不能有空格 未规定最大长度,中间不允许有空格
不区分大小写 区分大小写

问题:如何禁止在标志符中使用短横线(-)?
可以在PB.INI的[pb]节中将DashesInIdentifiers=1修改为DashesInIdentifiers=0

Related Posts

People who read this, also read...

DbUnit结合Spring进行SqlMap的单元测试

Posted by dohkoos on April 10th, 2006 (1,202 views)

使用DbUnit,开发人员可以控制测试数据库的状态。进行一个DAO单元测试之前,DbUnit为数据库准备好初始化数据;而在测试结束时,DbUnit会把数据库状态恢复到测试前的状态。下面的例子使用DbUnit为SqlMap编写单元测试。

SqlMap映射文件如下所示:


DELETE FROM user WHERE username = #username#


UPDATE user SET
password = #password#,
first_name = #firstName#,
last_name = #lastName#
WHERE username =#username#


INSERT INTO user (username, password, first_name, last_name)
VALUES (#username#, #password#, #firstName#, #lastName#)

SqlMapConfig配置文件内容如下:

cacheModelsEnabled="true"
enhancementEnabled="true"
maxSessions="64"
maxTransactions="8"
maxRequests="128" />


首先,要为单元测试准备测试数据。我们可以用DbUnit的Flat XML格式来准备测试数据集。下面的XML文件称为目标数据库的Seed File,它为测试准备了两个User数据。其中元素名user对应数据库的表名,属性username,password,first_name和last_name是表user的列名,属性值就是记录值。


password="john"
first_name="dbunit"
last_name="john" />

password="peter"
first_name="ibatis"
last_name="peter" />

缺省情况下,DbUnit在单元测试开始之前执行CLEAN_INSERT操作,删除Seed File中所有表的数据,并导入Seed File的测试数据。我们可以通过覆盖getSetUpOperation()和getTearDownOperation()方法来控制单元测试前和测试后的数据库状态。一种高效的实施方案就是让getSetUpOperation()方法执行REFRESH操作,通过执行这个操作,我们可以用Seed File中的数据去更新目标数据库里的数据。接下来,就是getTearDownOperation(),让他执行一个NONE操作,也就是什么也不执行。
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}

protected DatabaseOperation getTearDownOperation() throws Exception {
return DatabaseOperation.NONE;
}

为了方便测试,我们为SqlMap的单元测试编写一个抽象的测试基类,代码如下:
public abstract class SqlMapTestCase extends DatabaseTestCase {
protected SqlMapClient sqlMapClient = null;
protected Properties props = new Properties();

protected IDatabaseConnection getConnection() throws Exception {
props.load(Resources.getResourceAsStream("properties/database.properties"));

Class.forName(props.getProperty("driver"));
Connection conn = DriverManager.getConnection(props.getProperty("url"),
props.getProperty("username"), props.getProperty("password"));
return new DatabaseConnection(conn);
}

protected IDataSet getDataSet() throws Exception {
String resource = "org/dbunit/example/dao/impl/sql/dataset.xml";
return new FlatXmlDataSet(Resources.getResourceAsStream(resource));
}

protected void setUp() throws Exception {
super.setUp();

// Build the SqlMapClient
Reader reader = Resources.getResourceAsReader("sql-map-config.xml");
sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);

// Tell the SqlMapClient to use the given DataSource
DataSource dataSource = getDataSource();
TransactionConfig transactionConfig = getTransactionConfig(dataSource);
// Apply the given TransactionConfig to the SqlMapClient
applyTransactionConfig(sqlMapClient, transactionConfig);
}

protected void tearDown() throws Exception {
super.tearDown();

if (sqlMapClient != null) {
DataSource ds = sqlMapClient.getDataSource();
Connection conn = ds.getConnection();
conn.close();
}
}

private DataSource getDataSource() throws Exception {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(props.getProperty("driver"));
dataSource.setUrl(props.getProperty("url"));
dataSource.setUsername(props.getProperty("username"));
dataSource.setPassword(props.getProperty("password"));
return dataSource;
}

private TransactionConfig getTransactionConfig(DataSource dataSource) throws Exception {
Properties transactionConfigProperties = new Properties();
transactionConfigProperties.setProperty("SetAutoCommitAllowed", "false");

TransactionConfig transactionConfig = (TransactionConfig)ExternalTransactionConfig.class.newInstance();
transactionConfig.setDataSource(dataSource);
transactionConfig.initialize(transactionConfigProperties);
return transactionConfig;
}

private void applyTransactionConfig(SqlMapClient sqlMapClient, TransactionConfig transactionConfig) {
if (!(sqlMapClient instanceof ExtendedSqlMapClient)) {
throw new IllegalArgumentException("Cannot set TransactionConfig with DataSource"
+ "for SqlMapClient if not of type ExtendedSqlMapClient: " + sqlMapClient);
}
ExtendedSqlMapClient extendedClient = (ExtendedSqlMapClient)sqlMapClient;
transactionConfig.setMaximumConcurrentTransactions(extendedClient.getDelegate().getMaxTransactions());
extendedClient.getDelegate().setTxManager(new TransactionManager(transactionConfig));
}
}

然后为每个SqlMap映射文件编写一个测试类,继承上面的抽象类:
public class UserSqlMapTest extends SqlMapTestCase {

public void testGetUser() throws Exception {
User user = (User)sqlMapClient.queryForObject("getUser", "john");
assertNotNull(user);
assertEquals("john", user.getName());
}
}

如此就可以进行单元测试了。

Related Posts

People who read this, also read...

MD5算法描述及Java的实现

Posted by dohkoos on September 24th, 2005 (389 views)

MD5算法的RFC网址:http://www.faqs.org/rfcs/rfc1321.html

word表示32-bit
byte表示8-bit

X_i表示Xi
X^i表示Xi

X<<<s表示左循环移位

not(X)表示~X
XvY表示X|Y
XY表示X&Y

假设有消息m,则b = m.getBytes().length * 8

if ((b % 512) >= 448) {
    padding (512 - b % 512 + 448) bits
} else if ((b % 512) < 448) {
    padding (448 - b % 512) bits
}
padding规则是一个1,n个0。使padding后的消息长度为448加上512的倍数。(0 <= n <= 512)

将b用64-bit表示,如果b > 264,则只取低64 bits,然后按照低位优先的原则将64 bits填充到上述结果后面,使的消息长度为512的倍数。该消息用M[0...N-1]表示。其中M[i]是一个word。

word A: 01 23 45 67
word B: 89 ab cd ef
word C: fe dc ba 98
word D: 76 54 32 10

A = 0x67452301
B = 0xefcdab89
C = 0x98badcfe
D = 0x10325476

4个辅助函数
f(x,y,z) = (x & y) | ((~x) & z)
g(x,y,z) = (x & z) | (y & (~z))
h(x,y,z) = x ^ y ^ z
i(x,y,z) = y ^ (x | (~z))

表T[1...64],其中T[i] = 4294967296 * abs(sin(i))的整数部分,i的单位是弧度。

for (int i = 0; i < N % 16; i++) {
    for (int j = 0; j < 16; j++) {
        X[j] = M[i * 16 + j];
    }

    AA = A;
    BB = B;
    CC = c;
    DD = d;

    /* Round 1 */
    /*
     * Let [abcd k s i] denote the operation
     *   a = b + ((a + F(b, c, d) + X[k] + T[i]) <<< s.
    */
    [ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
    [ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8]
    [ABCD  8  7  9]  [DABC  9 12 10]  [CDAB 10 17 11]  [BCDA 11 22 12]
    [ABCD 12  7 13]  [DABC 13 12 14]  [CDAB 14 17 15]  [BCDA 15 22 16]

    /* Round 2 */
    /*
     * Let [abcd k s i] denote the operation
     *   a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s).
     */
    [ABCD  1  5 17]  [DABC  6  9 18]  [CDAB 11 14 19]  [BCDA  0 20 20]
    [ABCD  5  5 21]  [DABC 10  9 22]  [CDAB 15 14 23]  [BCDA  4 20 24]
    [ABCD  9  5 25]  [DABC 14  9 26]  [CDAB  3 14 27]  [BCDA  8 20 28]
    [ABCD 13  5 29]  [DABC  2  9 30]  [CDAB  7 14 31]  [BCDA 12 20 32]

    /* Round 3 */
    /*
     * Let [abcd k s i] denote the operation
     *   a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s.
     */
    [ABCD  5  4 33]  [DABC  8 11 34]  [CDAB 11 16 35]  [BCDA 14 23 36]
    [ABCD  1  4 37]  [DABC  4 11 38]  [CDAB  7 16 39]  [BCDA 10 23 40]
    [ABCD 13  4 41]  [DABC  0 11 42]  [CDAB  3 16 43]  [BCDA  6 23 44]
    [ABCD  9  4 45]  [DABC 12 11 46]  [CDAB 15 16 47]  [BCDA  2 23 48]

    /* Round 4 */
    /*
     * Let [abcd k s i] denote the operation
     *   a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s).
     */
    [ABCD  0  6 49]  [DABC  7 10 50]  [CDAB 14 15 51]  [BCDA  5 21 52]
    [ABCD 12  6 53]  [DABC  3 10 54]  [CDAB 10 15 55]  [BCDA  1 21 56]
    [ABCD  8  6 57]  [DABC 15 10 58]  [CDAB  6 15 59]  [BCDA 13 21 58]
    [ABCD  4  6 61]  [DABC 11 10 62]  [CDAB  2 15 63]  [BCDA  9 21 64]

    /*
     * Then perform the following additions. (That is increment each
     * of the four registers by the value it had before this block
     * was started.)
     */
     A = A + AA
     B = B + BB
     C = C + CC
     D = D + DD
}

依照低位优先的原则输出A、B、C和D

测试数据
md5("") = d41d8cd98f00b204e9800998ecf8427e
md5("a") = 0cc175b9c0f1b6a831c399e269772661
md5("abc") = 900150983cd24fb0d6963f7d28e17f72
md5("message digest") = f96b697d7cb7938d525a2f31aaf161d0
md5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
md5("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789") =
        d174ab98d277d9f5a5611c2c9f419d9f
md5("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =
        57edf4a22be3c955ac49da2e2107b67a

Java源代码

Related Posts

People who read this, also read...

如何编写完美的equals方法

Posted by dohkoos on September 8th, 2005 (333 views)

Java 语言规范要求equals 方法具有下面的特点:
1. 自反性:对于任意非空引用x,x.equals(x) 应返回true;
2. 对称性:对于任意引用x、y,当且仅当y.equals(x) 返回true 时,x.equals(y) 返回true;
3. 传递性:对于任意引用x、y、z,如果x.equals(y) 返回true 且y.equals(z) 也返回true,那么x.equals(z) 应返回true;
4. 一致性:如果x 和y 引用的对象没有改变,那么对x.equals(y) 的重复调用应返回同一结果;
5. 对任意非空引用x,x.equals(null) 应返回false。

下面是编写完美的equals 方法的建议:
1. 测试this 和other 是否是同一个对象
if (this == other) return true;
2. 测试other 是否为null,如果是就返回false
if (other == null) return false;
3. 测试this 和other 是否属于同一个类
if (getClass() != other.getClass()) return false;
4. 将other 的类型转换为你的类所属类型
ClassName obj = (ClassName)other;
5. 最后,比较所有的字段。使用==比较基本类型字段,使用equals比较对象类型字段

如果你希望比较base class 对象和derived class 对象,该怎么做呢?你也许会考虑在equals 方法中使用instanceof,但我认为这是错误的想法!base class对象和derived class对象是不可能相等的,它们只可能相似。因此期望通过equals 方法来比较base class 对象和derived class 对象是没有道理的。因此derived class 应该总是实现新的equals 方法,而不是继承base class 的equals 方法。

Related Posts

People who read this, also read...

Java乱码问题分析

Posted by dohkoos on July 31st, 2005 (711 views)

java采用unicode编码来处理字符。Java程序无论是从/往文件系统以字符流读/写文件,还是往URL连接写HTML信息,或从URL连接读取参数值,都会有字符编码的转换。编/解码过程如下图:
java-encoding-1.jpg

乱码产生的根本原因是由于编码和解码采用的不是同一种码(GBK,UTF-8,ISO8859-1)。

字符串(String或char[])"123你"经过编码后的字节流(unicode字节流)为31 00 32 00 33 00 60 4f。如果你用new String("123你".getBytes("iso8859-1"), "gbk")来创建这个字符串时就会产生乱码。
java-encoding-2.jpg

因为getBytes("iso8859-1")取得的是"123你"经过iso8859-1编码后的字节流31 32 33 3f (iso8859-1字节流),
而在用new String(bytes, "gbk")构造字符串时java会将iso8859-1字节流(31 32 33 3f)当作是unicode字节流(因为java是采用unicode来处理字符的,所以它把字节流统统当作是unicode字节流来处理),因此31 32 33 3f也被它看成了是unicode字节流。而unicode字节流(31 32 33 3f)经过gbk编码后当然是123?了。于是,乱码产生了。下面的是一个测试程序:

public class Charset {

    public static void main(String[] args) {
        String str = "123你";

        try {
            byte[] unicode = str.getBytes("unicode");
            for (int i = 0; i < unicode.length; i++) {
                System.out.print(Integer.toHexString(unicode[i]) + " ");
            }
            System.out.println(new String(unicode));    // ? 1 2 3 30`

            byte[] utf8 = str.getBytes("utf-8");
            for (int i = 0; i < utf8.length; i++) {
                System.out.print(Integer.toHexString((utf8[i])) + " ");
            }
            System.out.println(new String(utf8));    // 123浣?

            byte[] iso88591 = str.getBytes("iso8859-1");
            for (int i = 0; i < iso88591.length; i++) {
                System.out.print(Integer.toHexString((iso88591[i])) + " ");
            }
            System.out.println(new String(iso88591));    // 123?

            byte[] gbk = str.getBytes("gbk");
            for (int i = 0; i < gbk.length; i++) {
                System.out.print(Integer.toHexString((gbk[i])) + " ");
            }
            System.out.println(new String(gbk));    // 123你

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Related Posts

People who read this, also read...

在Eclipse-3.x.x 中使用ssh2 来访问gro.clinux.org 的cvs 服务器

Posted by dohkoos on July 8th, 2005 (545 views)

1、在Eclipse-3.x.x 中生成公钥和私钥
打开Eclipsev-3.x.x,进入Window > Preferences > Team > CVS > SSH2 Connection Method > Key Management,点击Generate RSA Key... 然后填写Passphrase 和Confirm Passphrase,
接着点击Save Private Key... 保存公钥和私钥(公钥和私钥文件保存在C:Documents and Settingsusernamessh 下,id_rsa 是私钥文件,id_rsa.pub 是公钥文件)。

2、将公钥上传至gro.clinux.org 服务器
登陆gro 服务器,进入[帐号维护],在页面底部你可以看到如下信息:

Shell帐号信息

Shell box:
CVS/SSH 共享认证Key:0 [编辑Keys]

点击[Edit Keys],然后把刚才生成的文件id_rsa.pub 中的内容粘贴到文本框中(看看是不是符合它上面的要求,千万要仔细看看),如果没有问题的话,就更新吧。
大约六个小时后cron 会自动更新,在服务器上你的目录下会自动添加目录/.ssh/,目录里包含了名为authorized_keys2 的文件,你的公钥就保存在这里。

3、在Eclipse-3.x.x 中建立CVS 连接
进入CVS Repository Exploring Perspective,进入New > Repository Location,填入以下内容:
Host:cvs.unixname.gro.clinux.org
Repository Path:/cvsroot/unixname
User:你在gro.clinux.org 上注册的帐户
Password:先前保存公钥和私钥时输入的Passphrase
Connection Type:extssh

点击Finish。如果你是第一次登录的话,将会弹出一个对话框,不用看那么仔细,直接点击OK 就好了。

Related Posts

People who read this, also read...

如何生成可执行的jar 文件

Posted by dohkoos on June 22nd, 2005 (606 views)

首先用jar cvf executable.jar *.class命令生成jar文件,然后编辑jar文件中META-INF文件夹下的MAINFEST文件。在其尾部加上main-class: main-class-name就可以让jar文件变成可以执行的了。

Related Posts

People who read this, also read...