星期六, 5月 31, 2008
星期五, 5月 30, 2008
blog 編輯器

剛剛在網路上看到有人整理了 15 個 blog 編輯器清單,原來現在已經有這麼多的 blog editor 了。前年我還花錢在 OSX 平台上買了一個 ecto 編輯器,結果...後來 blogger 改版,ecto 作者卻是一直沒有跟上速度,一轉眼現在已經免費的 blog editor 一堆了,現在我看會花錢買的人應該很少了。
我自己現在習慣使用 Windows Life Writer,Windows Life Writer 不僅僅支援自己的 MSN Spaces,幾乎目前 popular 的 blog 平台都有支援,加上又是免費的,因此,我個人是最推薦 Windows Life Writer。
More......
Posted by
Jacky
at
09:44
0
comments
Labels: blog
星期四, 1月 10, 2008
開始 Ruby on Rails 之旅
發現自己真的是對於寫部落格很沒有持續性。一方面也是下班以後就很不想要寫這些東西,尤其是要把一些東西整理出來也是很花時間的事情。我手上還有一大堆東西要看,一大堆東西要寫...不過寫部落格的好處是可以把一些過程記錄下來,以後如果還需要使用到的話,就可以直接查詢了。還是把記憶力多拿來記憶一些其他事情吧!
最近兩三個禮拜我開始在看 Ruby On Rails 的東西,不過也不單單只有 RoR,還有 Java 類似 RoR 的一個 Framework,Grails。Grails 其實是個很不錯的東西,因為它可以說是擷取 RoR 的優點,而又可以兼顧到目前的 JVM 相容性,換句話說,目前 Java 的一些好用 packages 都還可以繼續沿用。Grails 還有搭配了一個新的 Script 語言 - Groovy,所以不僅看了 Grails 也把一本 Groovy 的書籍看得差不多了。結果最後還是決定使用 RoR -_-
RoR 最令人驚艷的部份就是可以快速的開發出 Web Application 雛形。當然除了這個好處之外,RoR 的 ActiveRecord 已經把 Database 整合到 Framework 裡面,因此在開發一些 Database Driven 的應用程式上,RoR 的確是可以加速開發的速度。另外對於 AJAX 的整合部份,RoR 也是比 Java 目前的一些 Framework 好。
因此會陸續開始 RoR 的筆記心得了....
More......
Posted by
Jacky
at
11:13
0
comments
星期五, 5月 04, 2007
Spring Framework 筆記 (五)
寫 Web Form 程式在以往最麻煩的地方就是 Form Validation 部份。早期都只能透過 Javascript 來做 client 端的 validation,但是 Javascript 驗證的缺點就是不好維護,而且要做到 reuse 也相對是比較難一些;Spring 在 Form Validation 方面也提供了一套 validcation 的機制,可以輕鬆的達到 Form Validcation。
我們使用一個註冊的 Form 來做例子,提供一個 Register Form 讓使用者可以輸入要申請的帳號以及密碼 (得要輸入兩次以便驗證兩次是否都一樣),而申請的帳號如果是 "jacky",就秀出已經註冊過的訊息;若是密碼兩次輸入不一樣,同樣也會秀出密碼不一樣的錯誤訊息。
Form HTML 為:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Language" content="zh-tw" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled 1</title>
</head>
<body>
<form method="post" action="register.do">
<table>
<tr>
<td>account:</td>
<td><input name="login" type="text" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input name="passwd" type="password" /></td>
</tr>
<tr>
<td>Password Again:</td>
<td><input name="passwd2" type="password" /></td>
</tr>
<tr>
<td><input name="Submit1" type="submit" value="Register" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
延伸之前例子的 Member Java Bean,多加入了 passwd2 以及 email attribute。
package com.esolution.Model;
public class Member {
private String login;
private String passwd;
private String passwd2;
private String email;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPasswd2() {
return passwd2;
}
public void setPasswd2(String passwd2) {
this.passwd2 = passwd2;
}
}
修改 URL Mapping 的設定:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.htm">
springappController
</prop>
<prop key="/login.do">
springappSimpleFormController
</prop>
<prop key="/register.do">
memberRegisterController
</prop>
</props>
</property>
</bean>
接著因為我們需要 spring 將 form 上面的欄位資料跟 JavaBean binding 在一起,所以需要 spring taglib 來做 data binding:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="spring" uri="/spring" %>
<!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">
<head>
<meta http-equiv="Content-Language" content="zh-tw" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled 1</title>
</head>
<body>
<spring:bind path="command.*">
<font color="red">
<c:forEach items="${status.errorMessages}" var="error">
<strong><c:out value="${error}"/></strong><br>
</c:forEach>
</font>
</spring:bind>
<form method="post" action="register.do">
<spring:bind path="command">
<table>
<tr>
<td>account:</td>
<td><input name="login" type="text" value="<c:out value='${command.login}'/>"/></td>
</tr>
<tr>
<td>Password:</td>
<td><input name="passwd" type="password" value="<c:out value='${command.passwd}'/>"/></td>
</tr>
<tr>
<td>Password Again:</td>
<td><input name="passwd2" type="password" value="<c:out value='${command.passwd2}'/>"/></td>
</tr>
</spring:bind>
<tr>
<td><input name="Submit1" type="submit" value="Register" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
在上面 JSP Code 中 spring:bind tag 分成兩個部分,錯誤訊息顯示以及 data binding。spring data binding 會使用一個 Command Class 來存 data,而該 command class default 的名稱是 command;例如在上面的例子就是使用 spring:bind tag 將 login、passwd、passwd2 三個 form 欄位跟 Command class binding 在一起 (該 Command class 的名稱叫做 command):若是使用者的輸入驗證沒通過 command.login 、command.passwd、command.passwd2 都會秀出之前使用者輸入的值。至於錯誤訊息顯示的部分 spring 會把錯誤資訊放在 status 變數中。
接著要撰寫 validator 程式:
package com.esolution.Validator;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.esolution.Model.*;
public class RegisterValidator implements Validator {
public boolean supports(Class clazz) {
return Member.class.isAssignableFrom(clazz);
}
public void validate(Object obj, Errors errors) {
Member member = (Member)obj;
if("jacky".equalsIgnoreCase(member.getLogin())){
errors.rejectValue("login", "existed",null,"The Account is existed");
}
if(! member.getPasswd().equals(member.getPasswd2())){
errors.rejectValue("passwd2", "passwordNotMatch",null, "Passwords does not match");
}
}
}
Validator 程式主要是要 implemtn Validator Interface,實做 supports 以及 validate methods:supports 主要是要判別傳進來的 class 參數是否是 Member 或繼承自 Member 的 class;validate method 主要是根據使用者在 form 上面輸入的值來做 validate;在上述程式中我們判斷兩個:一個是假設如果輸入的 login 欄位資料是 jacky,就秀出該帳號已經存在的訊息;若是兩次輸入的密碼不一樣,就秀出密碼不一致的訊息。
rejectValue method 資料如下:
void rejectValue(String field,
String errorCode,
Object[] errorArgs,
String defaultMessage)
field - the field name (may be null or empty String)
errorCode - error code, interpretable as a message key
errorArgs - error arguments, for argument binding via MessageFormat (can be null)
defaultMessage - fallback default message
修改 controller 的設定:(加入 validator、formView、commandClass、successView 資料) <property name="successView"> <property name="validator"><bean id="memberRegisterController" class="com.esolution.Controller.MemberRegisterController">
<property name="formView">
<value>register</value>
</property>
<property name="commandClass">
<value>com.esolution.Model.Member</value>
</property>
<value>success</value>
</property>
<bean class="com.esolution.Validator.RegisterValidator"/>
</property>
</bean>
More......
Posted by
Jacky
at
16:18
0
comments
星期四, 5月 03, 2007
Spring Framework 筆記 (四)
在 Web Application 裡面,Form 是一個非常重要的元素,透過 Form,使用者可以 submit 資料到後端的程式。另外 Form 的資料要如何的對應到後端的資料庫 Table 資料、Form 上面資料的資料驗證等等都是在 Form 的處理上需要考慮到的 issues。Spring 已經內建了不少實用的 Controller,其中有一個是 SimpleFormController。
底下是 Spring 一部份的 class diagram,從裡面可以看到 Controller 端,最上層是 Controller Interface,包含單一的 method - handleRequest。首先先看一下 SimpleFormController 的部分 Source Code:
public class SimpleFormController extends AbstractFormController {
private String formView;
private String successView;
protected ModelAndView onSubmit(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
throws Exception {
return onSubmit(command, errors);
}
...
}
上面的 Source Code 可以看出來,SimpleFormController 繼承自 AbstractFormController,而且它需要formView、successView 以及 command object。formView 可以視為呈現該 form 的頁面,successView 可以視為是 form submit 成功之後,會導向過去的成功頁。至於 Command object 可以視為是把 form 上面的欄位包裝起來的一個 object。而 onSubmit method 是當 form 點了 submit button 之後會 fire 的 method,也是我們需要覆寫的部分。
假設現在我們需要設計一個 login form,裡面只有兩個欄位,一個是 login name 另外一個是 password 欄位,我們需要做 login 以及 password 的檢查,若是檢查成功,則將使用者導到 success.jsp,若是失敗則秀出錯誤訊息。這個簡單的 form HTML soruce 如下:
<html>
<head><title>Spring Login Test</title></head>
<body>
<form name="loginForm" method="POST" action="login.do">
Login: <input name="login" type="text" > <br/>
Password: <input name="passwd" type="password"> <br/>
<input type="submit" value="login">
</form>
</body>
</html>
上面是一個非常典型的 Form 程式,包含了一個 login 欄位,以及 password 欄位,而 submit action 是 login.do,而我們現在要使用 spring SimpleFormController 來處理這個 Form。
因為我們設定的 form action 是 login.do,因此我們需要在 web.xml 上面設定 *.do 類型的檔案由 spring 處理:
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
除此之外,我們得要設定 URL mapping,將 login.do mapping 到處理該 submition 的 spring controller。
<!-- URL Mapping Defination -->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.htm">springappController</prop>
<prop key="/login.do">springappSimpleFormController</prop>
</props>
</property>
</bean>
就如同上面 SimpleFormController source code 所示,我們需要一個 command object 來包含 form 上面的 element,因此我們先產生一個 JavaBean 包括兩個欄位,login 以及 passwd:
package com.esolution.Model;
public class Member {
private String login;
private String passwd;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
接著設定 Spring 設定檔,將 Controller 的 property 填入:
<bean id="springappSimpleFormController" class="com.esolution.Controller.SpringappSimpleFormController">
<property name="formView">
<value>login</value>
</property>
<property name="commandClass">
<value>com.esolution.Model.Member</value>
</property>
<property name="successView">
<value>success</value>
</property>
</bean>
首先我們需要一個繼承自 SimpleFormController 的 Controller,也就是上面的 springappSimpleFormController,接著我們需要設定它的 formView、commandClass、以及 successView 。formView 代表我們的 form 頁面為 login.jsp、command class 為 Member JavaBean,成功之後會導向 success.jsp。 接著讓我們撰寫 com.esolution.Controller.SpringappSimpleFormController:
package com.esolution.Controller;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.validation.*;
import javax.servlet.http.*;
import java.util.*;
import com.esolution.Model.*;
public class SpringappSimpleFormController extends SimpleFormController {
public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object Command, BindException errors) throws Exception
{
Member memberForm = (Member)Command;
Map model = errors.getModel();
model.put("login", memberForm.getLogin());
model.put("passwd", memberForm.getPasswd());
return new ModelAndView(this.getSuccessView(),model);
}
}
當使用者在 login.jsp 輸入帳號密碼之後,按下 submit 之後,會進入 SpringappSimpleFormController 的 onSubmit method,而根據 JSP 上面的 spring binding,以及 spring 設定檔設定該 command class 為 Member JavaBean,因此我們只要把 Command 轉型為 Member JavaBean,我們就可以直接取出使用者輸入的值了。在這邊我們只是把值取出之後,傳送到 sucessView 頁面。
More......
Posted by
Jacky
at
14:59
0
comments
星期三, 5月 02, 2007
聲活派知識隨意貼
這是一個聲活派新推出的服務,可以讓使用者將喜歡的書籍以及試聽貼到自己的部落格上。只要將每本書的知識隨意貼語法貼到 blog 上面,就可以擁有該本書的書封以及試聽了。
我上面貼著這本書,QBA - 問題背後的問題,是一本很不錯的好書。整本書非常的袖珍,內容沒有很多,但是卻都可以切中主題。花短短的時間,就可以把這本書看完了,極力推薦大家去看看。
More......
Posted by
Jacky
at
09:56
0
comments
Labels: AudioBook
星期二, 5月 01, 2007
Spring Framework 筆記 (三)
上面的簡單例子可以簡單的描繪出 Spring Framework 在 Web Application 開發上所需要具備的一些元素。因此以 bottom-up 的方式,講完了例子,再反推回去看實際的 Spring Web Application 架構。
底下這張架構圖可以去對應上面的例子,DispatcherServlet 就是例子裡面的 springapp (org.springframework.web.servlet.DispatcherServlet),這個是控制著 Spring Web MVC 的起始點。
HandllerMapping 就是我們在例子裡面使用到的 urlmapping,指定對應到符合某些條件的 request 由哪支程式來做處理 (另外還可以加入一些前置或後置處理的 process)。
Contoller 就是 MVC 架構中的 'C',也就是上面例子裡面的 springappController。
ViewResolver 負責將 ViewName 解析到相對應的 View。
傳統的 JSP/Servlet 處理模式大概就是由 JSP 負責 View 的部分,由 Servlet 負責 Controller 部分,而 Servlet 會繼承自 HttpServlet,並且會覆寫 doPost 或 doGet methods,處理完之後,再 forward 或是 redirect 到結果頁面。在轉到結果頁面的過程中,若是 Servlet 有一些處理的資料需要讓結果頁面來呈現,就會透過 Session 或 HTTPServletRequest 傳遞資料。另外 Model 的部分就是使用 JavaBean 來包裝這些 Domain Model 的資料。
Spring MVC 架構主要也是架構在上述的 JSP MVC Model 2 架構,不過 Spring 將上面的 Model 包裝成一個 Framework,增加開發的 reuse 以及 pluggable 特性。
底下是 Spring Controller Interface 的程式碼,這只是一個 Interface,定義了 Contoller 該有的行為,handleRequest。handleRequest 的作用跟 HTTPServlet 裡面的 doPost 以及 doGet 類似,而最後回傳的是一個 ModelAndView 的 Object。ModelAndView 先不看程式碼,由上述的 JSP MVC Model 2 架構就可以很清楚的看出, ModelAndView 的主要作用在哪了。
public interface Controller {
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
再回頭看之前的 springappController 程式碼:
public class SpringappController implements Controller {
private String viewFileName;
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
logger.info("SpringappController - returning hello view");
String now = (new java.util.Date()).toString();
return new ModelAndView(getViewFileName(), "now", now);
}
public String getViewFileName() {
return viewFileName;
}
public void setViewFileName(String viewFileName) {
this.viewFileName = viewFileName;
}
}
主要就是 implement Controller Interface,把 handleRequest method 給實際 implement 出來,最後的 ModelAndView 的 View 部分就是從 Setter Injection 指定給 springappController 的 view name,以及現在日期的 model 資料 - now。
至於 URL mapping 以及 View Resolover 部分,都是直接使用 Spring 內建的 SimpleUrlHandlerMapping 以及 JstlView。除了 SimpleURLHandlerMapping 之後,Spring 還內建了其他的 URM Mapping 方式。同樣的,除了 JstlView 之外,Spring 也可以跟其他的 presenation 架構整合。
More......
Posted by
Jacky
at
13:50
0
comments
星期一, 4月 30, 2007
Spring Framework 筆記 (二)
從上面一個 hello 例子應該很難感覺出 Spring 的迷人之處在哪,所以接著就從上面的例子,我們再做一些改進。在上面的例子裡面,要呈現的 hello.jsp 檔案是寫死在 SpringappController 程式裡的,這在以後的程式維護上會缺少彈性,另外除此之外,Web View 部分也同樣可以在 Spring 的設定檔裡面做設定。
首先我們先把 SpringappController 裡面的 hello.jsp 透過 Spring 來做管理。Spring Framework 裡面最重要的概念就是 IoC (or Dependences Injection),所以我們在這邊使用 Setter Injection 的方式,在設定檔裡面來做參數的設定:
<bean id="springappController" class="com.esolution.Controller.SpringappController">
<property name="viewFileName">
<value>hello.jsp</value>
</property>
</bean>
但是我們希望可以在更簡化一點,可以只單純的使用一個代數方式來表現,不需要每次都要把路徑以及副檔名都寫上。因此這邊我們使用 Spring ViewResolver 來簡化設定:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
如上面設定所示,加入了 prefix 以及 suffix property 讓 springappController 可以只用 hello 就可以代表 /hello.jsp,除此之外,上面的設定也指定使用 JSTL 來當作 View 端的呈現方式。(若是要使用其他種的 Presentation 方式,只需要在這邊做設定)。
而原本的 springappContoller 設定就轉變為:
<bean id="springappController" class="com.esolution.Controller.SpringappController">
<property name="viewFileName">
<value>hello</value>
</property>
</bean>
如同上面提到的,我們使用 setter injection 來控制,所以現在我們需要在 springappController.java 上面加入 viewFileName property,讓 Spring 可以把 viewFileName 指定給 springappContoller。
package com.esolution.Controller;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class SpringappController implements Controller {
private String viewFileName;
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
logger.info("SpringappController - returning hello view");
String now = (new java.util.Date()).toString();
return new ModelAndView(getViewFileName(), "now", now);
}
public String getViewFileName() {
return viewFileName;
}
public void setViewFileName(String viewFileName) {
this.viewFileName = viewFileName;
}
}
現在若是需要變動 view 的部分,原本的 springappContoller 就可以不需要做任何的變動,只需要去改變 spring 設定檔即可。
More......
Posted by
Jacky
at
23:19
0
comments
星期日, 4月 29, 2007
Spring Framework 筆記 (一)
當你要開發一個系統的時候,除非只是一個很小的系統,否則搭配一個適合的 Framework 可以簡化你以後開發的速度。例如在 Windows Application 開發上有微軟的 MFC 或 Borland 的 VCL,而在 Web Application 開發上也有不少的 Framework 可以使用。目前比較常被提到的有 Struts、JSF、Spring Framework、WebWork ,而我現在主要就是要以 Spring Framework 來開發系統。
JSF 是我之前拿來開發過一個政府案子的一個 Framework,JSF 最常被拿來跟 Struts 做比較,因為這兩個 Framework 有很多相似的地方,但是 JSF 是屬於由 Sun 官方 Support 的,而 Struts 是由 Jakarta 所 Support。當初會選擇使用 JSF 的主要原因就是因為這是由 Sun 所支援,代表說其他的一些 Java 廠商也會跟著 Support。不過目前網路上使用 Struts Framework 的網站還是比 JSF 多很多。
每一個 Framework 都有其優缺點,所以我個人會傾向於找一個彈性比較大,容易跟其他 Framework 整合的 Framework,而 Spring Framework 就是這樣的一個 Framework。Spring Framework 並不只限於開發 Web Application,你也可以拿 Spring Framework 來開發 Windows Application。
底下是 Spring Framework 的一個架構圖,最重要的就是底層的 Spring Core 核心容器,用來定義了建立、配置和管理 bean 的方式。Spring 擁有自己的 Web MVC、Spring ORM,但是它也可以跟其他的 Framework搭配,也可以跟其他的 ORM 搭配 (例如:Hibernate) ,Spring Framework 就是這麼的彈性。
網路上有不少的 Spring Framework 介紹,包括 Spring Framework 的源由、IoC 概念以及 AOP 等等,所以有興趣的人可以直接從 google 上去找尋到這些資料,這篇文章就直接先從最基本的 hello 程式開始。首先先瞭解一下 Spring Framework 在 Web Application 上的處理流程大概如下圖所示:
所有的 request 都會先經過 Front Controller,再 dalegate 給適當的 Controller,而 Controller 會再回傳到對應的 View Template。
1. 下載 Spring Framework 檔案
Spring Framework 的下載位置在這邊,spring-famework-xxx-with-dependencies.zip 是包含其他一些會有到的 pacakages 全部都打包在一起了,若沒什麼特殊,可以直接下載這個檔案,解開之後,把 spring.jar、log4j.jar 以及 common-logging.jar copy 到 springapp/WEB-INF/lib 下 (假設這個 web-application 叫做 springapp)
2. 修改 web.xml 檔案
Spring Framework 使用一個 Dispatch Servlet 當作所有 request 的入口 (Front Controller),所以得要在 web.xml 指定,如下圖所示。另外在 servlet-mapping 中也指定所有的 *.htm 檔案都會由 Spring Framework 處理。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</web-app>
3. 新增 spring 設定檔案
因為在上述的 web.xml 檔案中,我們設定了 Dispatch Servlet 的名字為 springapp,所以 spring 的設定檔案名稱是 springapp-servlet.xml (也可以指定其他的檔案名稱,但是得要額外設定)。內容大致如下:
在 Spring 設定檔案中最主要就是要設定 bean 的資料,首先我們需要設定一個 url mapping 的 bean 來設定哪些 request 需要給哪一個 handler 來處理。Spring 已經內建了幾個常用的 url mapping 機制,在底下我使用的是 SimpleUrlHandlerMapping,作用就只是單純的把 /hello.htm 的 request 丟給 springappController 處理。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.htm">springappController</prop>
</props>
</property>
</bean>
<bean id="springappController" class="com.esolution.Controller.SpringappController"/>
</beans>
4. 撰寫對應的 bean 程式
因為上述的設定需要一個 springappController 程式來處理由 /hello.htm 的 requestM,因此我新增了一個 springappController 的 bean,然後它的 class 資料如下:(com.esolution.Controller.SpringappController)
public class SpringappController implements Controller {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
logger.info("SpringappController - returning hello view");
String now = (new java.util.Date()).toString();
return new ModelAndView("hello.jsp", "now", now);
}
}
這個程式主要需要撰寫的部分在 handleRequest 這個 method 上面,因為我們只是要一個簡單的 hello,所以上面只是回傳一個 ModelAndView object。ModelAndView 顧名思義就是需要 Model 資料以及 View 資訊,在上面的 Model 資料就是現在的日期資訊以及名稱,而 View 資訊就是 hello.jsp。
5. 撰寫 View 程式
因為上面的 SpringappController 會把資訊傳遞到 hello.jsp 這個 JSP 程式,因此我們需要撰寫 hello.jsp。這邊我使用 JSTL 讓整個頁面可以更簡潔,不要讓 script 以及 HTML 混合在一起。下面就是秀出:
Greetings, it is now xxxx
xxxx 就是由上面的 ModelAndView 帶過來的 now 資訊。
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
<head><title>Hello :: Spring Application</title></head>
<body>
<h1>Hello - Spring Application</h1>
<p>Greetings, it is now <c:out value="${now}"/>
</p>
</body>
</html>
上面就是一個很簡單的程式,接下來再慢慢說明可以怎樣的變化。
More......
Posted by
Jacky
at
17:39
0
comments
星期四, 4月 26, 2007
聲活派再次改版

