分类存档: game-game - 第4页

64k大赛作品

请参考以下两个网址:

http://breakpoint.untergrund.net

http://www.scene.org

voltdb安装及使用

1、下载voltdb后直接解压:

$ tar -zxvf LINUX-voltdb-ent-3.6.tar.gz

2、两点注意事项,切记切记:

1.1.

Disable Swapping

Swapping is an operating system feature that optimizes memory usage when running multiple processes. However, memory is a critical component of the VoltDB server process. Any contention for memory, including swapping, will have a very negative impact on performance and functionality.

We recommend using dedicated servers and disabling swapping when running the VoltDB database server process. Use the swapoff command to disable swapping on Linux systems. If swapping cannot be disabled for any reason, you can reduce the likelihood of VoltDB being swapped out by setting the kernel parameter vm.swappiness to zero.

voltdb是内存数据库,常驻内存非常重要,因此需要将交换分区(虚拟内存)完全关闭。可以使用swapoff命令关闭,如果无法使用swapoff命令,则将内核参数vm.swappiness修改为0。

1.2.

Turn off TCP segmentation offload and generic receive offload if cluster stability is a problem.

There is an issue where, under certain conditions, the use of TCP segmentation offload (TSO) and generic receive offload (GRO) can cause nodes to randomly drop out of a cluster. The symptoms of this problem are that nodes timeout — that is, the rest of the cluster thinks they have failed — although the node is still running and no other network issues (such as a network partition) are the cause.

Disabling TSO and GRO is recommended for any VoltDB clusters that experience such instability. The commands to disable offloading are the following, where N is replaced by the number of the ethernet card:

ethtool -K ethN tso off
ethtool -K ethN gro off

Note that these commands disable offloading temporarily. You must issue these commands every time the node reboots.

这个是使用集群时需要注意的事项。

3、如果是旧版本升级需要按以下顺序执行:

The process for upgrading VoltDB for a running database is as follows:

    Place the database in admin mode using the @Pause system procedure (or VoltDB Enterprise Manager).

    Perform a manual snapshot of the database (using @SnapShotSave).

    Shutdown the database (using @Shutdown).

    Upgrade VoltDB.

    Recompile the application catalog using the new version of VoltDB.

    Restart the database using the create option, the new catalog, and starting in admin mode (specified in the deployment file).

    Restore the snapshot created in Step #2 (using voltadmin restore).

    Return the database to normal operations (using voltadmin resume).

4、将voltdb添加至环境变量中.

JAVA_HOME=/opt/jdk1.7.0_40
VOLTDB_HOME=/opt/voltdb-3.5.0.1
PATH=$PATH:$HOME/bin:$JAVA_HOME/bin:$VOLTDB_HOME/bin

export JAVA_HOME VOLTDB_HOME PATH

5、以下开始学习使用简单的voltdb命令。

先创建一个指定目录:helloworld

定义表结构:

CREATE TABLE HELLOWORLD (
   HELLO VARCHAR(15),
   WORLD VARCHAR(15),
   DIALECT VARCHAR(15) NOT NULL,
   PRIMARY KEY (DIALECT)
);

decoder解码优化

decoder中需要使用byte[]接收数据并转为protobuf对象。

本来考虑的是使用netty自带的缓存功能或直接在每个decoder中分配一个byte[]。这时想起来了fastjson的作者提过使用的线程绑定的byte[]功能。

查找到源代码,摘出来用。也感谢fastjson的作者开源代码。

package cn.joylab.game.util;

import java.lang.ref.SoftReference;

/**
 * 提供线程绑定数组缓存功能。
 * 
 * 可以避免频繁创建byte数组,最大长度限制为128k,超过128k的数据不进行缓存。
 * 
 * 用例1:decoder.
 * 
 * @author ZhuKunqian
 * 
 */
public class ThreadLocalCache {
	private final static int BYTE_CACHE_INIT_SIZE = 1024;
	private final static int BYTE_CACHE_MAX_SIZE = 1024 * 128;
	private static final ThreadLocal<SoftReference<byte[]>> byteBufLocal = new ThreadLocal<SoftReference<byte[]>>();

	public static void clearCache() {
		byteBufLocal.set(null);
	}

