Posts Tagged ‘java’

让JAXB生成序列化的类

November 20th, 2009

默认jaxb生成的类是没有序列化的,但是我们经常需要他们序列化。jaxb ri有生成序列化的类的这样的功能,但由于这不属于标准的功能,所以需要手动的开启。开启的方法是在用来生成java类的xml schema文件头添加如下内容:

<annotation>
	<appinfo>
		<jaxb:globalBindings generateIsSetMethod="true">
			<xjc:serializable uid="1"/>
		</jaxb:globalBindings>
	</appinfo>
</annotation>

另外,在使用jaxb的 xjc 编译器时,要加上 -extension 的参数。

  • Share/Bookmark

可恶的乱码问题

November 12th, 2009

在打印单据的时候,有两个汉字“玥”和“芃”,始终显示为“?”,这一问题困扰了业务人员一段时间了。以前没有空,就没有投入精力去查原因,上次得了空,终于把这个问题解决掉了。

这个乱码的汉字从哪里来的呢?首先是业务人员通过一个遗留的PHP应用,输入到一个mysql 4数据库中,然后我们的java程序从这个mysql 4中读取,再写入到新的mysql5的数据库中,最后通过java程序生成html在用户的浏览器里显示,结果就看到了这两个汉字乱码。那么这个问题如何解决呢?

只有两个汉字乱码,而不是所有的汉字都乱码,所以我们的程序一定使用了一种包含汉字较少的字符集,而这个出错的汉字恰好不在此字符集中,否则,就应当是大部分汉字乱码,而不仅仅是这两个了。很自然的就让人想到了 gb2312, gbk, gb18030, utf8等字符集之间的关系。其中gb2312中只有六千多个汉字,其它几个字符集支持的汉字数相差不多,我们程序一定是在该使用gbk, gb18030或utf8的地方使用了含有汉字较少的gb2312。

经查阅相关文档,果然发现那两个汉字都不在gb2312里,而在gbk, utf8字符集里。我们的mysql5使用的utf8字符集,生成的html也是utf8编码,如果mysql5中的汉字是正确的话,那么就应该能正常显示,因此,数据进入mysql5的时候就应该出错了。java程序在连接mysql5的时候,在jdbc连接中设置了utf8,所以如果从mysql4数据库中读取出来的是正确的,就不应该写入出问题,因此数据在mysql4中可能就错了,也可能是从mysql4中读取的时候出错了。php的兄弟们说mysql的数据库是gb2312字符集的,mysql的配置文件里也是这么配置的。如果果真如此,那么这个两个汉字在mysql4的数据库中就应该不正常了,所有的程序读出之后都应该是乱码,可是php的录入程序那边确实是能正常显示的。我断定这个数据库里放的实际上是gbk字符集的汉字。选用和mysql4相对应的mysql j connector 3.14,并在jdbc连接url里设置了characterEncoding=gbk,读出来的仍旧不正确!查阅了mysql j connector的文档,原来3 版本的mysql connector根本就不支持characterEncoding这个选项。看来只能修改mysql的配置文件了。修改之后,果然这两个汉字可以正常显示了。

如果计算机是中国人发明的,那么计算机也许一开始就得支持汉字,就再也没有乱码的问题。如果世界上只有一种汉字的编码方案,也不会有乱码的问题,可惜汉字偏偏有很多中编码方案。所以在我们的程序中,一定得搞清楚,我们的汉字数据来自于哪里,使用的哪种编码,每个环节都得配置得当,否则就会有乱码问题。

对于一般的web应用来说,需要关心编码的地方有:
1,数据库以什么编码存储数据
2,程序使用什么字符集连接数据库
3,程序内部运行时使用什么字符集
4,程序源码使用什么字符集
5,生成的html文件是什么字符集
6,程序告知浏览器的字符集
如果以上这些地方的字符集有配置不正确的地方,往往就会乱码。

如果可以的话,最好在所有的地方都使用一种编码,比如对于java应用来说,在所有的地方都使用utf8编码,就可以解决问题。需要注意的是,在windows环境下,默认的文件编码是gb18030的,而不是utf8。

另外,极端鄙视故意使用生僻字火星文的脑残族!!

  • Share/Bookmark

漫谈PHP和Java

September 27th, 2009

我为公司内部交流而写的PPT,谈论PHP和JAVA相关的话题。在这里查看:

漫谈PHP和Java

  • Share/Bookmark

ActiveMQ使用经验

June 18th, 2009

ActiveMQ是apache的一个开源JMS服务器,不仅具备标准JMS的功能,还有很多额外的功能。公司里引入ActiveMQ后,ActiveMQ成里我们公司业务系统中最重要的一个环节。所有应用都通过jms集成,如果ActiveMQ出了故障,整个系统就瘫痪了。因此,头对ActiveMQ的性能,可靠性,以及如何正确使用,是非常的关心的,而我就被指派来做关于ActiveMQ的调研,本文对此做了些总结。