沒幾個月,聲活派又再次改版了。比較不同的是,這次的改版全部是由我部門所完成的,包括 Art、Engineer 還有網站規劃。主要是放在視覺上的改變,以即將之前網站的一些缺點做改進,整個改版花了一個月左右,感謝我部門的努力,讓新版在今天正式上線。
這次改版在網站搜尋的部分,我加入了 Lucene .Net ,讓整個網站的搜尋更加的 Powerful。除了基本的 keyword search 之外,還可以使用 boolean 運算式來做查詢,例如:
投資 And 管理
會查詢 Index 資料裡面包含『投資』以及『管理』的有聲書。若使用 Or ,就是查詢包含『投資』或『管理』的有聲書。之後我會把 Lucene 的東西做個介紹。
再來就是之前我們加入的月費 299 聽到飽的機制,這種機制比較偏向於 KKBox 的收費方式,當然原本的單次購買還是保留著。
目前整個網站看起來質感增加不少,接下來就看明天開始導入流量的結果了。
More......
Posted by
Jacky
at
22:47
0
comments
Labels: AudioBook
星期二, 4月 17, 2007
讓 Google 管理公司的 Mail - Google 應用服務網站版
我想如果問一個網管說你覺得網管的 Server 裡面,哪一個最讓你棘手,我猜 Email 應賅是可以列入到前三沒問題的。我不是網管,但是只是因為我現在有時候還得要身兼一部份網管的工作,所以今天來介紹一個 goolge 提供的 Email 管理服務。理由很簡單,Email 幾乎已經是目前大家最常使用的網路 Service,你問看看你公司的人能不能一天收不到 Email?Email Server 一掛掉,可能大家就開始緊張了,而 Email Server 說簡單是很簡單,但是牽涉到的東西又很廣,包括 SMTP Server、DNS 設定、SPAM Mail 的阻擋等等。對於一般的中小型企業,Google 提供了一個很好的 Solution - Google 應用服務網路版。
首先你需要先去申請這個 Service,網址是 http://www.google.com/a/,你得要填一些網域或公司資訊等等,這些應賅都算很簡單的步驟。申請完之後,啟用電子郵件服務需要兩個步驟:
- 驗證網域擁有權:
這個步驟主要是要確認你是否是該網域的管理者,否則每個人都去隨便設定別人的網域,就可以把別人的信件都拿過來也太可怕了。比如說你的網域是 test.com,那你必須在 www.test.com 這台機器上放置一個 googlehostedservice.html 檔案,檔案內容就是複製說明頁上面的內容。
- 設定網域 MX Record:
這個步驟主要是要設定 DNS MX Record,在你的 DNS Server 中設定底下的資訊:
test.com IN MX 1 ASPMX.L.GOOGLE.COM.
test.com IN MX 5 ALT1.ASPMX.L.GOOGLE.COM.
test.com IN MX 5 ALT2.ASPMX.L.GOOGLE.COM.
test.com IN MX 10 ASPMX2.GOOGLEMAIL.COM.
test.com IN MX 10 ASPMX3.GOOGLEMAIL.COM.
test.com IN MX 10 ASPMX4.GOOGLEMAIL.COM.
test.com IN MX 10 ASPMX5.GOOGLEMAIL.COM.
test.com 是網域名稱,IN 指的是 Internet,MX 就是 Mail eXchange Reocrd,1、5、10 這些代表的是 priority,不見得要用 1、5、10,只要是數字可以表現成大小就可以了 (例如 10、20、30)。這些設定完之後,就可以把 mail account 設定上去了。
為什麼這樣設定以後,就可以透過 google 來收信呢?主要就是在 MX Record。Email 除了 SMTP Server 之外,還需要透過 DNS MX Record 資訊來得知要把信件傳遞到哪台 Server。因此上述的設定下,假設有人寄信給 xxx@test.com,Mail server 會去查詢 test.com 的 MX Record,由上述得知要把信件寄送到哪台機器 (根據 priority 決定,若 ASPMX.L.GOOGLE.COM 失敗就換 ALT1.ASPMX.L.GOOGLE.COM,以此類推)
More......
Posted by
Jacky
at
09:32
0
comments
星期一, 4月 16, 2007
好用的 Blog 離線編輯器 - Windows Live Writer
去年我為了可以方便在我的 iBook 上面寫 blog,參考了一些資料,找到了 ecto 這套 blog 編輯器; 我也花錢買了一套,說特別好用,我覺得也還好,不過也算是一套方便的工具就是了。我之前也寫過文章批評過 Blogger 真的是很不人性化的一個系統,去年 Blogger 可能聽到了很多人的抱怨,推出了 Blooger Beta,而這也照成另外一個問題,ecto 不支援 Blooger Beta XD。我在網站上早早就看到作者說他正在著手進行 ecto 3 的開發,不過幾個月過去了,似乎還在是在開發中。現在推薦一套微軟出的 Blog 離線編輯器 - Windows Live Writer。
一開始我以為 Windows Live Writer 只有支援 Windows Live Spaces,因為微軟一向都是會這樣搞。不過沒想到這次 Windows Live Writer 並沒有,而且對於其他 Blog 系統的支援度也滿不錯的。下載之後,只要底下的幾個步驟就可以開始使用了:以 Blogger Beta 為例:
1. 設定你的 Blogger Beta 的網址與帳號密碼