	public static byte[] getBytes(int length) {
		SoftReference<byte[]> ref = byteBufLocal.get();
		if (ref == null) {
			return allocateBytes(length);
		}

		byte[] bytes = ref.get();
		if (bytes == null) {
			return allocateBytes(length);
		}
		if (bytes.length < length) {
			bytes = allocateBytes(length);
		}
		return bytes;
	}

	private static int getAllocateLength(int init, int max, int length) {
		int value = init;
		while (true) {
			if (value >= length) {
				return value;
			}
			value *= 2;
			if (value > max) {
				break;
			}
		}
		return length;
	}

	private static byte[] allocateBytes(int length) {
		int allocateLength = getAllocateLength(BYTE_CACHE_INIT_SIZE,
				BYTE_CACHE_MAX_SIZE, length);
		if (allocateLength <= BYTE_CACHE_MAX_SIZE) {
			byte[] bytes = new byte[allocateLength];
			byteBufLocal.set(new SoftReference<byte[]>(bytes));
			return bytes;
		}
		return new byte[length];
	}
}

 

db的选择

今天仔细看了下voltdb,全内存数据库。

在新项目选择上,主要考查了3个数据库mysql,mongodb,voltdb。

mysql就不需要多说了,传统的关系数据库,而且用了多年,也比较熟悉。

mongodb,nosql数据库,使用二进制json格式保存,支持sql语句。

voltdb,关系数据库,也可当做nosql数据库来用,全内存,支持sql语句。因为是全内存操作,所以速度是非常快的。

mysql,mangodb需要读写磁盘,所以相对要慢一些。但voltdb官方推荐是4G内存启动。虽然也可以1G内存启动起来,会有会有其它后果还不清楚。而且还有一个很恶心的问题,voltdb不像mysql那样或以多个database启动,一个voltdb实例,只是一个database。这还不算问题,如果要在一台机器上开启20个database,则无法像官方所说的那样,按4G内存分配。估计每个database只能分配1G。

但voltdb可以当作一个jar嵌入到工程中,这样可以避免线程中的数据传输,又是一个好处。

voltdb也提供了jdbc driver,因此新项目中可以尝试使用voltdb,如果发现有解决不了的问题,可以直接切换至mysql.

阿里开源中间件:druid Dubbo cobar

网站地址:

https://github.com/alibaba/druid/wiki/_pages

druid 阿里巴巴用的数据库连接池,根据作者的测试,比其它类型的数据库池要快上很多。而且自带监控页面,可以方便的分析sql。

Dubbo 是一个

 

mina开发中遇到问题

1、SO_REUSEADDR,允许多个server绑定到同一个端口上。

dbcp内存泄漏解决方案

tomcat 6.0.24以上版本关闭时报以下错误:

严重: The web application [/igame] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

这是因为dbcp的一个小小的内存泄漏,你可以无视它,也可以去解决它。

更多关于这个问题的讨论:

http://stackoverflow.com/questions/3320400/to-prevent-a-memory-leak-the-jdbc-driver-has-been-forcibly-unregistered

我采用的是改为使用tomcat jdbc pool。

tomcat也使用大篇幅来描述tomcat-jdbc比dbcp好的优点:

http://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html

注意:并不是所有的tomcat版本都包含了tomcat-jdbc.jar,如果发现tomcat_home/lib下没有这个包,自己手工添加上。可能mysql-connector包也需要手工加上。

另一种方法:手动注销driver:

实现ServletContextListener,在contextDestroyed添加:

Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
log.info(“deregister driver :” + driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
log.error(“deregister dirver error:”, e);
}
}

解决appfuse中的ava.lang.ClassNotFoundException: org.aspectj.weaver.BCException错误

解决方案:强制maven-eclipse-plugin为2.9版本。

注意:这种操作需要先执行  mvn eclipse:clean 来清除旧数据。

<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
</configuration>
<version>2.9</version>
</plugin>

 

异常信息如下:

 

ERROR [main] TestContextManager.prepareTestInstance(324) | Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@d6ef] to prepare test instance [org.haifi.service.GameBaseManagerTestCase@11f1520]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userManagerTx’: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/BCException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:605)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
… 24 more
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/BCException
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2404)
at java.lang.Class.getDeclaredConstructors(Class.java:1853)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:962)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:935)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
… 37 more
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.BCException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
… 50 more

