1. Applet基础
在网页中嵌入Applet程序:
<applet codebase= "."
code= "com.webtec.graph.TopGraphApplet.class"
archive="topview20111202.jar"
width=800 height=600>
<param name=width value="800">
<param name=height value="600">
</applet>
Codebase: applet程序位置(.表示页面和applet在同一位置)
Code: applet类的全名
Archive:引入的jar包,多个用","隔开
<param name=width value="800">指定向applet传入的参数
Applet程序:
getParameter("width"), 从Apple获取参数对应值,未设置返回null
getCodeBase (),返回当前applet的路径,即applet的目录的URL。
这里犯了个错误,想要从properties文件中读取服务器配置,在applet中配置连接服务器的路径,但是applet是服务器端下载的,不能访问客户端的文件系统,不可能读到properties文件,最后用getCodeBase()方法替代了。要配置用户属性,可以在param标签配置。
Validate(),在applet中动态添加组件,不显示,调用了一下Validate()方法,然后图形出来了,repaint()、doLayout()都不得行,也不是很明白,时间紧急没有细究。
2. Applet与服务器交互
准备在applet程序中绘制图形,图形数据从数据库中获取出来的,开发的时候直接访问了数据库,还用了JPA,在Eclipse里面发现运行起来很正常,很强大,发布的时候发现又做错了。
Applet是运行在客户端的,需要客户端的java类库支持,开发的时候直接把很多包放到了类路径下,发现用户要从网页运行不可能下载所有的jar包支持运行,所以不要把applet功能做得太过强大,主要是用来展示的。
Applet可以直接访问数据库,但是需要JDBC的支持,但是最好不要这样做。一方面客户端是没有jdbc包的,直接放到applet一起会增加用户访问时的网络负担;另一方面,数据库服务器不一定能够从客户端直接连通,主要是网络问题,可能数据库位于内外或者其他安全考虑。
最终不得不考虑从远程Http服务器获取图形数据,代码如下:
/**
* 从服务器读取数据绘制TOP图的数据
* */
public static String getGraphicData() {
String graphicData = "";
//服务器servlet或Action请求路径(绝对路径)
String urlString = Common.ActionAddress.getGraphDataUrl();
byte buffer[] = new byte[4096];
StringBuffer data = new StringBuffer();
HttpURLConnection conn = null;
try {
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int len = 0;
while((len = is.read(buffer))>0){
data.append(new String(buffer, 0, len));
}
is.close();
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null,
"Error: " + "Error occurs when request to : \n" +
urlString + "\nReason: " + e.getLocalizedMessage(),
"Applet Message", JOptionPane.ERROR_MESSAGE);
}
return graphicData;
}
在开发环境中测试一切正常,但是发布到网页中无法执行。上面的代码表面上看只有IOException,所以一开始只捕获了IO异常,开发环境中运行正常,但是网页加载后执行正常,Java控制台无任何异常信息,调了很久不知道为什么。后来只好将IOException改成Exception,捕获到了java.net.SocketPermission,提示Access Denied,发现是applet无法使用网络资源,是java security机制的原因,applet无法访问客户端的网络、文件等资源,所以只好在客户端修改配置了,配置方法在下一节。
网络异常解决了,程序还是无法执行,检查到java.lang.reflect.ReflectPermission异常,可能是在给Filed设置值是设置了私有成员,最终没有解决,网上查不到资料,自己改不来,只好吧那部分代码换了,用了点低级的代码先把功能实现了再说。
还有一个问题不能解决的是Applet的字符编码问题,服务器端用的是UTF-8的编码格式,在页面测试正常,开发环境中的Applet测试正常,但是发布到网页测试不正常,说是Applet运行的时候用的是操作系统的默认字符集,最后只好把它从GBK转了一遍,勉强凑合,但是没有完全去除乱码,GBK2312和GBK18030直接抛异常,没搞懂为什么,期待高手指点。
3. Applet安全设置
Applet访问网络,抛出异常:
java.security.AccessControlException: access denied (java.net.SocketPermission server1 resolve)
这个错误的通知你访问被拒绝。这就是说,由于 applet 程序试图在没有获得正确的权限的情况下访问系统资源,括号中代码表示,若要纠正这种情况,您需要一个向数据库所在计算机(主机名为server1) 授予 applet 访问权限的 SocketPermission。
解决办法:
创建policy策略文件,内容如下:
grant {
permission java.net.SocketPermission "server1", "resolve";
permission java.net.SocketPermission "127.0.0.1:8080", "connect, resolve";
};
将该文件保存成ASCII文件,命名为netconnect.policy,存于${JRE_HOME}/lib/security/目录下(主要是为方便后面路径填写)。
修改Java安全配置:
创建了策略文件后,修改${JRE_HOME}/lib/security/java.security文件,在
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
下添加一行
policy.url.3= file: ${java.home}/lib/security/netconnect.policy
再次访问页面的applet,又捕获到如下异常:
java.security.AccessControlException: access denied(java.net.SocketPermission 127.0.0.1:8080 connect,resolve)
网络访问仍受限,不能访问服务器127.0.0.1:8080,在前面生成的策略文件中加入
permission java.net.SocketPermission "10.6.1.16:1521", "connect, resolve";
再次访问,运行成功。
还有种说法是为applet添加安全证书,用keytool工具,暂时没有时间去研究没搞懂,过段时间可以去研究一下。