2. 系統開始抓資料設定
3. 詢問 blog 資訊
4. 開始寫 blog
畫面就跟 word 類似,所以應賅是可以很容易上手的。不過現在不支援圖片直接上傳,這點跟 ecto 之前對於 blogger 的支援一樣。編輯之後就可以存成 Draft 或是 Publish 到 Blog 了。
More......
Posted by
Jacky
at
11:43
0
comments
Labels: Tools
星期三, 2月 28, 2007
Java 與 UTF-8 編碼 (五)

這些文章我覺得整理的不是很好,大部分都是想到什麼就寫什麼,可能有空再做整理了。不過基本上前面提到的事把 JSP 跟 Servlet 部分如何以 UTF-8 處理,以避免亂碼,這篇主要就是 Database 的部分了。
Database 算是比較單純的,因為現在大部分的知名 Database 幾乎都是已經 Support Unicode,例如:MS SQL Server、MySQL、Oracle 等等。我之前寫的一篇文章「在 OSX 上安裝 MySQL」,當時我會選擇自己從新從 Source Code Configure 以及 Compile 的原因也就是想要變成直接支援 UTF-8 編碼。
資料從 JSP 進入到 Database,每一部份都是使用 UTF-8
JSP --> Servlet --> Database
資料從 Database 到 JSP 呈現,如果也都一樣使用 UTF-8,那就可以避免到中文亂碼的問題了。
Database --> Servlet --> JSP
More......
Posted by
Jacky
at
01:12
0
comments
星期二, 2月 27, 2007
Java 與 UTF-8 編碼 (四)