游戏开发准备(三)--传输协议

google 的 protobuf 是最近非常火的将结构对象进行序列化及反序列化的工具,据google称,已经应用在了google非常多的内部项目上。

1、下载protobuf,protoc:

https://code.google.com/p/protobuf/downloads/detail?name=protobuf-2.4.1.tar.bz2&can=2&q=

https://code.google.com/p/protobuf/downloads/detail?name=protoc-2.4.1-win32.zip&can=2&q=

2、下载下来的protoc放在 protobuf/java/src目录下

3、在protobuf/java目录下修改pom.xml(仅windows下需要修改)

<exec executable=”../src/protoc”>

修改为:

<exec executable=”src\protoc.exe”>

4、执行:

mvn test

mvn install 安装至 maven repository

mvn package 可以打包成jar包,供单独使用

mvn install -P lite 生成lite版本,lite缺少描述及反射功能,但在手机平台上推荐使用

这里我也打包了jar包,用来学习时使用。

5、在eclipse中创建java工程,来学习一下protobuf的使用

建立addressbook.proto

option java_package = “com.example.tutorial”;

message Person {
required string name = 1;
required int32 id = 2;        // Unique ID number for this person.
optional string email = 3;

enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}

message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}

repeated PhoneNumber phone = 4;
}

// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}

执行:

protoc addressbook –java-out=.

使用方式:

Person p = Person.newBuilder().setName(“hello world”).setId(111)
.build();
System.out.println(p.toByteArray().length);

toByteArray()进行序列化,parseFrom()进行反序列化。

下面在maven中集成:

添加plugin:

<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir=”target/generated-sources” />
<exec executable=”protoc”>
<arg
value=”–java_out=target/generated-sources” />
<arg
value=”src/main/protobuf/test.proto” />
</exec>
</tasks>
<sourceRoot>
target/generated-sources
</sourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

添加dependency:

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.4.1</version>
</dependency>

里面有一个反射机制,需要查一下能起到什么作用

optimize_for 这个选项需要关注一下,如果开发手机网游,这个选项会有大用处。

option optimize_for = SPEED; // 默认

CODE_SIZE

LITE_RUNTIME //手机网游推荐使用这种

另外,需要检查一下protobuf的压缩。测试了一下,字符串好像并未压缩。

从smartfox上查找一下他们用的压缩工具,继续测试一下。

决定使用snappy算法。

https://github.com/dain/snappy

各种压缩算法在java平台上的测试结果。

实际测试后压缩效果不尽如人意,使用了deflate和snappy压缩算法,分别测试了小于20字节和120字节的压缩,只能压缩不到20%,初始怀疑protobuf的二进制已经充分优化过了,如果是这样的话,再消耗cpu进行压缩就没有必要了。但是也不排除测试的样本太少。可以等正式上线后,再回头进行压缩的测试。对了,snappy必须在jdk7下运行,因为用了到sun的非公开函数,所以需要注意一下是目标环境是否支持。

使用protobuf还有一个好处,可以避免使用java反射机制带来的效率降低。

游戏开发准备(二)--服务器端准备工作

新的游戏准备继续使用appfuse。

接触到的两款游戏没有放在web容器中执行,但我希望依旧保留web功能,在未来会有一些交互性及管理的功能使用web来实现。

而且mina也支持与tomcat整合。

OK。下面开始准备新的appfuse 2.0工程:

1、JDK 6+

2、mysql 5.5+(我使用的是mysql5.0,但我认为已经足够了,没有必要进行升级)

3、需要修改mail.properties,发送mail的功能随后我会修改掉,可以忽略这条。

4、Maven 3.0.4+,(另外还得准备好maven 2.x版本,full-source在3.x下无法执行通过)

下面开始生成项目文件:

1、mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-basic-struts-archetype -DarchetypeVersion=2.1.0 -DgroupId=org.haifi -DartifactId=igame -DarchetypeRepository=http://oss.sonatype.org/content/repositories/appfuse

2、进入igame目录,修改pom.xml,设置db连接,执行:mvn jetty:run-war

可以在浏览器访问:http://127.0.0.1:8080/

3、执行:mvn appfuse:full-source (这里需要maven 2.x来执行)

如果出现错误:

