本周在单位实习就做了两件事情:其一是用Java Swing开发了一个简单FTP的小软件,支持客户端上传文件至服务器以及由服务器下载文件至客服机;其二是用Ext开发了一个可以维护数据库中某一张表并且校验SQL能否正确执行的小工具。下面就开发过程中遇到过的问题作一个简单的总结。
一、简单版本FTP
基础知识:
1、对JavaSwing中常用的一些组件要很熟悉(JTree、JFrame、JMenuBar、JLabel);
2、可以用java.io.*包中的File抽象出客户端的文件目录结构;
3、必须了解java.net.*网络编程;
4、使用JSON格式数据抽象服务端的文件目录;
5、使用java.io.*二进制流进行文件的上传和下载;
6、对JTree之间的拖放事件了解,在节点拖动结束后启动线程进行上传和下载。
认识总结:
1、对于任何Swing的应用都要遵循M-VC的原则,Swing中只显示的定义了Model接口,而在一个UI对象中集成了视图和控制器的部分机制。VC比较松散的交叉组合在一起,而更多的控制逻辑是在事件监听者部分引入的。
2、客户端直接定义一个FileTreeModel类实现TreeModel接口即可;
3、服务端根据客户机传来的文件目录构造JSON格式的数据返回客户端,可能下面提供的递归方法并非最优写法但是已经能实现功能:
public static void recursDir(File f,JSONObject fo)
throws JSONException{
if(f.isDirectory()){
JSONArray fa = new JSONArray();
fo.put("children", fa);
fo.put("isDirectory",true);
File[] fs = f.listFiles();
for(int i = 0;i < fs.length;i++){
JSONObject o = new JSONObject();
o.put("path", fs[i].getAbsolutePath());
o.put("isDirectory", true);
fa.put(o);
recursDir(fs[i],o);
}
}else{
fo.put("path", f.getAbsolutePath());
fo.put("isDirectory", false);
}
}
这样服务端已经可以根据请求抽象出文件的目录结构了,将服务端的文件目录模型定义为JSONObject即可按照请求的目录显示出服务器上面的目录文件。
4、实现上传和下载功能
- 下载实现思路:
创建HttpURLConnection请求服务端返回需要下载文件的二进制流数据,创建本地文件,将服务端返回的流数据写入到空文件中。下面是部分代码:
File f = new File(filepath);
if(!f.exists()){
file.createNewFile();
}
//创建输出流
FileOutputStream fos = new FileOutputStream(file);
int len = -1;
byte[] buf = new byte[MAX_BUFFER_SIZE];
while((len = inStream.read(buf)) > 0){
fos.write(buf, 0, len);
}
inStream.close();
fos.close();
//inStream是从服务端传来的二进制流文件
- 上传实现思路
将本地文件写入到二进制流中,HttpURLConnection交互服务器,服务端创建文件并写入流数据,下面看部分代码:
//将本地文件转换
FileInputStream fis = new FileInputStream(new File(uploadPath));
int len = 0;
byte[] b = new byte[MAX_BUFFER_SIZE];
while(len != -1){
len = fis.read(b);
if(len > 0){
out.write(b, 0, len);
out.flush();
}
}
fis.close();
out.close();
//out输出流,将客服端的文件名和转换为二进制流的文件输出到服务端。
此时服务端要实现的代码就很简单了,只需要按照客户端的文件名,在指定的文件目录中创建一个空文件并将接受的二进制数据写入到文件中。继续代码:
File f = new File(fileProperty[0] + File.separatorChar + fileProperty[1]);
if(!f.exists()){
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream(f);
int len = -1;
byte[] buf = new byte[2048];
while((len = objInStream.read(buf)) > 0){
fos.write(buf, 0, len);
}
inStream.close();
fos.close();
//ObjectInputStream objInStream = new ObjectInputStream(inStream);
//Object obj = objInStream.readObject();
//obj对象中封装了上传来文件名和上传的位置
二、SQL维护小软件
这个小玩意其实也没什么好总结的,主要是写一下自己对布局管理器和Ext事件处理的心得。以及调用存储过程将数据库出错信息显示到前台的想法,呵呵这个需求有点变态。
- Ext中的布局管理器
布局是在容器中内置创建的,开发过程中在使用布局时,只要在容器类的配置项中指定layout和layoutConfig即可。它们分别用来指定布局方式和布局的配置项。
Ext中的布局方式可以分为5类:
1、Border布局(BorderLayout)
BorderLayout布局比较常用,它把平面分成north、south、west、east、center5个部分。除了center区域是必需的之外,其他区域都是可选的。
2、锚定位布局(AnchorLayout、AbsoluteLayout、FormLayout)
3、自适应位置布局(FitLayout、AccordionLayout、CardLayout)
FitLayout布局是最简单的布局方式,它让容器中的子组件能自动扩展适应容器的大小,并填充到容器中去。一般来讲,使用FitLayout布局时都只有一个子组件,对于多个子组件一般采用其子布局AccordionLayout或是CardLayout。
4、表列布局(ColumnLayout、TableLayout)
SQL维护小软件就是采用ColumnLayout布局的,说白了就是分列排布容器中的每个子组件。
5、箱子布局(VBoxLayout、HBoxLayout)
- Ext同步请求
有些时候如果我们不希望我们的调用时异步的怎么办?如果再引入Jquery或者使用Ext官网提供的补丁包那不免有点麻烦,其实一种简单的方式Ext自身也可以实现同步调用:
var conn = Ext.lib.Ajax.getConnectionObject().conn; url = "biz_logic.jsp?_ajaxP="+ Ext.util.JSON.encode(obj)+"&operator=checkSqlExec"; conn.open("GET",url,false); conn.send(null); var rs = conn.responseText; if(rs != 1){ alert("校验出错: "+ rs); rev = false; }
- 使用HtmlEditor编辑器取值的时候出现html标签怎么办?
在取出HtmlEditor组件中的值的时候,发现通过Ext.getCmp(el).getValue()取出的值是如下格式的:<p>where xh='310830'</p>,怎么办?可以试试下面的方法:
var tmp = Ext.getCmp('edit_xq').getValue(); var xq = Ext.util.Format.stripTags(tmp);这里,我一直没有认真看过关于Ext.util包里面的功能列表,现在想想确实还是需要了解一下的,其实Ext的开发团队已经为我们解决了80%开发中可能遇到的问题,没必要所有的问题都要我们开发人员去解决。