在项目中采用的OSGi模块开发,采用的Vaadin框架。在Vaadin框架中调用JavaScript比较麻烦,这套框架基于GWT框架开发的一套组件,非常类似于Java的swing组件,对有一定得Java Swing开发经验的同志比较适合吧,我没有看到一点的便利,调用前台的东西显得非常的繁琐和麻烦。项目中采用了购置的加密UKey,实现客户端登陆的限制,需要通过提供的JavaScript接口进行对UKey进行操作,不得不编写JavaScript代码,国内采用这个框架的还比较少,查阅了官方的文档、论坛才得以解决该问题,做下记录、也希望能给用到该框架的朋友一点参考。
1、创建客户端小组件。右击选择新建向导->Vaadin->Vaadin Widget
2、编写客户端、服务器端的代码:创建类似的包结构
|
|--com.cn.readUKey.client
| |--NaviteJavaScript.java
| |--VUKey.java
|--com.cn.readUKey
| |--UKey.java
| |--UKeyWidgetset.gwt.xml
|--WebContent
| |--VAADIN
| |--WEB-INF
3、在Vaadin框架引用的theme下,VAADIN目录下添加JavaScript包和Widget编译之后的文件(我们项目采用的OSGi,在系统对自定义客户端组件进行注册,不知道在非OSGi项目下是否需要注册,我想也需要注册吧)
在theme目录下的结构:
4、部件源码添加到项目中
5、附带源码
调用JavaScript的JSNI代码:
package com.cvicse.unicorn.ukey.client;
/**
* 调用相应的Javascript本地方法
*
* 描述:<p> 功能描述,该部分必须以中文句号结尾。</p>
* 创建日期:2012-7-25 下午2:20:04<br>
* @author:tianyj<br>
* @update:$Date$<br>
* @version:$Revision$<br>
* @since 版本号,用来指定该类是从整个项目的哪个版本开始加入到项目中的
*/
public class NativeReadUKey{
public native static String readUKeyName()/*-{
var name = $wnd.getUserNameFromKey();
return name;
}-*/;
public native static String readUKeyPassWord()/*-{
var password = $wnd.getPasswordFromKey();
return password;
}-*/;
public native static String readUKeyInit()/*-{
var initAction = $wnd.init();
return initAction;
}-*/;
}
客户端代码:
package com.cvicse.unicorn.ukey.client;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
/**
* Client side widget which communicates with the server. Messages from the
* server are shown as HTML and mouse clicks are sent to the server.
*/
public class VUKey extends Widget implements Paintable{
/** Set the CSS class name to allow styling. */
public static final String CLASSNAME = "v-ukeyreadutil";
public static final String CLICK_EVENT_IDENTIFIER = "click";
/** The client side widget identifier */
protected String paintableId;
/** Reference to the server connection object. */
protected ApplicationConnection client;
/**
* The constructor should first call super() to initialize the component and
* then handle any initialization relevant to Vaadin.
*/
public VUKey() {
// TODO This example code is extending the GWT Widget class so it must set a root element.
// Change to a proper element or remove this line if extending another widget.
setElement(Document.get().createDivElement());
setStyleName(CLASSNAME);
// Tell GWT we are interested in receiving click events
sinkEvents(Event.ONCLICK);
}
/**
* Called whenever an update is received from the server
*/
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
if (client.updateComponent(this, uidl, true)) {
return;
}
this.client = client;
// Save the client side identifier (paintable id) for the widget
paintableId = uidl.getId();
String initAction = NativeReadUKey.readUKeyInit();
if (!"".equals(initAction) && null != initAction && "action".equals(initAction)) {
String name = NativeReadUKey.readUKeyName();
String pass = NativeReadUKey.readUKeyPassWord();
this.client.updateVariable(paintableId, "userName", name, true);
this.client.updateVariable(paintableId, "password", pass, true);
}
this.client.updateVariable(paintableId, "initAction", initAction, true);
}
}
服务器代码:
package com.cvicse.unicorn.ukey;
import java.util.Map;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractComponent;
/**
* Server side component for the VUKeyReadUtil widget.
*/
@com.vaadin.ui.ClientWidget(com.cvicse.unicorn.ukey.client.VUKey.class)
public class UKey extends AbstractComponent {
/**
*
*/
private static final long serialVersionUID = -2799113484905263109L;
/*private String message = "Click here.";
private int clicks = 0;*/
private String initAction = "";
private String userName = "";
private String password = "";
@Override
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
// Paint any component specific content by setting attributes
// These attributes can be read in updateFromUIDL in the widget.
/*target.addAttribute("clicks", clicks);
target.addAttribute("message", message);*/
// We could also set variables in which values can be returned
// but declaring variables here is not required
// target.addAttribute("nameOrpass", nameOrPass);
}
/**
* Receive and handle events and other variable changes from the client.
*
* {@inheritDoc}
*/
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
super.changeVariables(source, variables);
// Variables set by the widget are returned in the "variables" map.
/* if (variables.containsKey("click")) {
// When the user has clicked the component we increase the
// click count, update the message and request a repaint so
// the changes are sent back to the client.
clicks++;
message += "<br/>" + variables.get("click");
System.out.println(clicks);
System.out.println(message);
requestRepaint();
}*/
if (variables.containsKey("initAction")) {
initAction = variables.get("initAction") == null ? "" : variables.get("initAction").toString();
}
// 得到前台JS读取UKey中的用户名
if (variables.containsKey("userName")) {
userName = variables.get("userName") == null ? "" : variables.get("userName").toString();
}
// 得到前台JS读取UKey中的密码
if (variables.containsKey("password")) {
password = variables.get("password") == null ? "" : variables.get("password").toString();
}
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/**
* @return the initAction
*/
public String getInitAction() {
return initAction;
}
/**
* @param initAction the initAction to set
*/
public void setInitAction(String initAction) {
this.initAction = initAction;
}
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit super widgetset -->
<inherits name="com.vaadin.terminal.gwt.DefaultWidgetSet" />
<script src="/VAADIN/javascript/ukey.js"></script>
</module>
JavaScript:
// 声明UKey操作对象、设备路径
var aObject,devicePath;
/**
* 初始化设备操作对象
*/
function init() {
try {
// 建立操作锁的控件对象,用于操作UKey1000D锁
aObject = new ActiveXObject("Syunew3A.s_simnew3");
// 查找是否存在锁,这里使用了FindPort函数
devicePath = aObject.FindPort(0);
if( aObject.LastError!= 0 ) {
setTimeout('window.alert ( "没有找到UKey,请插入UKey")', 500);
// window.alert ( "没有找到UKey,请插入UKey");
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return "action";
}
/**
* 读取UKey中的用户名,使用默认的读密码"FFFFFFFF","FFFFFFFF
*/
function getUserNameFromKey() {
var ret,mylen,userName;
try {
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
ret = aObject.YReadEx(0,1,"ffffffff","ffffffff",devicePath);
mylen = aObject.GetBuf(0);
userName = aObject.YReadString(1,mylen, "ffffffff", "ffffffff", devicePath);
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return userName;
}
/**
* 读取UKey中的密码,使用默认的读密码"FFFFFFFF","FFFFFFFF
*/
function getPasswordFromKey() {
var ret,mylen,password;
try {
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
ret = aObject.YReadEx(20,1,"ffffffff","ffffffff",devicePath);
mylen = aObject.GetBuf(0);
password = aObject.YReadString(21,mylen,"ffffffff", "ffffffff", devicePath);
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return password;
}
/**
* 读取UKey的ID方法
*/
function getKeyID() {
var keyID;
try {
init();
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
keyID = toHex(aObject.GetID_1(devicePath))+toHex(aObject.GetID_2(devicePath));
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return keyID;
}
/**
* 返回随机数加密之后的结果
* @param rand 服务器端传递的随机数
* @return 返回的随机数加密之后的结果
*/
function getResultRand(rand) {
var randResult;
try {
init();
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
randResult = aObject.EncString(rand,devicePath);
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return randResult;
}
/*
*-82 表示写数据到加密锁储存器时错误,可能是写密码错误;
*-81 代表输入的地址空间超出
*-47 代表进行读写字符串时,地址空间超出
*-88 代表输入的地址空间超出
*-92 代表不存在指定的加密锁
*-93 代表操作加密锁时错误
*-94 代表操作加密锁时错误
*-83 表示从加密锁读取数据时错误,可能是读密码错误
*-46 使用控件时,输入的字符不能是空字符串
*/
function codeConvertMsg(code) {
var msg = "";
switch(code) {
case "-82":
msg = "写数据到加密锁储存器时错误,可能是写密码错误";
break;
case "-81":
msg = "输入的地址空间越界";
break;
case "-47":
msg = "进行读写字符串时,地址空间越界";
break;
case "-88":
msg = "输入的地址空间越界";
break;
case "-92":
msg = "不存在指定的加密锁";
break;
case "-93":
msg = "操作加密锁时错误";
break;
case "-94":
msg = "操作加密锁时错误";
break;
case "-83":
msg = "从加密锁读取数据时错误,可能是读密码错误";
break;
case "-46":
msg = "使用控件时,输入的字符不能是空字符串";
break;
}
return msg;
}
var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
function toHex(n) {
var result = ''
var start = true;
for ( var i=32; i>0; ) {
i -= 4;
var digit = ( n >> i ) & 0xf;
if (!start || digit != 0) {
start = false;
result += digitArray[digit];
}
}
return ( result == '' ? '0' : result );
}
/**
* 写入用户名操作
*/
function writeUserName(userName) {
var ret, mylen;
try {
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
mylen = aObject.YWriteString(userName, 1, "ffffffff","ffffffff",devicePath);
aObject.setBuf(mylen, 0);
ret = aObject.YWriteEx(0,1,"ffffffff","ffffffff",devicePath);
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert(e.name + ": " + e.message);
}
return ;
}
/**
* 写入密码操作
*/
function writePassword(password) {
var ret, mylen;
try {
if (devicePath == null || devicePath == "" || devicePath == undefined) {
return ;
}
mylen = aObject.YWriteString(password, 21, "ffffffff","ffffffff",devicePath);
aObject.setBuf(mylen, 0);
ret = aObject.YWriteEx(20,1,"ffffffff","ffffffff",devicePath);
if( aObject.LastError!= 0 ) {
window.alert(codeConvertMsg(aObject.LastError.toString()));
return ;
}
} catch (e) {
window.alert("write Password" + e.name + ": " + e.message);
}
return ;
}