[FATAL] Non-resolvable parent POM: Could not find artifact org.appfuse:appfuse:p
om:2.2-SNAPSHOT and ‘parent.relativePath’ points at wrong local POM @ line 21, c
olumn 13

那就表示你用了maven 3.x。

添加包依赖,不知道为什么默认没有。缺少包可以去http://search.maven.org下载

<aspectj.version>1.6.9</aspectj.version>
<commons.beanutils.version>1.8.3</commons.beanutils.version>
<commons.collections.version>3.2.1</commons.collections.version>
<commons.dbcp.version>1.3</commons.dbcp.version>
<commons.lang.version>2.5</commons.lang.version>
<compass.version>2.2.0</compass.version>
<cxf.version>2.2.4</cxf.version>
<dwr.version>2.0.1</dwr.version>
<ehcache.version>2.2.0</ehcache.version>
<ehcache.web.version>2.0.2</ehcache.web.version>
<hibernate.annotations.version>3.6.0-SNAPSHOT</hibernate.annotations.version>
<hibernate.version>3.6.9.Final</hibernate.version>
<jpa.version>2.0.Beta2</jpa.version>
<javamail.version>1.4.1</javamail.version>
<jstl.version>1.1.2</jstl.version>
<log4j.version>1.2.16</log4j.version>
<sitemesh.version>2.4.2</sitemesh.version>
<slf4j.version>1.6.1</slf4j.version>
<spring.security.version>3.0.4.RELEASE</spring.security.version>
<struts.menu.version>2.4.3</struts.menu.version>
<urlrewrite.version>3.1.0</urlrewrite.version>
<velocity.version>1.4</velocity.version>

另外添加:

<repository>
<id>central</id>
<url>http://search.maven.org</url>
</repository>
<repository>
<id>appfuse</id>
<url>https://repository.sonatype.org/content/groups/public</url>
</repository>
<repository>
<id>springsource-repo</id>
<name>springsource repository</name>
<url>http://repo.springsource.org/release</url>
</repository>
<repository>
<id>repository.jboss.org-public</id>
<name>JBoss repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
</repository>

4、下载源码包:mvn dependency:sources

5、mvn org.apache.maven.plugins:maven-eclipse-plugin:2.6:eclipse

然后在eclipse中导入工程。

继续后续修改:

1、pom.xml中修改

<amp.genericCore>false</amp.genericCore>
<amp.fullSource>true</amp.fullSource>

2、properties语种文件中我们只保留 zh_EN,zh_TW,en及默认,其它删除。

删除test目录下的jdbc.properties,log4j.xml

3、我把整个工程的字符集设置为UTF8

或者更好的一种方式:

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>

4、web.xml中启用lazyloadfilter,gzipfilter暂时和xfire有冲突,暂时不启用。

5、优化 applicationContext-resources.xml中设置

<bean id=”dataSource”
class=”org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy”>
<property name=”targetDataSource” ref=”targetDataSource” />
</bean>

可以避免空事务去连数据库

6、修改applicationContext-dao.xml

添加:

hibernate.hbm2ddl.auto=update
hibernate.show_sql=false

7、添加mina支持

