在J2EE平台中可以使用java.net和java.io提供的类来访问网络服务和文件系统。由于移动设备的处理器和内存有限,因此,他们并不适合运行在移动终端上。为移动信息设备制定一个灵活、易于扩展的联网框架,于是诞生了通用连接框架GCF。通用连接框架定义在CLDC1.0(JSR30)规范中,具体实现则留给了上层的简表,如MIDP。事实证明,GCF的设计非常成功,还有专门为J2SE平台定制的版本,通用连接框架是基于借口设计的,便于扩展[2]。
通用连接框架设计灵活,使用异常简单。首先,类建立到服务器端应用表示层的连接,然后为该连接分别建立两个数据缓冲区,客户端通过数据输入流和数据输出流来发送请求信息和接收响应信息。考虑到联网可能会堵塞用户界面,因此在该系统开发过程中,把联网操作在单独的线程中处理,而不在主线程中进行联网[3]。
⑵针对消息格式的设计
本系统中,MIDlet发送给Servlet的HTTP 请求信息只有三种:一是查询课程请求,二是更改用户信息请求,三是申请更新课程请求,鉴于安全需要三类请求都通过POST方法传输。
当课程查询时,MIDlet发送的POST请求中包含3个字段:、密码、Number(一个指示查询方式的数字)。Number=0表示查询最近学期的课程;Number=1~8表示查询指定学期的课程Number=9表示查询所有已修课程。因为服务器端的Servlet的目的是与手机中的MIDlet打交道,而不是与电脑中的Web 浏览器打交道,因此返回给客户端的查询结果采用了更加有效的纯文本格式而非
HTML格式[4]。该格式首先指出课程数目,然后是用换行符分隔的课程信息串。每门课程信息由3部分组成:课程名、成绩、学分。
当修改密码时,MIDlet发送的POST请求中也包含3个字段:、密码、新密码。尽管两类POST请求都包含3个字段,并且前两个字段完全一样,但是,Servlet不会混淆这两类请求,因为密码的长度通常不少于6个字符(MIDlet也会检测密码长度),Servlet可以根据最后一个字段的长度分辨出该POST请求是查询课程请求还是更改密码请求。更改密码时,Servlet返回的POST响应中,用1表示密码更改成功、0表示失败。
申请更新课程(即选课)时,MIDlet发送的POST请求中需包括课程号,,密码3个字段,与修改和查询一样Servlet不会混淆此三类POST请求,服务器端返回POST响应,1表示成功,0表示失败。
⑶访问网络时的死锁问题
为了解决因为网络流量过大造成的瓶颈问题以及提高数据库的访问效率,需通过数据库连接池技术实现数据库连接,实现多个请求共享公用资源。
死锁产生的原因正是由于事件处理线程和访问网络线程共享了共同的数据--MIDlet对象。两个线程都为获得MIDlet资源而相互争执,互不相让,也就出现了线程死锁。为了解决操作的不完整性问题,在JAVA语言中引入了对象互斥锁的概念,用来保证共享数据操作的完整性。每一个对象都应用于一个可称为互斥锁的标记,这个标记用来保证在任一时刻只能有一个线程访问该对象。关键字synchronized与对象的互斥关系,当某个对象用synchronized修饰时,表示该对象在任一时刻只能有一个线程访问[5]。
JAVA技术使用wait()和notify()来解决线程之间的交互。如果线程对一个同步对象x发出一个wait()调用,该线程会暂停执行,直到另一个线程对同一个同步对象x也发送一个wait()调用。
然而为了让线程对一个对象调用wait()和notify(),线程必须锁定那个特定的对象,也就是说,只能在他们被调用的实例的同步块内使用wait()和notify()。而当线程执行包含对一个特定对象执行wait()调用的同步代码时,那个线程被放到了相关对象的等待池中,调用wait()方法的线程会自动释放对象的锁标志。调用wait()方法时必须进行异常处理。
另一方面,在对一个特定对象执行notify()调用时,将对象的等待池中移走一个任意的线程,并放到锁池中,那里的对象一直在等待,直到可以获得对象的锁标记。只有锁池中的线程能获得对象的锁标记。锁标记允许线程从上次因调用wait()而中断的地方开始继续运行[6]。
在本系统中,为了避免死锁现象,将访问网络设计成为一个独立的线程,当应用
程序想要访问网络时,可以将访问网络线程唤醒,调用notify()方法。网络访问结束后,调用wait()方法,使访问网络线程释放锁并处在等待状态。
⑷设计过程中的中文问题解决
方案 在服务器端做UTF8-GBK编码转换。Java语言本身采用unicode,在高版本加强了对国际化的支持,在服务器端转换编码就显得比较容些。
在无线客户端使用J2ME版本的URLEncode类将url要传送的参数进行编码转换,之后在服务器端进行解码。当然也可以把要上传的参数以输入流的方式上传,随后在服务器端把上传的参数据读取出来,得到上传后的utf-8参数后再进行编码转换。转换成能被数据库识别的GBK编码[7]。
无论是
JSP还是servlet在访问数据库后得到的编码都是数据库的编码值,可以通过在数据库jdbc驱动的url中设置将其返回的编码进行转换。当然也可以流的方式写出到网页。还可以通设置网页返回属性进行[8]。
在无线客户端以字节流的方式读取字节数据之后进行编码重组,如果客户端仅支持utf-16,还可以进行utf-8到Unicode的编码转换。
3. 研究步骤、方法及措施
本选课系统是在JDK1.6的编译环境下,运用Eclipse3.4.2绑定EclipseME 1.79作为开发主环境编写,并通过Tomcat6.0实现客户端与服务器的通信,后台数据库采用SQL Server 2005开发版。前期需要对JDK1.6进行安装并配置环境变量,且在windows中配置SQL Server数据源,最后在Ecl