xml格式须知

着重介绍与项目使用相关的xml知识

常见节点

  • 虽然xml节点是可以带属性的,但是我们项目中使用的通常没有带属性。
  • 常见节点有带子节点的节点(非内容节点)、带文本的节点。
  • 协议中表示可选的节点,通常是指文本为空的节点,如,而不能不带。

节点的顺序

  • 非列表节点,通常是不需要限定顺序的,但不排除有一些SB系统处理不了,所以最好按协议顺序来。
  • 带列表节点,最好保证子节点按业务要求的顺序排列,即使有标示顺序的子节点。

命名空间

  • 通常是有命名空间的话,所有节点都会带,不带通常是不对的。
  • 命名空间是通过xmlns:n0=”http://www.gmcc.net/ngcrm/” 来进行别名的,理论上应该认URI而不是别名,但实际使用却常用别名来识别。
  • 解析时可以考虑忽略命名空间处理,例如xpath,可以用doc.selectNodes(“//*[local-name()=’Service’]”)找到Service节点。

编码格式

  • xml是一种自编码文本,是由第一行决定整个xml的编码格式。
  • 上面只是规范,但像http一样,总有系统不是这么玩的,需要双方协商和确认。
  • 有的xml就是没有第一行的编码描述,更是应该协商确认。

合法的值

  • 除了内置xml文本作为文本节点,或者明显可能特殊字符的文本(如密码,各种属性用某符号拼接),大多数情况不需要关注。
  • 和html一样,某些特殊字符是需要转移的,见下面的转义列表。
  • 如果不想转义,需要用<![CDATA[]]>括起来,需要注意的是,里边的内容需要保持不转义。
  • <![CDATA[]]>里边的内容是原封不动获取的,即使内容带了回车、空格,如果需要对内容二次处理的话,需要注意某些留空可能导致无法处理。
  • <![CDATA[]]>不能嵌套两次,只能用转义来规避。

常见的特殊字符

lt &lt; <(小于号)
gt &gt; >(大于号)
amp &  &(“and”符)
apos ' '(撇号或单引号)
quot " "(双引号)

2014读书笔记

ruby元编程

  • 作者Paolo Perrotta
  • 阅读于2014-04-22,大约5天
  • 适合有一定ryby/rails开发经验的同学,对认识ruby魔法很有帮助

最近看这本书,主要是跟别人谈起这本书,一时兴起又阅读一下,主要是复习复习。毕竟自己搞ruby/rails有好几个年头了,虽然现在主要以java为主,但是ruby还是我工作以外的首选。说回这本书,是系统介绍ruby魔法的魔法书,如果想了解一下那些神奇的库是怎么实现的,又或者想用ruby构建自己的DSL,这本书可以给你足够的知识点。放马去吧!

CSS实战手册

  • 作者David Sawyer McFarland
  • 阅读于2014-04-18,大约7天
  • 适合想系统学习点CSS的童鞋,书籍出版了有些年头,不过的确经典,强力推荐

最近在弄个网站,苦恼bootstrap水太深,想调整难度大,所以看看书找找感觉。 这个The Missing Manual系列还是比较出名的,特别是这本CSS实战手册,难度也不是大,但讲解得很系统化。 其实,这本书还出了新版,专注CSS3了。可惜的是,现在只有英文版,不是很适合我这种CSS初哥,不过下一阶段打算看看。 那么多概念,还是浮云呀,终究还是看基础扎不扎实。

Go语言编程

  • 作者许式伟、吕桂华(七牛云存储团队)
  • 阅读于2014-04-09,大约3天
  • 适合对Go语言刚兴趣、想一窥究竟的童鞋,内容一般、比较浅显,不是很适应英文的童鞋可以优先考虑

看这本书主要是冲着七牛云存储团队的名气去的,毕竟他们是国内第一个吃螃蟹的,据说90%以上的代码都是GO实现的。 另外,我最近用Go在做点东西,看从中看到对Go实践方式的解读。阅读之后,感觉内容偏浅,不如看官方文档。 不过里边有些例子还不错,适合有其他语言经验的童鞋阅读,可以通过对比其他语言的代码实现,加深印象。 总结一下,这书适合快速浏览,剩下的还是老老实实编程吧。

代码的未来

  • 作者松本行弘(Ruby之父)
  • 阅读于2014-04-06,大约3天
  • 适合轻松阅读、扩展知识面,不深入,可以读读

这本书和作者另外一本书”松本行弘的程式世界”感觉有些类似,都是以发表在某专栏的文章集合为主。 可能是由于篇幅问题,大多都是泛泛而谈,点到即止。阅读起来没有什么压力,如果有需要深入的话,就得自己去找资料了。 总体来说,我对这类书还是挺感兴趣的,可以挑选一些自己感兴趣的话题进行阅读,有助于开阔视野。

websphere+spring+jndi数据源配置

配置的步骤在下面简要说明:

  1. 增加基于spring的jndi数据源配置
  2. 在websphere上增加数据源配置
  3. 链接iiop地址

下面进行详细描述。

  • 基于spring的jndi配置文件

注意:如果是第二种方式,可以忽略第三部分”链接iiop地址”

第一种方式:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

+	<bean id="GlobalConfig"
+		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+		<property name="systemPropertiesMode">
+			<value>1</value>
+		</property>
+		<property name="searchSystemEnvironment">
+			<value>true</value>
+		</property>
+		<property name="ignoreUnresolvablePlaceholders">
+			<value>true</value>
+		</property>
+	</bean>

+	 <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
	 <tx:annotation-driven transaction-manager="jtaTransactionManager"  proxy-target-class="true" /> 
	 <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/> 

+	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
+		<property name="jndiName"><value>XXX</value></property>
+		<property name="resourceRef"><value>true</value></property>
+		<property name="jndiEnvironment"><props><prop key="java.naming.provider.url">${java_naming_provider_url}</prop></props></property>
+	</bean>  
</beans>
  • 在websphere上增加数据源配置

效果图

  • 链接iiop地址

在server的java进程定义里边配置jvm参数: -Djava_naming_provider_url=iiop://localhost:port/,另外,修改启动参数需要重启server才能生效。

效果图

其中每个server的port都是不一样的,具体的端口通过Application servers - serverX - Communications - Ports上查看,如下图:

效果图

jdk7编译的bug记录

过程

昨天在编译某个android项目的时候,发现dex打包出错。 后来检查发现编译生成的SplashScreenActivity$1.class格式出错。

后来经常测试,发现jdk6正常,jdk7不正常,包括最新的u51版本。

bug分析

相关的代码如下:

private void checkUpdate() {
    if (UpgradeInfo.isApkLocalExist(SplashScreenActivity.this, UpgradeInfo.getFilePath())) {
        updateInstall();
    } else if (AUTO_UPDATE) {
        initDialog();
        mUpgradeInfo = new UpgradeInfo();
        mGetVersionConfig = new GetVersionConfig(SplashScreenActivity.this,
                new CheckUpgradeHandler(), mUpgradeInfo, getUpgradeRequestParam());
        mGetVersionConfig.start();
    } else {
        // /没版本且不升级
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent i = new Intent(SplashScreenActivity.this, LoginActivity.class);
                startActivity(i);
                finish();
            }
        }, LOADING_TIME);
    }
}

