今天突然心血来潮想写写关于j2me开发一些心的。
因为项目需要需要使用j2me开发,并且需要调用远程服务器,开始使用JSR 172开发,后来发现很多手机并不支持JSR 172,如果您是针对特定机型来开发并且那款机器支持JSR 172标准的话,恭喜你,我的教程您可以不用看了,因为用JSR 172开发超级简单。
好了回到正题,正式开始讲解。
首先说点废话,您需要下载、以及kxml2。
下载地址:http://downloads.sourceforge.net/ksoap2/ksoap2-j2me-core-2.1.2.jar?modtime=1173974533&big_mirror=0
http://downloads.sourceforge.net/kxml/kxml2-2.3.0.jar?modtime=1151079308&big_mirror=0
您可以去这里下载,下载好了导入你的工程即可。
剩下的当然就是代码啦。。。呵呵
由于我是直接从项目中拷贝出来的,所以一些细节东西我就不进行更改了
现在贴上核心代码:
String serviceNamespace = WebServiceUrl.URL + "service/SalesDataCollectionService";//WebServiceUrl.URL 这里面存放了一个具体的url地址便于 我调试使用,我的地址里面写的其实是 http://localhost:8080/
String serviceURL = WebServiceUrl.URL + "service/SalesDataCollectionService";//具体用处不是很大,因为和上面的地址是一样的,用上面的地址也是一样能跟完成的。
String methodName = "getXtm12ByXtwpdm";//调用的具体方法。这个方法需要传入一个参数,返回一个bean给用户。
SoapObject request = new SoapObject(serviceNamespace, methodName);//这里是一些准备工作,具体用处我就不多介绍了,因为我也不是很明白
request.addProperty( "xtwpdm",getTextFieldXtwpdm().getString());//这里是传入的参数,如果是多条参数就多复制几下就行了。他是一个键值对应的,其实也是按添加顺序来做的,你只要按照顺序往里面添加就行了,不过我的习惯是按照服务器端的名字对应填入键值。
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);//类似于创建了一个连接工厂,因为我英语很烂,所以具体什么意思我也没弄明白,反正照着敲就不会错。
envelope.bodyOut = request;//将填入参数的request放入envelope 当中
(new MarshalBase64()).register(envelope);//需要做一下转码,其实用处不是很大,不过做总比不做好。要不不同的系统谁知道会出现什么问题呢。
HttpTransport ht = new HttpTransport(serviceURL);//创建连接了
ht.debug = true;//可以为false
ht.call(null, envelope);//调用webservice了
if(envelope.getResponse()!=null){//判断是否返回结果,因为我这个是一个查询操作,是带有返回值的。byte[] bb = Base64.decode(envelope.getResponse().toString());将返回的结果进行转码,从string类型转换为byte[]数组,这个在后面我会介绍的,不要着急。
Xtm12Form xtm12 = Xtm12Form.deserialize(bb);//这个就是我们希望得到的那个bean。//bean的源码我会在后面公开的。
//既然得到的你要的bean了,剩下的就是你自己的事情了,自己该怎么向下进行都ok了。
//这个就是ksoap2的精华所在了。
}
下面给大家看看 我服务器端的代码
public byte[] getXtm12ByXtwpdm(String xtwpdm) {
Xtm12 x = this.xtm12DAO.findById(xtwpdm);//得到我要的结果了
Xtm12Form xf = new Xtm12Form();//将结果进行了封装
xf.setKcjldw(x.getKcjldw());//因为涉及到商业机密,就简单的列出一个set方法了。
return xf.serialize();//返回是要求是byte[],所以我在bean中做了一下封装。
}
现在该看看精华了Xtm12Form bean 的源码,
package com.MobileRDA.FormBean;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import com.MobileRDA.StringVector;
public class Xtm12Form {
private String xtwpdm = "";
private StringVector wsvPersonName = new StringVector();//这就是进行二进制转换的类,我们将来在网络上传输的任何东西都是用二进制传输的,然后在将二进制转换回我们需要的东西。
public String getXtwpdm() {
return xtwpdm;
}
public void setXtwpdm(String xtwpdm) {
this.xtwpdm = xtwpdm;
}
public static Xtm12Form deserialize(byte[] data) {//将二进制还原为我们所需要的类
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
Xtm12Form wc = new Xtm12Form();
try {
wc.xtwpdm = dis.readUTF();
bais.close();
dis.close();
} catch (Exception exc) {
// exc.printStackTrace();
}
return wc;
}
public byte[] serialize() {//将我们的类转换为二进制便于网路传输。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeUTF(xtwpdm);
wsvPersonName.writeObject(dos);
baos.close();
dos.close();
} catch (Exception exc) {
// exc.printStackTrace();
}
return baos.toByteArray();
}
}
StringVector类的源码:
/**
* Vector主要用来保存各种类型的对象(包括相同类型和不同类型的对象)。
* 但是在一些情况下使用会给程序带来性能上的影响。这主要是由Vector类的两个特点所决定的。
* 第一,Vector提供了线程的安全保护功能。即使Vector类中的许多方法同步。
* 但是如果你已经确认你的应用程序是单线程,这些方法的同步就完全不必要了。
* 第二,在Vector查找存储的各种对象时,常常要花很多的时间进行类型的匹配。
* 而当这些对象都是同一类型时,这些匹配就完全不必要了。
* 因此,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector类
*/
package com.MobileRDA;
public class StringVector{
// 这儿的transient标示这个属性不需要自动序列化
private transient String[] data;
private int count;
public int size() {
return count;
}
public StringVector() {
// default size is 10
this(10);
}
public StringVector(int initialSize) {
data = new String[initialSize];
}
public void add(String str) {
// ignore null strings
if (str == null) {
return;
}
ensureCapacity(count + 1);
data[count++] = str;
}
private void ensureCapacity(int minCapacity) {
int oldCapacity = data.length;
if (minCapacity > oldCapacity) {
String oldData[] = data;
int newCapacity = oldCapacity * 2;
data = new String[newCapacity];
System.arraycopy(oldData, 0, data, 0, count);
}
}
public void remove(String str) {
if (str == null) {
return; // ignore null str
}
for (int i = 0; i < count; i++) {
// check for a match
if (data[i].equals(str)) {
System.arraycopy(data, i + 1, data, i, count - 1); // copy data
// allow previously valid array element be gc'd
data[--count] = null;
return;
}
}
}
public final String getStringAt(int index) {
if (index < 0) {
return null;
} else if (index > count){
return null; // index is > # strings
} else{
return data[index]; // index is good
}
}
public synchronized void writeObject(java.io.DataOutputStream s) throws java.io.IOException {
// Write out array length
s.writeInt(count);
// Write out all elements in the proper order.
for (int i = 0; i < count; i++) {
s.writeUTF(data[i]);
}
}
public synchronized void readObject(java.io.DataInputStream s) throws java.io.IOException, ClassNotFoundException {
// Read in array length and allocate array
int arrayLength = s.readInt();
data = new String[arrayLength];
// 同步data的大小
count = arrayLength;
// Read in all elements in the proper order.
for (int i = 0; i < arrayLength; i++) {
data[i] = s.readUTF();
}
}
}
另外这个bean以及StringVector需要在服务器端和客户端都存在,不是一个单方面的。
好了,代码已经基本上写完了,剩下的就需要大家自己体会了。