在 Java 與 UTF-8 編碼 (一) 裡面有提到我上面的例子使用 UTF-8 格式來存 JSP 檔案。那現在我們試看看如果使用不同的編碼格式來存檔,結果會變成如何呢?
我使用 Notepad++ 把 JSP 檔案編譯成 ANSI 格式,另外我在 JSP 檔案裡面加入中文的訊息,包括 title 以及 body 都加入中文,JSP 內容如下:
從上面的檔案看起來,我們也加入了 :
<%@page contentType="text/html; charset=UTF-8"%>
內容從 Notepad++ 看起來跟之前的 JSP 檔案也差不多,那執行起來的結果呢?如下圖:
發現所有中文的部分都變成亂碼了。這時候 ANSI 編碼以及 UTF-8 又衝突了,怎麼解決這問題呢?很簡單,只要把 pageEncoding="big5" 加入 JSP Page 宣告中:
<%@page contentType="text/html; charset=UTF-8" pageEncoding="big5"%>
出來的結果就正常了。pageEncoding 是用來宣告你的 JSP 檔案是以什麼 Format 來存檔的,如果你有很多檔案都是已經寫好了,而且也都不是使用 UTF-8 格式來存檔的,那最快的方式就是使用 pageEncoding 來宣告你的存檔格式。不過我還是建議存檔直接以 UTF-8 格式來存檔是最好的了。
More......
Posted by
Jacky
at
22:54
0
comments
星期一, 2月 26, 2007
Java 與 UTF-8 編碼 (三)