正常情况下,Runnable匿名类会生成一个class,但是这里的AUTO_UPDATE被定义为static final,并且设置为true。 在这种情况下,jdk会优化掉后面的分支,但是jdk6不会生成class,但是jdk7会生成一个格式有误的class,反编译后如下:

class SplashScreenActivity$1
  implements Runnable
{
  public void run();
}

所以,在进行dex打包的时候,就会检测到不规范的class,进行报错。 我想,如果在web应用上的话,应该是不会有问题的,因为这个类没有机会被使用。

后来,我发现在其他項目中也有类似写法,但是编译不会有问题。如下所示:

if (UpgradeInfo.isApkLocalExist(LogoActivity.this,UpgradeInfo.getFilePath())) {
    // /检测到有新版本可以安装
    String msg = getString(R.string.dialog_check_version);
    DialogUtil.dialogForTwoButton(... , new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //..
                }
            });
} else if (AUTO_UPDATE) {
    // ....
} else {
    ///没版本且不升级
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            Intent i = new Intent(LogoActivity.this, OperatorLoginActivity.class);
            startActivity(i);
            finish();
        }
    }, LOADING_TIME);
}

故猜测,这个bug只出现在第一个不被使用匿名类身上(因为这个类前面还有个OnClickListener的匿名类)。 经过测试,发现也的确是存在这样的情况。