1 使用jms需要注意的问题

一下所述的问题,不仅是对ActiveMQ,对于其他的JMS也一样有效。

1.1 不要频繁的建立和关闭连接

JMS使用长连接方式,一个程序,只要和JMS服务器保持一个连接就可以了,不要频繁的建立和关闭连接。频繁的建立和关闭连接,对程序的性能影响还是很大的。这一点和jdbc还是不太一样的。

1.2 Connection的start()和stop()方法代价很高

JMS的Connection的start()和stop()方法代价很高,不能经常调用。我们试用的时候,写了个jms的connection pool,每次将connection取出pool时调用start()方法,归还时调用stop()方法,然而后来用jprofiler发现,一般的cpu时间都耗在了这两个方法上。

1.3 start()后才能收消息

Connection的start()方法调用后,才能收到jms消息。如果不调用这个方法,能发出消息,但是一直收不到消息。不知道其它的jms服务器也是这样。

1.4 显示关闭Session

如果忘记了最后关闭Connection或Session对象,都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了Connection,由这个Connection生成的Session也会被自动关闭,结果并非如此,Session并没有关闭,导致内存泄漏。所以一定要显示的关闭Connection和Session。

1.5 对Session做对象池

对Session做对象池,而不是Connection。Session也是昂贵的对象,每次使用都新建和关闭,代价也非常高。而且后来我们发现,原来Connection是线程安全的,而Session不是,所以后来改成了对Session做对象池,而只保留一个Connection。

2 集群

ActiveMQ有强大而灵活的集群功能,但是使用起来还是会有很多陷阱。

2.1 broker cluster和 master-slave

ActiveMQ可以做broker的集群,也可以做master-slave方式的集群。前者能在多个broker之前fail-over和load-balance,但是在某个节点出故障时,可能导致消息丢失;而后者能实时备份消息,和fail-over,但是不能load-balance。broker cluser的方式,在一个broker上发送的消息可以在其它的broker上收到。当一个broker失效时,客户端可以自动的转到别的broker上运行,多个broker可以同时提供服务,但是消息只存储在一个broker上,如果那个broker失效了,那么客户端直到它重新启动后才能收到该broker上的消息,假如很不幸,那个broker的存储介质坏了,那么消息就丢失掉了。
Master-slave方式中,只有master提供服务,slave只是实时的备份master的数据,所以消息不会丢失。当master失效时,slave会自动升为master,客户端会自动转到slave上工作,所以能fail-over。由于只有master提供服务,所以不能将负载分到多个broker上。
其实单个broker的性能已经是相当的惊人了,在我们公司的机器上能达到每秒收发4000个消息,没个消息4K字节这样的速度,足够公司目前的需要了,而公司并不希望丢失任何数据,所以我们选择使用master-slave模式。

2.2 多种master-slave模式

master-slave也有多种实现方式。它们的不同只是在共享数据和锁机制上。

2.2.1 Pure master-slave

Pure master-slave,显示的在配置文件中指定一个broker做为另一个broker的slave。运行时,slave同过网络自动从master出复制数据,同时在和master失去连接时自动升级为master。当master失效,slave成为master后,如果要让原先的master重新投入运行,需要停掉运行中的slave(现在升级为master了),手动复制slave中的数据到master中。再重新启动master和slave。这种方式最简单,效率也不错,但是只能有两台做集群,只能fail-over一次,而且需要停机回复master-slave结构。

2.2.2 JDBC master-slave

这种方式不需要特殊的配置,只要让所有的节点都把数据存储到同一个数据库中。先拿到数据库表的锁的节点成为master,一旦它失效了,其它的节点获得锁,就可以成为master。因为数据通过数据库共享,放在一个地方,不需要停机恢复master-slave。这种方式,需要额外的数据库服务器,如果数据库失效了,那么就全失效了,而且速度不是很快。我们在用mysql测试时,并没有成功,master失效后,其他的节点始终没有升级成slave,可能是数据库配置的问题。

2.2.3 Share file master-slave

这种方式类似于前者,也不需要特别的配置,只是通过共享文件系统来共享数据,靠文件锁实现只有一台成为master。共享文件系统的方式有很多,我们测试了nfs v4 (v3有bug,不行), 最终在稳定性,效率等方面不是很满意,可能是通过网络太慢了。

测试过众多master-slave模式后发现,pure方式管理起来麻烦,jdbc方式成本高,效率低,share file方式需要高性能的共享文件,都有缺点。鉴于单台activeMQ很可靠,而我们的基础平台组愿意用硬件备份,最终还是决定不用master-slave了,也不用broker cluster,就用单台,通过硬件冗余保证数据不会丢失,并找另外一台刀片机做冷备,在主服务器失效时顶替。

  • Share/Bookmark