這個系列的文章,主要都是要解決亂碼的問題。如果是英語系的國家,基本上就不用處理這些煩人的問題了。Java 本身就提供了原生的 Unicode Support,所以我的經驗是乾脆就全部都使用 UTF-8 編碼。(從網頁 --> 程式 --> 資料庫)
在 Java 與 UTF-8 編碼 (一) 跟 Java 與 UTF-8 編碼 (二) 都是比較偏向於網頁端處理部分,在裡面的例子我使用一支 Servlet 來處理 Form Submit 的處理,程式如下:
package com.esolution.test;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EncodingTestServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println(name+ "
");
}
}
裡面仔細看會看到
req.setCharacterEncoding("utf-8");
...
resp.setContentType("text/html;charset=utf-8");
分別對 HttpServletRequest 設定 UTF-8 encoding 以及對最後的 HttpServletResponse 設定 Content Type 的 charset 為 UTF-8。但是如果每個處理程式都要這樣做那有沒有更簡單的方式呢?有的,那就是使用 Filter。
Filter 在 Servlet 2.3 Spec. 中佔有很重要的地位,這篇文章有簡介 Filter 的功用以及介紹一些現成可以使用的 Filter。根據上面文章的解釋:
A filter is an object that can transform a request or modify a response. Filters are not servlets; they don't actually create a response. They are preprocessors of the request before it reaches a servlet, and/or postprocessors of the response leaving a servlet.
上面點出了 Filter 的最大功用,可以針對 request 做前置處理,以及 response 做後置處理。而我們現在就是希望可以在每個 request 以及 response 裡面加入 encoding 以及 content type 修改。其實在 Tomcat 裡面就已經有這個 Filter 了,內容如下:
package com.esolution.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String encoding = selectEncoding(request);
if (encoding != null) {
request.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
除了上面的程式之外,web.xml 也需要做一些設定:
<filter>
<filter-name>SetCharacterEncodingFilter</filter-name>
<filter-class>com.esolution.filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>>
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
這樣就可以用一支 Filter 把所有程式裡面的 request 以及 response 關於 encoding 跟 content type charset 都設定為 UTF-8 了。
More......
Posted by
Jacky
at
21:19
0
comments
星期日, 2月 25, 2007
Java 與 UTF-8 編碼 (二)

在上一個例子裡面,我使用一個 jsp 以及 html 檔案分別作 form submit (JSP 跟 html 的檔案內容都一樣),並且使用一個 servlet 把傳遞的參數顯示在網頁上面。在上面的例子雖然都可以從網頁上得到正確的結果,但是實際內容卻是不一樣的。
第一個例子使用的是單純 html,而且在 html 裡面有加入 meta tag 指定 charset 為 utf-8:
<meta http-equiv=="Content-Type" contentType="text/html; charset=UTF-8">
另外該 html 檔案存檔的時候,我是採用 UTF-8 格式來存檔,當 Browser 瀏覽這個頁面的時候,會以 UTF-8 編碼方式來解析該網頁。當 form submit 到 servlet 的時候,也同樣會以 UTF-8 的方式來傳遞,因此最後印出來的結果正確無誤。
第二個例子變成以 JSP 的方式來呈現。雖然也同樣加入了 meta tag 指定 charset 為 utf-8,也同樣使用 UTF-8 格式存檔,出來的結果雖然正確,但是如果去檢視 output 的 HTML source,會發現其實內容並不是我們要的。(會以 D; 的形式出現, D 代表該字元在 Unicode character set 的 decimal codepoint)
這個問題會產生的原因主要是 JSP Default 的編碼方式是 ISO-8859-1,而中文字並沒有辦法直接以 ISO-8859-1 的方式來編碼,因此 browser 直接將非 ISo-8859-1 字元以該字元在 Unicode character set 的 decimal codepoint 傳遞出去。
上面編碼方式會因為 browser 而有些差異,我測試 IE6 跟 Firefox 的部分就有些差異:例如在 Firefox 上面,使用 get 的方式傳遞 name=中文,會以底下的編碼傳遞:
http://localhost:8080/WebTest/EncodingTestServlet?name=%26%2320013%3B%26%2325991%3B&%E9%80%81%E5%87%BA=Submit+Query
但是在 IE 下則是:
http://localhost:8080/WebTest/EncodingTestServlet?name=%26%2320013%3B%26%2325991%3B&%E9%80%81%E5%87%BA=%26%2336865%3B%26%2320986%3B%26%2326597%3B%26%2335426%3B
差別主要是在最後的部分: Submit+Query 是英文字元,Firefox 並沒有使用 Unicode character set decimal codepoint 格式,但是 IE 卻是全部都轉換為 Unicode character set decimal codepoint。不過前面的參數部分,Firefox 跟 IE 都是一樣的。
我上次在這邊卡了一兩個小時,一直找不到原因。因為我已經指定了 meta tag 為 utf-8,但是結果卻不是我要的。最後我發現 JSP 一定得要強制加上:
<%@page contentType="text/html; charset=UTF-8"%>
只有單純加上 html content type meata tag 指定 charset 是沒有用的。因為我檢視了 JSP 產生出來的 Java 檔案,發現若缺少 JSP page 去宣告 charset 的話,JSP 實際上是:
response.setContentType("text/html;charset=ISO-8859-1");
若加入 JSP page 宣告 charset 為 UTF-8,JSP 產生的 Java 檔案內容為:
response.setContentType("text/html;charset=utf-8");
More......
Posted by
Jacky
at
15:40
0
comments
星期六, 2月 24, 2007
ESL Podcast

推薦一個我在上班通勤時間很常聽的一個 Podcast - English as a Second Language Podcast。這是一個英文學習的 Podcast,主講人是 Dr. Jeff McQuillan,很適合給非英語系國家的人學習英文使用。
很可惜在台灣目前 Podcast 還不是一個很 popular 的東西,但是在歐美,Podcast 的應用已經非常多元化了。Podcast 的優點是可以表現出個人化,只要你敢秀,你的聲音很容易就可以傳播到全世界。
通勤時間是一段非常無聊的時間,我個人是很討厭浪費時間在坐車上面。所以早上時間我搭火車的時候,就會使用 iPod 來聽 ESL Podcast,一個禮拜會有 2-3 個課程,會先用放慢速度的對話,再由 Dr. Jeff McQuillan 解釋裡面的一些特殊單字或片語,最後再用正常的速度播放該對話。另外還有 English Cafe 介紹一些文化、節慶等不同的主題以及回答從世界各地 mail 給 ESL Podcast 的英語問題。
這是一個非常好的 Podcast,極力推薦!
(BTW,Podcast 並不是只有 iPod 才能收聽)
More......
Posted by
Jacky
at
23:52
0
comments
Labels: Podcast
星期三, 2月 21, 2007
聲活派小改版上線
聲活派趁著這次過年做了一個小改版, 讓整個網頁更有年味了.
另外也在首頁加入了八本書的試聽, 讓整個網站的內容看起來更豐富一些. 在南部家裡上網只能使用撥接上網, 實在是慢的痛苦...-_-
More......
Posted by
Jacky
at
15:34
0
comments
Labels: AudioBook
星期日, 1月 28, 2007
Java 與 UTF-8 編碼 (一)

使用 Java 的人應該都或多或少遇到過編碼問題吧,到底什麼時候要用什麼編碼,網頁要怎麼寫 charset,然後網頁的資訊傳遞的時候,接收的時候是不是還得要經過轉碼?最後進入 Database 的時候是不是還得要做一次編碼?真的會令人傻傻的分不清楚!
我之前寫過一篇關於 MySQL 安裝的筆記,我想要重新從 source code 安裝的一個很重要因素就是 UTF-8,因為中文的編碼是一件非常麻煩的事情,尤其 PHP + MySQL 還有很常被問到的 「許功蓋」問題。
因此我自己的經驗是可以 UTF-8 編碼的,就直接使用 UTF-8 編碼,這樣子是可以最輕鬆的。而現在的 Database 幾乎都是支援 Unicode 編碼了,例如:MS SQL Server、MySQL 等等。而除了 Database 之外,接下來就是程式語言以及網頁的部分。
網頁的部分又可以細分兩個部分,一個是存檔的時候是不是使用 UTF-8 編碼來存檔,另外一個是設定網頁的 charset。網頁的 charset 是由底下的 meta tag 來設定的:
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
charset 是指定 browser 來瀏覽的時候該使用哪種語系來解析該頁面,這問題在 PHP 之類的語言比較少會遇到亂碼,但是對於 Java 就不一樣了。主要是 Java 底層就是使用 unicode 編碼,網頁程式如果是 JSP 的話還會先轉成 Servlet ( java 檔案),再 compile 成為 class 檔案。若是轉換的過程中 encoding 不一致,就可能變成亂碼了。這篇文章討論了網頁編碼以及進入 Database 編碼的問題,很值的一看。
我的經驗是一切都使用 UTF-8 編碼,包括存檔的時候以及 charset。舉個例子:

上面是很簡單的一個 form submit 例子,我分成兩種狀況 (BIG format 存檔以及 UTF-8 format 存檔)上面的檔案是以 BIG5 編碼方式去存檔 (光看內容是看不出來的,尤其都是英文的狀況)
1. 我把上面的內容以 html 的方式來呈現,並且 submit 資料給 Servlet。
Servlet 只是直接使用 request.getParameter("name") 的方式抓取資料並列印到頁面。結果是:(測試環境是 IE 6.0 以及 Tomcat 4.1.34)
至於處理該 JSP form 的 servlet 程式碼如下:
package com.esolution.test;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EncodingTestServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println(name+ "
");
}
}
上面會設定 HttpServletRequest 的 CharacterEncoding 為 UTF-8 以及 HttpServletResponse 的 content type。
檢視 HTML Source,結果也是「中文」沒錯。
2. 把上面的內容以 JSP 的方式存檔,並且同樣 submit 出去,會得到底下的結果:
不注意看,會覺得結果都一樣啊,也得到想要的中文結果了,可是如果仔細去看 HTML Source 卻會看到:
因為我上述的 form 是以 get 的方式傳遞的,仔細去看網址:
http://localhost:8080/WebTest/EncodingTestServlet?name=%26%2320013%3B%26%2325991%3B&Submit=Submit+Query
原來 name 是以 name=%26%2320013%3B%26%2325991%3B 的方式去傳遞的,而 %26 跟 %23 分別是 & 跟 # URL encode 的結果,而 20013 跟 25991 則是 「中」跟「文」的 code position。這篇文章有解釋到 HTML Character Reference,有興趣的人可以自己看一下。
%26%2320013%3B%26%2325991%3B 這樣的結果對於 browser 來說,還是可以呈現正確的結果,可是如果今天我們是要把這個資料存到 Database,那就會出問題了。我們總不希望存在 Database 裡面的是一些 browser 才看的懂的資料吧?
上面會出現這樣的結果,也就是常會讓大家覺得 Java 的編碼為什麼會有很多問題的感覺。同樣的東西,怎麼使用 HTML 跟 JSP 出來看到的結果雖然一樣,但是實際上的內容卻又有差別。這個主要就是 JSP 檔案並不是直接就呈現內容,還得要透過轉成 servlet (java file) 然後再 compile 成 class 檔案,再印出到 browser 上,所以只要有些地方編碼不一致,就可能出現錯誤了。
這篇先點出問題,下一篇再說怎麼解決這樣的狀況。明天還要一早起來坐車,今天不能太晚睡了。
More......
Posted by
Jacky
at
16:51
0
comments
星期五, 1月 26, 2007
Jakarta Commons FileUpload

