J2EE客戶端應該有很多種的實現方法,可以用Web Service、RMI、EJB等很多技朮實現,最近開發中發現也可以用一種非常簡單的實現,那就是直接用Apache的HttpClient來實現。
這種實現有個很大的好處,就是服務器端可以很好地和Web應用結合,只是在原來的Web應用中添加一些用于客戶端訪問的Servlet。
首先大家應該都有一種觀念,Servlet就是要按照HTML的方法來生成Response,因為我們需要客戶端使用各種可能解析HTML的瀏覽器來展現,但是如果我們寫了一些不用瀏覽器解析的Servlet,直接產生String類型的Response給客戶端,更甚至可以產生一個Stream的Response,當然瀏覽器是無法正確解析,但是我們可以放一個我們自己的客戶端去解析返回的結果。
這中間就需要一種技朮,就是怎樣可以讓Java程式模擬瀏覽器,發送GET或是POST的請求給我們Server放置的Servlet,這個就是HttpClient了,它是一種使用Java發送HTTP Request,並得到Response的工具。
1.首先是簡單的訪問,如果返回的結果只是一個簡單的字串,那么我們可以在Servlet中直接使用out.println(YOUR_RESULT);這樣的語句來返回Response,客戶端則使用HttpClient提供的getResponseBodyAsString方法,得到Server返回的結果,這 里對這一方法做了個簡單的封裝,可以方便使用:
Server代碼:
/**
* write a given string to response
*
* @param result
* the string to send to client
* @param response
* the response to transfer string
* @throws IOException
*/
protected void writeStringToResponse(String result,
HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
out.print(result);
out.flush();
out.close();
}
Client代碼:
public static String getResponseAsString(String uri) throws HttpException, IOException {
String result = "";
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(uri);
client.executeMethod(method);
if (method.getStatusCode() != HttpStatus.SC_OK) {
throw new HttpException("execute failed " + method.getName());
}
result = method.getResponseBodyAsString();
method.releaseConnection();
return result;
}
該方法支持直接傳入一個URL,返回Response中的字串。
2.如果需要從Server返回一個復雜的Object類型的對象,那我們可以使用Java提供的序列化技朮,在Servlet中將對象序列化之后直接寫入Response中,客戶端使用getResponseBodyAsStream方法來讀取,然后進行反序列化,得到相應的對象。同樣對關鍵代碼做了封裝,代碼如下:
Server代碼:
/**
* write a given object to response
*
* @param object
* the object to send to client
* @param response
* the response to transfer object
* @throws IOException
* throws when exception
*/
protected void writeObjectToResponse(Object object,
HttpServletResponse response) throws IOException {
OutputStream out = response.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
objectOutputStream.writeObject(object);
out.flush();
out.close();
}
Client代碼:
public static Object getResponseAsObject(String uri) throws HttpException, IOException, ClassNotFoundException {
Object result = null;
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(uri);
client.executeMethod(method);
if(method.getStatusCode() != HttpStatus.SC_OK){
throw new HttpException("execute failed: " + method.getName());
}
result = new ObjectInputStream(method.getResponseBodyAsStream()).readObject();
method.releaseConnection();
return result;
}
以上兩個都是使用GET的方法請求,當然也可以使用POST方法做請求。
3.POST方法發送請求,其它相同,只是發送請求時有所不同,同樣對代碼作了封裝,代碼如下 :
Client Post 請求代碼:
public static String postResponseAsString(String uri, Map<String, String> parameter) throws IOException {
String result = "";
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(uri);
Iterator<String> it = parameter.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
NameValuePair pair = new NameValuePair(key, parameter.get(key));
method.addParameter(pair);
}
client.executeMethod(method);
result = method.getResponseBodyAsString();
method.releaseConnection();
return result;
}
其中第二個參數為Post參數列表,另外postResponseAsObject與前面相似,這里不給出代碼。