规避方式

乖乖使用jdk6,不要使用jdk7。

android+maven问题记录

参考材料

  • https://code.google.com/p/maven-android-plugin/wiki/GettingStarted
  • http://books.sonatype.com/mvnref-book/reference/android-dev.html
  • http://www.ikoding.com/build-android-project-with-maven/
  • https://github.com/mosabua/maven-android-sdk-deployer
  • http://rgladwell.github.io/m2e-android/
  • http://wiki.eclipse.org/M2E_plugin_execution_not_covered

前提条件

  • JDK 1.6+
  • Android SDK r21.1+
  • Maven 3.1.1+
  • Set environment variable ANDROID_HOME to the path of your installed Android SDK and add $ANDROID_HOME/tools as well as $ANDROID_HOME/platform-tools to your $PATH. (or on Windows %ANDROID_HOME%\tools and %ANDROID_HOME%\platform-tools)

特别注意maven的版本号

maven配置

请设置环境变量M2_HOME,并把settings.xml放到M2_HOME/conf中去。

eclipse配置

对于eclipse来说,除了要maven插件,还需要m2e-android插件。

dependency中support-v4的版本号只有很旧r7

其实除了support-v4,像android也有类似的问题。有一种解决方案是采用maven-android-sdk-deployer。 我测试过之后,发现这个解决方案虽然可行,但实际上比较麻烦。我直接在公司内的代理仓库上安装了新版本的。

Plugin execution not covered by lifecycle configuration

pom.xml很可能出现下面的错误提示:

Plugin execution not covered by lifecycle configuration: 
 com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.8.2:consume-aar 
 (execution: default-consume-aar, phase: compile)

虽然不影响编译,但是很怪,可以通过下面的配置进行排除:

<pluginManagement>
	<plugins>
		<plugin>
			<groupId>org.eclipse.m2e</groupId>
			<artifactId>lifecycle-mapping</artifactId>
			<version>1.0.0</version>
			<configuration>
				<lifecycleMappingMetadata>
					<pluginExecutions>
						<pluginExecution>
							<pluginExecutionFilter>
								<groupId>com.jayway.maven.plugins.android.generation2</groupId>
								<artifactId>android-maven-plugin</artifactId>
								<versionRange>3.8.2</versionRange>
								<goals>
									<goal>manifest-update</goal>
									<goal>generate-sources</goal>
									<goal>proguard</goal>
									<goal>consume-aar</goal>
								</goals>
							</pluginExecutionFilter>
							<action>
								<ignore />
							</action>
						</pluginExecution>
					</pluginExecutions>
				</lifecycleMappingMetadata>
			</configuration>
		</plugin>
	</plugins>
</pluginManagement>

可以参考M2E_plugin_execution_not_covered

OutOfMemory或创建不了虚拟机

有时候会出现内存溢出或创建不了虚拟机的错误。考虑设置内存大小