<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>${mina.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>${mina.version}</version>
</dependency>

因为mian打包格式是bundle,需要添加:

<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>

在spring中添加

<!– mina game server –>
<bean id=”trapHandler”
init-method=”start” />

<bean id=”snmpCodecFilter”
class=”org.apache.mina.filter.codec.ProtocolCodecFilter”>
<constructor-arg>
<bean
class=”org.apache.mina.filter.codec.textline.TextLineCodecFactory” />
</constructor-arg>
</bean>

<bean id=”loggingFilter”
class=”org.apache.mina.filter.logging.LoggingFilter” />

<!– The filter chain. –>
<bean id=”filterChainBuilder”
class=”org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder”>
<property name=”filters”>
<map>
<entry key=”loggingFilter” value-ref=”loggingFilter” />
<entry key=”codecFilter” value-ref=”snmpCodecFilter” />
</map>
</property>
</bean>
<bean
class=”org.springframework.beans.factory.config.CustomEditorConfigurer”>
<property name=”customEditors”>
<map>
<entry key=”java.net.SocketAddress”>
<bean
class=”org.apache.mina.integration.beans.InetSocketAddressEditor” />
</entry>
</map>
</property>
</bean>
<bean id=”ioAcceptor”
class=”org.apache.mina.transport.socket.nio.NioSocketAcceptor”
init-method=”bind” destroy-method=”unbind” lazy-init=”false”>
<property name=”defaultLocalAddress” value=”:8888″ />
<property name=”handler” ref=”trapHandler” />
<property name=”filterChainBuilder” ref=”filterChainBuilder” />
</bean>

8、创建测试样例类:

在src/test/java下建立

public class GameBaseManagerTestCase extends BaseManagerTestCase {

// 这里指定testcase读取的spring配置文件

protected String[] getConfigLocations() {
setAutowireMode(AUTOWIRE_BY_NAME);

return new String[] { “/applicationContext-resources.xml”,
“classpath:/applicationContext-dao.xml”,
“/applicationContext-service.xml”,
“classpath*:/**/applicationContext-event.xml”,
“classpath*:/**/applicationContext-ds.xml”,
“classpath*:/**/applicationContext.xml”,
“classpath*:/**/applicationContext-activemq.xml”,
“classpath*:/**/applicationContext-job.xml”,
“classpath*:/**/remoting-servlet.xml”, };
}

// 这里添加自己多增加的资源文件,可以让测试样例读取到
@Override
protected void onSetUp() throws Exception {
super.onSetUp();
//
// 使用LocalizedTextUtil可以读取到wgame中的资源文件
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources”);
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources_enum”);
LocalizedTextUtil.addDefaultResourceBundle(“ApplicationResources_log”);
LocalizedTextUtil
.addDefaultResourceBundle(“ApplicationResources_exception”);
// 初始化测试对象
if (initPlayers) {
initPlayers();
}
time = System.currentTimeMillis();
GameDynamicElement.skipTournament=true;
log.debug(“———————- start ” + getName()
+ ” ———————–“);

}

 

9、因为工程转为使用UTF-8编码,如果遇到如下错误“ 编码 GB18030 的不可映射字符”,在pom.xml中修改如下:

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>

10:为maven-javadoc添加额外的java源码目录:

<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/protobuf/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

或者用另一种方式:

<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<excludePackageNames>
org.haifi.webapp:org.haifi.dao:org.haifi.service:org.haifi.game.reflection:org.haifi.game.channel:org.haifi.game.compiler:org.haifi.game.mina
</excludePackageNames>
<sourcepath>${basedir}/src/main/java;${basedir}/src/main/protobuf/java</sourcepath>
</configuration>

直接指定源文件所在目录

11:添加spring http invoker支持:

定义applicationContext-remoting.xml文件:

<bean name=”/GameUserService”
class=”org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter”>
<property name=”service” ref=”localGameUserRemotingManager” />
<property name=”serviceInterface”
value=”org.haifi.game.service.GameUserRemotingManager” />
</bean>

<!– 定义为local,可以提供给测试样例调用 –>
<bean name=”localGameUserRemotingManager”
class=”org.haifi.game.service.impl.GameUserRemotingManagerImpl” />

web.xml中添加:

<!– 支持sprint http invoker –>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>namespace</param-name>
<param-value>applicationContext-remoting</param-value>
</init-param>
<!– default context config location:remoting-servlet.xml –>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/gr/*</url-pattern>
</servlet-mapping>

可是浪费了好几个小时怎么还不生效呢。原来是urlwrite搞的鬼:

urlrewrite中添加:

<rule>
<from>/gr/**</from>
<to>/gr/$1</to>
</rule>

好了,下面开始客户端进行调用:因为游戏中的url是不固定的,所以需要用代码生成client:

HttpInvokerProxyFactoryBean bean = new HttpInvokerProxyFactoryBean();
bean.setServiceUrl(“http://127.0.0.1:8080/gr/GameUserService”);
bean.setServiceInterface(GameUserRemotingManager.class);
bean.setHttpInvokerRequestExecutor(new CommonsHttpInvokerRequestExecutor());
bean.afterPropertiesSet();
GameUserRemotingManager obj = (GameUserRemotingManager) bean
.getObject();
log.info(obj);


Warning: Use of undefined constant XML - assumed 'XML' (this will throw an Error in a future version of PHP) in /opt/wordpress/wp-content/plugins/wp-syntaxhighlighter/wp-syntaxhighlighter.php on line 1048