2008年11月24日 星期一
JDK 6.0自帶web service
我 以前也用java開發過web service ,但是當初用了一個apache下axis開源項目。如果axis夜進化了,反正我不認識了。不過java自帶有何必捨近求遠呢。今天我就把自己創建的最 簡單java webservice範例過程記錄下來,與大家分享。
我用的是netbeans 6,首先建立一個java應用程序工程,名為WebServices。建立一個服務端程序。
package WebServices;
import javax.jws. * ;
import javax.xml.ws.Endpoint;
/**
* @author hecm
*/
@WebService(targetNamespace = " http://www.blogjava.net/JAVA-HE " , serviceName = " HelloService " )
public class WSProvider
{
// @WebResult(name = "Greetings") //自定義該方法返回值在WSDL中相關的描述
@WebMethod(action = " sayHi " , operationName = " sayHi " )
public String sayHi(@WebParam(name = " MyName " ) String name)
{
return " Hi, " name; // @WebParam是自定義參數name在WSDL中相關的描述
}
@Oneway //表明該服務方法是單向的,既沒有返回值,也不應該聲明檢查異常
@WebMethod(action = " printSystemTime " , operationName = " printSystemTime " ) //自定義該方法在WSDL中相關的描述
public void printTime()
{
System.out.println(System.currentTimeMillis());
}
public static void main(String[] args)
{
Thread wsPublisher = new Thread( new WSPublisher());
wsPublisher.start();
}
private static class WSPublisher implements Runnable
{
public void run()
{
//發布WSProvider到http: // localhost:8888/hechangmin/WSProvider這個地址,之前必須調用wsgen命令
//生成服務類WSProvider的支持類,命令如下:
// wsgen -cp . WebServices.WSProvider
Endpoint.publish("http://localhost:8888/JAVA-HE/WSProvider", new WSProvider());
}
}
}
當然建立對應的包,就不用說了。
然後編譯文件。
進入命令提示符下,進入classes目錄,運行:wsgen -cp . WebServices.WSProvider
可以看到將剛才的class生成了幾個java文件和class文件。
現在要做的是發布ws到http://localhost:8888/chinajash/WSProvider
而實際上的動作就是:Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
當然直接運行WSProvider 。
然後輸入http://localhost:8888/JAVA-HE/WSProvider?wsdl
就已經查看到生成的wsdl (webservice描述語言)。
也就是服務端就OK了。
保持運行。編寫一個測試客戶端:
首先選擇項目,右鍵新建web服務客戶端。其中ws url填入剛才生成的wsdl地址:
http://localhost:8888/JAVA-HE/WSProvider?wsdl
(實際上:和wsimport http://localhost:8888/JAVA-HE/WSProvider?wsdl一樣的效果)
產生一個效果:在classes下按照之前指定的名字空間產生的包下(目錄結構)生成了7個幫助class。
然後我們建立一個包client建立測試文件:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package client;
import net.blogjava.java_he. * ;
/**
*
* @author hecm
*/
public class Test {
public static void main(String args[])
{
HelloService hs = new HelloService();
WSProvider ws = hs.getWSProviderPort();
System.out.println(ws.sayHi( " hechangmin " ));
ws.printSystemTime();
}
}
運行這個測試類:
Hi,hechangmin
輸出了。順利完成!
一點個人經驗,你發布的地址最好寫成可配置。還有就是wsdl中會嚴格按照你指定的url來訪問,比如你指定的127.0.0.1那麼你用本機IP的時候也許並不能順利訪問。
Source: http://www.blogjava.net/JAVA-HE
2008年11月16日 星期日
How To Develop iPhone Applications in Java
Previously I have provided two ways how Java developers can install, compile and run iPhone applications on Java. Today I will present a third method.
Apple's SDK for the iPhone, as you know, is based on Objective-C as the development language as well as Cocoa for the GUI.
Unfortunately Apple's super-restrictive license agreement for the iPhone SDK prohibits the porting of the Java virtual machine to the iPhone. Today we will talk about how we can use Open Source Java to run applications which will run on Apple's iPhone. The open source project by Arno Puder, Associate Professor at the San Francisco State University, uses a cross-compiler to convert Open Source Java code to Objective-C and provide a Java-based implementation of the Cocoa library. With the help of these tools, iPhone applications can be written in pure Java.
Using the Java version of Cocoa, it is possible to run a Java-based iPhone application as a Java desktop/applet application that can be cross-compiled to run natively on the iPhone.
You can find more details about the software from http://www.xmlvm.org/
XmlVM's SourceForge.net Subversion repository can only be checked out through SVN with the following instruction set:
svn co https://xmlvm.svn.sourceforge.net/svnroot/xmlvm xmlvm
Warning: This is a generic Subversion checkout command which will pull all modules, tags and/or branches of the project. In most cases, you will want to add '/trunk' to the HTTPS URL above to check out only trunk (main development line).
Each of the boxes in the diagram above represents an artifact while the arrows denote the various transformations between those artifacts. The input to the XMLVM toolchain is either a Java class file or a .NET executable. A Java class file is translated to XMLVMJVM which is an XML-document describing the contents of that class file. Likewise XMLVMCLR is an XML-document describing the contents of a .NET executable. XMLVMCLR can be cross-compiled to XMLVMJVM with the help of a data flow analysis (DFA) which is shown as XMLVMCLR-DFA in the figure below. XMLVMJVM serves as a canonical representation as it acts as a boundary between the front- and back-end of the cross-compiler. Once XMLVMJVM has been generated, it can be mapped to various high-level programming languages. It is also possible to map XMLVMJVM to a Java class file again.
Check it out. Also don't forget to read the detailed guide on how to install, compile & run Java applications on iPhone.
2008年11月4日 星期二
Digital Signal Processing (DSP) Tutorial
1489 Plotting 3D Surfaces using Java
1492 Plotting Large Quantities of Data using Java
100 Periodic Motion and Sinusoids
104 Sampled Time Series
108 Averaging Time Series
400 Processing Image Pixels using Java, Getting Started
402 Processing Image Pixels using Java, Creating a Spotlight
404 Processing Image Pixels Using Java: Controlling Contrast and Brightness
406 Processing Image Pixels, Color Intensity, Color Filtering, and Color Inversion
408 Processing Image Pixels, Performing Convolution on Images
410 Processing Image Pixels, Understanding Image Convolution in Java
412 Processing Image Pixels, Applying Image Convolution in Java, Part 1
414 Processing Image Pixels, Applying Image Convolution in Java, Part 2
416 Processing Image Pixels, An Improved Image-Processing Framework in Java
418 Processing Image Pixels, Creating Visible Watermarks in Java
450 A Framework for Experimenting with Java 2D Image-Processing Filters
452 Using the Java 2D LookupOp Filter Class to Process Images
454 Using the Java 2D AffineTransformOp Filter Class to Process Images
456 Using the Java 2D LookupOp Filter Class to Scramble and Unscramble Images
458 Using the Java 2D BandCombineOp Filter Class to Process Images
460 Using the Java 2D ConvolveOp Filter Class to Process Images
462 Using the Java 2D ColorConvertOp and RescaleOp Filter Classes to Process Images
1478 Fun with Java, How and Why Spectral Analysis Works
1482 Spectrum Analysis using Java, Sampling Frequency, Folding Frequency, and the FFT Algorithm
1483 Spectrum Analysis using Java, Frequency Resolution versus Data Length
1484 Spectrum Analysis using Java, Complex Spectrum and Phase Angle
1485 Spectrum Analysis using Java, Forward and Inverse Transforms, Filtering in the Frequency Domain
1486 Fun with Java, Understanding the Fast Fourier Transform (FFT) Algorithm
1487 Convolution and Frequency Filtering in Java
1488 Convolution and Matched Filtering in Java
1490 2D Fourier Transforms using Java
1491 2D Fourier Transforms using Java, Part 2
1510 A Recursive Filtering Workbench in Java
1511 The Driver Class for the Recursive Filtering Workbench in Java
1512 The User Input GUI for the Recursive Filtering Workbench in Java
1513 The Recursive Filtering Workbench in Java, Putting it all Together
...
Adaptive Filtering
2350 Adaptive Filtering in Java, Getting Started
2352 An Adaptive Whitening Filter in Java
2354 A General-Purpose LMS Adaptive Engine in Java
2356 An Adaptive Line Tracker in Java
2358 Adaptive Identification and Inverse Filtering using Java
2360 Adaptive Noise Cancellation using Java
2362 Adaptive Prediction using Java
...
2444 Understanding the Discrete Cosine Transform in Java
2446 Understanding the 2D Discrete Cosine Transform in Java
2448 Understanding the 2D Discrete Cosine Transform in Java, Part 2
http://www.dickbaldwin.com/tocdsp.htm
2008年10月28日 星期二
關於權限控制策略的討論
我要實現的功能是:
1.對系統菜單(頁面)的控制,不可訪問的不顯示;
2.對頁面上的具體操作進行控制,如該用戶對該模塊只有查詢權限,不能修改、刪除。
對於第一點,我可以做到。根據當前登錄的用戶,獲取他擁有的角色,進而獲取他可訪問的全部模塊列表,顯示這些可以訪問的模塊。
對 於第二點,我有個想法,在數據庫中,對模塊的訪問設定級別,1-全部操作;2-只能查詢。這樣的話,顯示頁面時,判斷該用戶對該頁面的訪問級別,若為1, 顯示“增加、刪除”按鈕,若為2,只顯示查詢按鈕。但這樣的話,實際上時把權限控制的代碼寫到了各個頁面,很不雅觀。
對合同管理模塊,我們在公司權限系統中新增了五種角色:合同錄入人、合同查閱人、合同審核人、合同管理員、超級管理員。在合同管理權 限設置中,對員工賦角色,一個角色可能有多個員工,而一個員工可能也有多個角色。然後設置一員工所能夠管理的部門。基本業務邏輯是,誰(員工)對何部門有 何權限(5種角色)。
上述系統涉及到以下幾張表:
1.角色表。 (ID),角色名,描述。
2.用戶表。 (HrID),描述。
3.部門表。 (DeptID),描述。
4.部門-角色-用戶表。 (ID,HrID,DeptID)。
在表4中,完成上述的業務邏輯,也即“誰對何部門有何權限”。這裡的權限是用角色名來標識,比如合同錄入人這個角色,擁有合同錄入的 權限,合同查閱人這個角色,擁有查閱合同的權限。而部門的樹形結構,則是依賴於DeptID。 DeptID由12位數字構成,每兩個1組,由左至右分別對應部門的級別。比如010500000000代表**公司**部門。實際使用時,通過like ‘01%’,like ’0105%‘判斷員工所管理的部門(個人認為,這里相當Cool)。
我們用公司現有的權限系統來管理角色,增加部門-角色-用戶映射表來管理權限,在前台頁面中完成用戶的授權。這種設計結構相對清 楚,但在應對高靈活的情況是,可能力不從心,比如要增加合同確認這一功能,那麼必須在增加合同確認人角色等。所以有以下一些考慮。
1.將角色和角色所具有的操作分離,常見的操作包括Insert(新增),Select(查看),Update(更新),Delete等操作。用一個素數 對應這四個操作,分別為2,3,5,7。將角色和操作的對應關係放入數據庫。比如合同錄入人所擁有的操作對應2,而合同查閱人對應3,合同審核人對應3, 合同管理員對應3*7。在Unix系統中,採用1,2,4對應讀、寫、執行三種操作,將這三種標識碼相加,對應組合操作。
2.角色體現在業務流程上,如審核人只有讀的操作,流程上可以對一個合同審核通過,或者是駁回重填。
在《關於權限系統的探討》一文中,還考慮了“限定內容列表”,以區分能夠被操作的表、字段。由(ID)、名稱、描述構成。比如在我們的這個合同管理系統中,可能就是A用戶可以修改數據庫裡的這幾個表,而B用戶只能修改數據庫裡的那幾個表。
Simple is beautiful! 發覺自己思路開始混亂。這樣設計複雜,同時和原有的系統並不兼容,純屬遐想。
http://topic.csdn.net/t/20030413/09/1653829.html
2008年10月24日 星期五
FFT - Fast Fourier Transform Program (Algorithm)
Copy From http://people.csail.mit.edu/hammond/teaching/hide/fft/
public class fft
{
private double[] YREAL;
private double[] YIMAG;
private double[] XREAL;
private double[] AFFT;
private double[] BFFT;
private double[] COSX;
private double[] SINX;
private int[] POW;
fft(String[] datapoints)
{
try
{
// put the given values in to an array
YREAL = makeRealArray(datapoints);
YIMAG = makeImaginaryArray(datapoints);
// make array of x values
XREAL = makeXArray(Integer.parseInt(datapoints[0]));
// the given values function are starting values for
// Fourier Results
AFFT = YREAL;
BFFT = YIMAG;
// make cos(x) array and sin(x) array
COSX = makeCosXArray(XREAL);
SINX = makeSinXArray(XREAL);
// generate power array
POW = makePowerArray(Integer.parseInt(datapoints[0]));
// actual fft calculation done here
calculateABValues(Integer.parseInt(datapoints[0]));
// unscramble the vertices according to POW values
unscramble();
}
catch (Exception e)
{
System.out.println("Exception " + e.toString());
e.printStackTrace();
System.exit(-1);
}
for(int i = 0; i < realarray =" new" i =" 0;" imaginaryarray =" new" i="0;" xarray =" new" i =" 0;" cosxarray =" new" i =" 0;" sinxarray =" new" i =" 0;" powerarray =" new" i =" 0;" totalnumberofruns =" (int)" i =" 1;" j =" 1;" j =" 0;" i =" 0;" stage =" 1;" numberofsets =" 1;" cyclelength =" NumberOfData/2;" k =" 0;" tempa =" AFFT;" tempb =" BFFT;" setnumber =" 1;" i =" 0;" j =" (i" l =" POW[(int)(k/cycleLength)];"> AFFT.length || l > AFFT.length || j+cycleLength > AFFT.length)
System.out.println("HELP");
TEMPA[k] = AFFT[j] + COSX[l]*AFFT[j+cycleLength] - SINX[l]*BFFT[j+cycleLength];
TEMPB[k] = BFFT[j] + COSX[l]*BFFT[j+cycleLength] - SINX[l]*AFFT[j+cycleLength];
k++;
}
}
AFFT = TEMPA;
BFFT = TEMPB;
stage++;
NumberOfSets *= 2;
cycleLength /= 2;
k = 0;
} while (stage <= (int)(Math.log(NumberOfData)/Math.log(2))); } /** * Method: unscramble * Input: none * Output: none * Function: Rearranges the A and B values */ private void unscramble() { double[] tempA = AFFT; double[] tempB = BFFT; for (int i = 0; i < length ="=" data1 =" {" alg =" new" i =" 0;"> Integer.parseInt(args[0]))
printUsage();
} while (true);
// make sure number entered equals the number of
// datapoints
if ((args.length - 1)/2 != Integer.parseInt(args[0]))
printUsage();
}
catch (Exception e){
// probably error in input
printUsage();
}
// all is good.
// start the program (Fast Fourier Transform)
fft alg = new fft(args);
}
private static void printUsage()
{
System.out.println("Fast Fourier Transform");
System.out.println("Returns the fft of a list of data points");
System.out.println("--usage");
System.out.println(" fft number datapoints");
System.out.println();
System.out.println("Number must be the number of datapoints");
System.out.println("Number must be power of 2");
System.out.println("Datapoints must be written as: y1real y1imaginary y2real y2imaginary...");
System.out.println("X values are considered to be standardized on [0,2*pi]");
System.out.println();
System.exit(0);
}
}
2008年10月20日 星期一
Java Focus 簡談
JAVA的組件分為重量級和輕量級組件,區別在於重量級組件實例的成員peer-對等體,其行為緊密依託本地系統的GUI行為函數庫來進行實現。比如一個 JFRAME,當setvisible時,會依托peer.show進行屏幕繪製行為,該行為會通過本地系統GUI行為函數庫完成;這樣一來,當其被點擊 時,本地系統會依據最初調用本地GUI函數繪製時留下的信息,從而能夠經底層處理後(比如將該鼠標事件附加peer標記信息,同時可能經底層分析需要構造 出一個可能的focus_gain事件,則在操作系統層面登記當前聚焦GUI組件等)準確將底層GUI事件派送給該JVM進程,該事件因而在jvm進程中 的AWT-Windows線程loop獲取到,並通過事件提供的peer標記最終確定目標為重量級組件JFRAME,因此一個source== JFRAME的AWTEvent被構造出來並最終分派給EDT進行後續處理。
事件機制是程序中家喻戶曉的設計模式了。但是,看java的focus實現中對這個機制似乎多少有些不那麼絕對的清晰J。
個 人理解,事件的含義就是某種定義的情況發生了。比如點擊鼠標這個動作可以說觸發了多個事件,如press,release,click等,分別指發生了鼠 標button1按下,放開,完成點擊的情況。 button1按下這個事件比起完成點擊就要更基礎一些,因為完成點擊指的是一個由按下,放開動作序列組合的情況發生了。
那麼對於focus,focus_gained,focus_lost這兩個事件應該是指某組件獲得焦點或失去焦點的情況發生了,反映在機器裡,應該是某種指向當前聚焦組件的全局變量發生了更新。
然而在java awt實現裡,概念混亂出現啦。
如 果awt_windows loop到了focus事件,一,這個事件一定是目標向重量級組件的;二,此時,這個事件對於底層系統的對等組件,focus_gainded是發生了 (底層系統標記當前聚焦組件的全局變量已經更新;底層操作系統沒有mess,總是在真正focus改變後才分發focus事件),然而在java層面,截 至到awt_windows loop到底層focus事件並包裝成FocusEvent放置到EVENT QUEUE時,java層面並沒有更新jvm裡的全局變量。所以我個人認為這個時候就不應該包裝成FocusEvent,至少不應該叫這個名字,應該叫 PrepareFocusEvent,嘿嘿。
澄清事件機制的概念後,回頭看java focus要實現的目標。
1.當用戶從別處聚焦點切換到某文本框時(通過約定好的一些鍵盤鼠標操作,比如鼠標點擊或其他可能的動作),需要更新JAVA全局變量使該文本框成為聚焦組件,而後通知該組件的事件監聽focusgainedlistener。
當 前的難點是,輕量級組件雖可以設計在組件切換操作(如mouse_press)的listener中實現全局變量更新,然而問題是如果輕量級組件的容器是 一個重量級組件,比如一個Panel,而此時它的本地對等組件在本地系統中很可能還沒有獲得焦點。若實現上只是在切換操作監聽中簡單的把java的全局變 量更新了,那系統中就會在此時間出現兩個聚焦組件:一個是底層系統承認的原來的某底層對等組件,一個是java裡認為的現在的jtextfield。在這 個時空裡界面將很難不混亂,你很可能會看到最顯眼的是有一個亮亮的TextField,而那個上面有“已經聚焦”的jtextfield的panel面板 卻灰灰的,而你輸入的一個個字符竟然在灰灰的jtextfield中顯示出來。
2.可以提供某方法供應用調用,比如setfocus指定某組件聚焦。
難 點是根據前面的分析,指定輕量級組件聚焦,則要在處理中要通知其重量級容器對應的本地對等組件聚焦並等到它確實聚焦完成了再更新JAVA的全局變量。若實 現上真就是在setfocus調用中直接調用底層setfocus,問題出現在即使底層系統根據調用通知更新了focus,馬上還會繼續對外設可能的焦點 切換操作響應(可以認為有一個系統進程在處理外設的響應),很有可能別的C應用就在此時再要求focus,於是接著就更新了底層的focus登記;而我們 的setfocus調用卻是在jvm進程的某線程中,顯然這就是個並發的情景,這樣,很有可能我們的對本地對等組件的通知發過去並返回了,那邊底層系統就 馬上切換到了C的某個組件focus,而我們的線程繼續更新JAVA的全局focus變量並隨後發布 focus_gained(target==jcomponent),於是又出現了不一致的場景。難道我們要同步這兩個進程,讓系統進程等待我們的調用 setfocus的線程返回再繼續運行,顯然那樣是不合理的。 (JAVA只能服從OS,不能讓OS服從JAVA。---出自《英雄亂語》J)
鑑於1,2的分析,java focus的實現是setfocus是requestfocus,意思是只是將這個切換焦點的請求登記上但並不實際切換focus;隨後如果重量級組件聚焦了再處理request並徹底完成focus切換。
3.聚焦組件後馬上獲得隨後的鍵盤事件。
難 點是按用戶的實際想法,mouse_press後,馬上就要鍵盤拼寫,鍵盤的輸入應該target到mouse_press的jtextfield。根據 前面的分析,mouse_press響應中requestfocus/setfocus後並沒有意味著切換焦點已經完成。若實現上對於後續的鍵盤事件只是 簡單地根據JAVA的那個全局focus變量target,則這些鍵盤事件將不會target到期待的組件上。
鑑於3的分 析,java focus的實現是requestfocus時,如果這個請求按普遍規則一定通過而只是在等待時機,那麼在處理這個請求返回前就登記一個時間戳,在這個時 間戳之後在下一個requestfocus時間戳之前,EDT逐個取的keyevent都將target到該組件並登記,直到該組件徹底聚焦完成後,馬上 把這些keyevent dispatch。
4.需要支持TAB鍵等焦點遍歷操作。
這一點JAVA有一個遍歷模型,如下:
具體參照http://java.sun.com/javase/6/docs/api/java/awt/doc-files/FocusSpec.html
該要求並沒有難點。實現上只要對keyevent監聽,並根據規則進行合適處理即可。
2008年10月18日 星期六
JAVA 6 讓 Webservice 變簡單
JAVA 6 的出現,拯救了像我這種怕麻煩的人 ...
關鍵在於兩個 annotation: @WebService 和 @WebMethod
參考了 Vivek Pandey's Blog 和 学习Java6(一) WebServices(3)在tomcat中发布,簡單地整理開發 Webservice 的 Server 端和 Client 端程式的過程,以及如何部屬到 Tomcat:
參考 Vivek 的範例,寫一個加法的 Webservice
Server Side
WebServiceStarter.java
public class WebServiceStarter extends HttpServlet{
private static final long serialVersionUID = 5870534239093709659L;
public WebServiceStarter() {
super();
}
public void destroy() {
super.destroy();
}
public void init() throws ServletException{
System.out.println("\nStarting Calculator Service ......\n");
try{
Endpoint.publish("http://localhost:8088/calculator", new Calculator());
}catch (Exception e){
System.out.println("Caught Exception: " + e.toString());
}
System.out.println("\nCalculator Service is OK!\n");
}
}
在 Endpoint.publish 的部份,原本以為 Port 的設定應該與 Tomcat 的預設值 8080 一樣,但是在啟動 Tomcat 的時候發現會跟 Tomcat 搶 8080 Port,所以我改成 8088。
加法的 Service:Calculator.java
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
public class Calculator{
@WebService(targetNamespace = "http://localhost/sample")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class Calculator {
@WebMethod
public int add(int a, int b) {
return a+b;
}
}
Deploy
程式編譯好後,在 Tomcat 的 webapps 目錄下建立一個 Service 的目錄,如: sample,其內在建立 WEB-INF 目錄,在此目錄裡建立 web.xml:
web.xml
在 WEB-INF 裡面在建立 classes 的目錄,把編譯好的 Calculator.class 和 WebServiceStarter.class 複製到裡面,重新啟動 Tomcat。檢視 Tomcat 的 log :
catalina.out
Jun 29, 2007 5:16:16 PM org.apache.catalina.core.AprLifecycleListener init
INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/lib/jvm/java-6-sun-1.6.0.00/jre/lib/i386/client:/usr/lib/jvm/java-6-sun-1.6.0.00/jre/lib/i386:/usr/lib/jvm/java-6-sun-1.6.0.00/jre/../lib/i386:/usr/java/packages/lib/i386:/lib:/usr/lib
Jun 29, 2007 5:16:16 PM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Jun 29, 2007 5:16:16 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 875 ms
Jun 29, 2007 5:16:16 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Jun 29, 2007 5:16:16 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.13
Starting Calculator Service ......
Calculator Service is OK!
Jun 29, 2007 5:16:18 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Jun 29, 2007 5:16:18 PM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Jun 29, 2007 5:16:18 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/43 config=null
Jun 29, 2007 5:16:18 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2077 ms
這樣 Server 端就 OK 了!
Java Client
先產生需要的 class: wsimport -keep
http://localhost:8088/calculator?wsdl
CalculatorApp.java
class CalculatorApp {
public static void main(String args[]){
/**
* Instantiate the generated Service
*/
CalculatorService service = new CalculatorService();
/**
* Get the port using port getter method generated in CaculatorService
*/
Calculator calculatorProxy = service.getCalculatorPort();
/**
* Invoke the remote method
*/
int result = calculatorProxy.add(10, 20);
System.out.println("Sum of 10+20 = "+result);
}
}
編譯,執行,結果應該是:Sum of 10+20 = 30
Flex Client
用 Flex 做一個比較好用的 GUI:
測試網址:http://ir.tmu.edu.tw/calc/
有沒有很簡單呢,呵呵!