<plugin>
	<groupId>com.jayway.maven.plugins.android.generation2</groupId>
	<artifactId>android-maven-plugin</artifactId>
	<configuration>
		<dex>
			<jvmArguments>
				<jvmArgument>-Xms256m</jvmArgument>
				<jvmArgument>-Xmx512m</jvmArgument>
			</jvmArguments>
		</dex>
	</configuration>
</plugin>

出现maven打包太慢的情况

经过测量,在dex成classes.dex的阶段比较慢,dx工具有提供一些参数进行优化.

  • incremental 增量打包,开发阶段可以开启,可以比较明显的缩短打包时间
  • optimize 是否优化classes.dex,开发阶段可以关闭
<dex>
  <incremental>true</incremental>
  <optimize>false</optimize>
</dex>

libpng error: Not a PNG file

如果直接把jpg格式换个名字,变成png,编译会报下面的错误,导致后面编译的.9图片也出问题(混淆问题的原因)

[INFO] libpng error: Not a PNG file
[INFO] ERROR: Failure processing PNG image E:\projects\G3ESOP\ESOP-Hubei2\res\drawable-xhdpi\more_about_pic1.png

‘build.plugins.plugin.version’ is missing

[WARN] 'build.plugins.plugin.version' is missing fororg.apache.maven.plugins:maven.compiler.plugin
It is highly recommended to fix these problems because they threaten the stability of your build.
For this reason, future Maven versions might no longer support building such malformed projects.

很简单,给maven.compiler.plugin这个插件添加version属性。 其实所有引用的插件都应该指定版本,不然都会有类似的提示。

关于编码

对于源码的编码格式和编译版本,应该进行指定:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.1</version>
	<configuration>
		<source>1.6</source>
		<target>1.6</target>
		<encoding>UTF8</encoding>
	</configuration>
</plugin>

对于资源处理的话,可能出现下面的提示:

[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!

这个应该设置成UTF-8,如下所示:

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>

maven-jarsigner-plugin对带特殊字符的口令的处理

这个弄了好久,最后发现得把密码用引用引起来。切记切记。

后来,发现在linux这样又不能支持。所以只能用profile解决。

部分代码在jdk7中编译后dex出错

参考jdk7编译的bug记录,暂时只用jdk6编译

jdk6不支持android-19的proguard

原因是android-19的API实现了一些jdk7的特性,在proguard会找不到这些api。 由于和上一个问题有些冲突,暂时不考虑proguard。后续考虑考虑上jdk7。

如何添加.so支持

例如下面的百度地图SDK,需要加入一个so文件,在百度SDK里边是这样调用的:

System.loadLibrary("BaiduMapSDK_v2_3_1");

如果要用maven集成的话,可以用下面的配置(已经部署到代理仓库):

<dependency>
	<groupId>com.baidu</groupId>
	<artifactId>libBaiduMapSDK_v2_3_1</artifactId>
	<version>2.3.1</version>
	<classifier>armeabi</classifier>
	<scope>runtime</scope>
	<type>so</type>
</dependency>

如何转换成eclipse项目

项目目录中只有pom.xml,如果要导入eclipse的话,可以考虑使用下面的命令生成.project和.classpath文件

mvn eclipse:eclipse

生成之后可能会有M2_REPO变量找不到的问题,可以在eclipse中通过window>Preferences>Maven>Installations>Add进行添加maven安装位置。

否则的话,可以按以下方法添加M2_REPO: Window > Preferences > Java > Build Path > Classpath Variables 新增一个M2_REPO变量指向你maven本地仓库。

常用命令

mvn clean package
打包,但不部署。

mvn clean install
打包,部署并运行。

mvn clean package android:redeploy android:run
这个命令通常用于手机上已经安装了要部署的应用,但签名不同,所以我们打包的同时使用redeploy命令将现有应用删除并重新部署,最后使用run命令运行应用。

mvn android:redeploy android:run
不打包,将已生成的包重新部署并运行。

mvn android:deploy android:run
部署并运行已生成的包,与redeploy不同的是,deploy不会删除已有部署和应用数据