28 9月 2011

好用的Java Date Library -- Joda Time

Java裡提供的Calendar 與 Date在實用上實在有許多不方便的地方,這點我想有異議的人應該不多,所以大部份的開發團隊都會有一些DateUtils來補足常用的日期操作。

例如像是
int getCurrentMonth(Calendar date); #Java Calendar的月份是從0開始....
boolean isBetween(Date begin, Date end);
boolean isBefore(Date source, Date target);
Calendar addDay(Calendar source, int days); #日期計算
String format(SimpleDateFormat sdf); #轉換日期格式

總歸一下大約是有下列幾種的需求

  1. 基本資訊的取得,例如年,月,日,星期幾等資訊
  2. 格式轉換,包換顯示日期字串的格式與反向將字串轉為日期物件
  3. 日期間的比較
  4. 日期計算,例如減個2天,加個1個月

自已寫也不是什麼困難的事,比起寫出ThreadSafe 的Collection算是小菜了。
但這兩天發現了一個Library -- Joda Time (http://joda-time.sourceforge.net/index.html),試用後覺得真的不錯!(好像有點後知後覺)
在jsr310沒有進入JDK前,我想Joda Time是個不錯的選擇。

用maven的朋友可以利用下列設定將joda time加入project裡
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.0</version>
</dependency>

再介紹Joda Time的用法

基本上Joda Time的DateTime就同於Java的Calendar,所以建立instance的方法也近於Calendar
DateTime dt = new DateTime();
DateTime dt = new DateTime(2011, 9, 11, 12, 0, 0, 0);

基本資訊就以get的方式來取得
int month = dt.getMonthOfYear(); #這個月份比較符合一般的習慣
int year = dt.getYear();

日期的推算,就用plus(), minus()來操作,
dt.plusMonths(2);
dt.minusDays(1);

也可用Period或Duration的方式來做。
dt.plus(Duration.standardDays(1));
dt.minus(Period.months(2));

日期的比較就以isXXX()來操作
dt.isBefore(target);
dt.isAfter(target);

格式的轉換就以dt.toString(DateTimeFormatter);

順帶一提,joda time還提供了Hibernate與Jsp tag的支援,整體上算是相當方便的工具程式了。

 

 

 

26 7月 2011

Struts2 處理404錯誤的方法

一個Member問起這個問題,我覺得很不錯。

Error Code 404 這個問題說大不大,不過是使用者敲錯了URL,又不是Error Code 500代表我們的系統出現錯誤,何況使用者要敲什麼,我們哪管得著?我想這也沒錯啦,如果我在Google Map敲個'我家',然後還希望它給我什麼好看的是不是有點超過?(也許會出現全家便利商店?)

在Struts2中,一般要解決的404URL大約是兩類,一類是struts2 的.action,另一類就是一般的resource,像jpg、js等

第一類Action的方式很容易,在struts.xml中設定一個default的package,然後用個default-action-ref就可以解決

	<package name="default" extends="struts-default">
		<default-action-ref name="index"/>
		<action name="index">
			<result>/index.jsp</result>
		</action>
	</package>

第二類非Action的話就要在xml中加上error-page的設定

	<error-page>
		<error-code>404</error-code>
		<location>/rootAction.action</location>
	</error-page>
這類的處理要注意的是,如果是直接導到jsp或html就不用在意,但若是想導到一個action的話,請注意你的struts action filter,是不是有加上error 的dispatcher。
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
		<!-- <init-param> <param-name>actionPackages</param-name> <param-value>com.mycompany.myapp.actions</param-value> 
			</init-param> -->
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>*.action</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>

31 5月 2011

A500 首發

用blogger-droid寫blog大概就只能寫出plurk的內容吧
Published with Blogger-droid v1.6.9

27 4月 2011

Maven Android Plugin

 

主要是參考 sonatype的reference - Android Application Development with Maven

1. Maven android sdk deployer
Android SDK的安裝就不在這篇記錄了,直接跳到maven android sdk deployer安裝,先連到https://github.com/mosabua/maven-android-sdk-deployer/,按下Download後自行解壓縮。

Github - Maven android sdk deployer

 

進入解壓縮後的目錄執行

mvn install

正常的話可以看到類似下列的結果
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Maven Android SDK Deployer ........................ SUCCESS [0.598s]
[INFO] Android Platforms ................................. SUCCESS [0.007s]
[INFO] Android Platform 1.5 API 3 ........................ SUCCESS [0.336s]
[INFO] Android Platform 1.6 API 4 ........................ SUCCESS [0.034s]
[INFO] Android Platform 2.1 API 7 ........................ SUCCESS [0.022s]
[INFO] Android Platform 2.2 API 8 ........................ SUCCESS [0.016s]
[INFO] Android Platform 2.3 API 9 ........................ SUCCESS [0.033s]
[INFO] Android Platform 2.3.3 API 10 ..................... SUCCESS [0.019s]
[INFO] Android Platform 3.0 API 11 ....................... SUCCESS [0.037s]
[INFO] Android Add-Ons ................................... SUCCESS [0.011s]
[INFO] Android Add-On Google Platform 1.5 API 3 .......... SUCCESS [0.075s]
[INFO] Android Add-On Google Platform 1.6 API 4 .......... SUCCESS [0.034s]
[INFO] Android Add-On Google Platform 2.1 API 7 .......... SUCCESS [0.021s]
[INFO] Android Add-On Google Platform 2.2 API 8 .......... SUCCESS [0.027s]
[INFO] Android Add-On Google Platform 2.3 API 9 .......... SUCCESS [0.032s]
[INFO] Android Add-On Google Platform 2.3.3 API 10 ....... SUCCESS [0.028s]
[INFO] Android Add-On Google Platform 3.0 API 11 ......... SUCCESS [0.022s]
[INFO] Android Extras .................................... SUCCESS [0.012s]
[INFO] Android Compatibility Extra V4 .................... SUCCESS [0.016s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.922s
[INFO] Finished at: Wed Apr 27 17:28:29 CST 2011
[INFO] Final Memory: 4M/528M
[INFO] ------------------------------------------------------------------------
如果有特定的Platform或Add-On失敗的話,請確認在安裝AVD時是否有把所有的platform與add-on裝上。
其實全裝才有點不正常吧....
所以也可以改用指定profile的方式安裝
mvn install -P 2.3.3
 
可用的profile有1.5, 1.6, 2.1, 2.2, 2.3, 2.3.3, 3.0,就看本身AVD有裝哪些囉

2. pom.xml修改

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>Best1</groupId>
 <artifactId>Best1</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>apk</packaging>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 

<build> <finalName>best</finalName> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>maven-android-plugin</artifactId> <version>2.9.0-beta-4</version> <configuration> <sdk> <platform>10</platform> </sdk> <emulator> <avd>Android233</avd> <wait>10000</wait> <!--<options>-no-skin</options>--> </emulator> <deleteConflictingFiles>true</deleteConflictingFiles> </configuration> <extensions>true</extensions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.google.android</groupId> <artifactId>android</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> </dependencies> </project>

再來就可以執行mvn android:emulator-start, mvn android:deploy來測試程式囉

 

OGNL note

Basic Syntax:
用“.“取得property,例如:user.name => user.getName();
最後加上“()“則代表呼叫method,例如:user.name.toString()
陣列的使用則是以"[]"來操作, users[0]

利用'@'來指定特定的Class、Method及Property,
例:呼叫static method @my.package.Utils@staticMethod(args)取得static property @my.package.Utils@myproperty

在OGNL的概念裡,所有變數都是global variable,但有一個特定的變數做為root
要取得變數以'#'來標示,如:#currentUser,
若是僅見到currentUser,代表是呼叫root.getCurrentUser()以取得root的currentUser

Constant:
String : 用''或““標示字串,{'name',"password"}
Character : 用''標示字元Number : 一般int, long, float, double不用特別標記,但可以用'b'或'B'標示BigDecimal
Boolean : 以true, false標示Null : 以null標示
Variable:利用#取值,可以用#this代表現有的物件也可以為variable設值,如#var1='adam';

Collection:
建立Object Array : {"name",'password'}建立指定型別的Array : new int[] {100,200,300}, new int[3] => new int[] {0,0,0}
建立Map : #{ "name":"adam", "password":"psadam" }建立指定型別的Map : #@java.util.HashMap@{ "name":"adam", "password":"psadam" }

Selecting:
可利用條件篩選Collection裡的物件,如 : users.{? #this.age > 18},代表只有age大於18的人才放入結果
還可以利用類似expression的'^'或'$'來取得第一個或最後一個符合條件的物件:users.{^ #this.age > 18}, users.{$ #this.age > 18}

Projection:
OGNL提供了Projection,也就是可以針對collection裡的物件呼叫相同的method或取得特定的property值,並將其置入另一個Collection中
如:users.{name},這代表將取出所有user的name。
由於OGNL也提供了#this,所以也可以見到這樣的用法 : users.{#this.age > 18 ? #this : null},代表只有age大於18的人才放入projection,不然就放入null

特殊property:

  • Collection:(1)size(2)isEmpty
  • List:(1)iterator
  • Map:(1)keys(2)values
  • Set:(1)iterator
  • Iterator:(1)next(2)hasNext
  • Enumeration:(1)next(2)hasNext(3)nextElement(4)hasMoreElements

容易混淆的Operator

  • Index : array[index]
  • Projection : collection.{exp}
  • Selection : collection.{? exp}