上傳檔案在 Web Application 開發中是很常遇到的需求,Jakarta 的 commons FileUpload package 提供了一個很不錯的檔案上傳功能,可以讓我們簡單的就完成檔案上傳的功能。
在 commons fileUpload 網站上有大概說明怎麼使用這個 package 做上傳,大致上的 code 如下:
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
Iterator itr = items.iterator();
while(itr.hasNext()){
FileItem item = (FileItem)itr.next();
if(item.isFormField()){
processFormField(item);
} else {
processUploadedFile(item);
}
}
因為現在我們使用的是上傳檔案的 form ( enctype="multipart/form-data" ),所以我們要抓從頁面傳過來的值不能直接使用 request.getParameter("parameter_name") 的方式,而是得要使用類似底下的方式:
// Process a regular form field
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
...
}
至於處理上傳檔案的部分則是類似底下的 code:
// Process a file upload
if (!item.isFormField()) {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
...
}
// Process a file upload
if (writeToFile) {
File uploadedFile = new File(...);
item.write(uploadedFile);
} else {
InputStream uploadedStream = item.getInputStream();
...
uploadedStream.close();
}
上面大部分的 code 都是從 commons fileUpload 網站上 copy 下來的,但是這些都是在當你上傳的檔案檔名是英文以及輸入的欄位資料也是英文的情況下才會正常 work。若你輸入的是中文,你就會發現亂碼問題又出現了。
其實這問題跟我上一篇寫的 UTF-8 有很大的相關。先說明要如何解決這問題:
1. 設定 ServletFileUpload 的 header encoding
upload.setHeaderEncoding("UTF-8");
2. 抓取參數 value 的時候加入 UTF-8
String value = item.getString("UTF-8");
除了這個,還有一些要注意到的地方,底下是我的 upload.jsp 內容: 
有空再繼續寫後續的東西好了,這篇主要還是先回歸到介紹 upload package 以及如何解決中文檔名以及中文輸入的問題。
More......
Posted by
Jacky
at
23:49
0
comments








