1、Web服务器:MS IIS应用服务器:tomcat、COM+等企业级应用服务器数据库:SQL Server 20003.系统设计 Flex相比传统的OA是显示界面的全新体验。 3.1从分层角度来看,企业应用分为三个层次。如表1所示 展现层主要负责信息展示以及用户与软件之间的交互逻辑“,展现层”接受用户输入并将用户的意图转换为对“领域层”或“数据源层”逻辑的调用。领域层也被称为“业务逻辑层”,主要解决应用针对业务领域的问题,该层负责校验来自“展现层”的输入数据,根据“展现层”用户指令进行业务逻辑处理,调用“数据源层”的逻辑实现数据的访问和持久化。数据源层主要负责数据访问和持久化,数据可能来自于数
2、据库或者其他文件。 Flex+JAVA开发的应用中“,展现层”逻辑完全运行在客户端的FLASH虚拟机中,而“领域层”和“数据源层”逻辑则运行在服务器端的java虚拟机中,如图2所示3.2确定通信框架 开发异构系统的时候,如何进行通信和传递数据,使用FLEX+JAVA开发基于C/S结构企业应用,客户端和服务器端的通信协议是HTTP协议。在FLEX中,基于HTTP协议访问服务器的通信组件有三个:HttpServiceWebServiceRemoteObject在企业应用开发中大部分都使用RemoteObject完成的,RemoteObject组件在BlazeDS的配合下能够调用后台服务器对象上的方
3、法,从而实现客户端与服务器端的通信。下面给出一段代码展示RemoteObject对象的使用:Public funcion userRemoteObject(intArg:int,strArg:String):void employeeRO=new RemoteObject(); employeeRO.destionation=“SalaryManager”;employee.getList.addEventListener(“result”,getListResultHandler);employeeRO.addEventListener(“fault”,faultHandler);emplo
4、yeeRO.getList(deptComboBox,selectedItem,data);上面代码中,首先使用语句:employeeRO=new RemoteObject(); 创建了一个RemoteObject对象employeeRO。然后通过语句:employeeRO.destionation=“SalaryManager”将RemoteObject对象的destionation属性赋值为“SalaryManager”,destionation属性表示远程对象调用的“目的地”,请求发送到服务器端后,服务器端的“第三方软件”接收到请求后会检查配置文件,找到destionation值所映射的
5、“服务器端组件”,从而可以调用该组件上的方法。接下来使用语句: employee.getList.addEventListener(“result”,getListResultHandler);设置远程服务调用成功时的处理方法,使用语句: employeeRO.addEventListener(“fault”,faultHandler);设置远程服务调用失败时的处理方法。最后使用语句: employeeRO.getList(deptComboBox,selectedItem,data);以deptComboBox,selectedItem,data为参数,调用destionation属性所映射
6、的“服务器端组件”的getList方法。这里“服务器组件”必须有一个名为getList的公开方法,调用“服务器端组件”的getList方法是异步调用的,因此它不会阻塞线程来等待调用结果的返回。二C#+java技术1.c#的介绍C#语言自C/C+演变而来。它现代、简单、完全面向对象和类型安全。关于C#最重要的一点:它是现代的编程语言。它简化和现代化了C+在类、名字空间、方法重载和异常处理等领域。屏弃了C+的复杂性,使它更易用、更少出错。2.运行环境3.相关实现C#客户端与JAVA服务器端的TCP文件传输 使用两种计算机语言的结合。可以用WebService做,也可用socket。因为不管什么类型
7、的计算机语言,都是用机器语言封装的,越是底层的技术,就越容易结合。socket技术很底层,但效率确实最高,对于JAVA以及C#的初学者来说,又简单易懂。首先是JAVA的服务器端,这个只要学习过J2SE网络编程的人,应该都能做得出来。代码如下:package com.ly.image;import java.io.BufferedInputStream;import java.io.BufferedWriter;import java.io.File;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.
8、ObjectInputStream;import java.io.PrintWriter;import .ServerSocket;import .Socket;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;import java.util.ResourceBundle;import org.apache.log4j.Logger;/* * TCP服务器端 */public class TCPServer private static Logger logger = Logger.
9、getLogger(TCPServer.class); /* * 接收文件存放路径 private static String path; * 接收端口 private static int port; * 读取资源文件 * 通过资源文件读取所需资源,方便更改,资源文件里有文件存放路径及接收端口 static System.out.print(读取配置文件.); /资源绑定 ResourceBundle rb = ResourceBundle.getBundle(config, Locale.getDefault(); path = rb.getString(path String portS
10、tr = rb.getString(port if(path = null | path.trim().equals() path = E:/; else if(!path.endsWith( path = path + if(portStr != null | !portStr.trim().equals( try port = Integer.parseInt(portStr); catch(Exception ex) System.out.println(端口获取失败,已变更为默认端口8888 port = 8888; else未配置端口,已变更为默认端口8888读取完成: + 接收端口
11、 + port + ,接收路径 + path); * 启动服务 public static void main(String args) new TCPServer().receiveFile(); * 接收文件 public void receiveFile() ServerSocket ss = null; Socket s = null; BufferedInputStream in = null; FileOutputStream out = null; ss = new ServerSocket(port);服务已正常启动! ex.printStackTrace();服务启动失败!
12、logger.error(启动服务失败! + ex); /永不停歇地运行 while(true) byte buffer = new byte1024; String fileName = null; s = ss.accept(); in = new BufferedInputStream(s.getInputStream(); /取得文件名 in.read(buffer, 0, buffer.length); fileName = new String(buffer).trim(); /若为测试信息 if(fileName.equals(test message接收到测试消息! logge
13、r.info( continue; /定义文件流 out = new FileOutputStream(new File(path + fileName); out.flush(); buffer = new byte1024; /写文件内容 int count = 0; while(count = in.read(buffer, 0, buffer.length) 0) out.write(buffer, 0, count);接收到文件 + fileName);传输异常, ex); finally if(out != null) out.close(); if(in ! in.close()
14、; if(s ! s.close();接收文件 + fileName + 失败使用此服务器接收时,过程如下:1.从流中读取第一拨数据,作为接收到文件的文件名(若接收到的为定义好的测试信息,则跳过本次循环)2.用上一步得到的文件名定义文件流3.从流中以1K为单位,读取字节内容,并写入文件流然后是C#的客户端代码:using System;using System.Collections.Generic;using System.Configuration;using System.IO;using System.Net;using System.Net.Sockets;using System.
15、Text;namespace Client class Program / / 发送文件/summaryparam name=文件全路径fileName文件名返回执行结果0成功,-1文件不存在,-2连接失败,-3IO异常,-4未知异常 public int StartSend(String path, String fileName) if (!File.Exists(path) return -1; NetworkStream stream = null; BinaryWriter sw = null; FileStream fsMyfile = null; BinaryReader brM
16、yfile = null; try TcpClient client = new TcpClient(172.16.60.30, 8888); stream = client.GetStream(); sw = new BinaryWriter(stream); /取得文件名字节数组 byte fileNameBytes = Encoding.Default.GetBytes(fileName); byte fileNameBytesArray = new byte1024; Array.Copy(fileNameBytes, fileNameBytesArray, fileNameBytes
17、.Length); /写入流 sw.Write(fileNameBytesArray, 0, fileNameBytesArray.Length); sw.Flush(); /获取文件内容字节数组 /byte fileBytes = returnbyte(filePath); fsMyfile = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); brMyfile = new BinaryReader(fsMyfile); while (count = brMyfile.Read(buffer, 0, 1024
18、) 0) sw.Write(buffer, 0, count); catch(SocketException se) Console.WriteLine(se.StackTrace); return -2; catch(IOException ioe) Console.WriteLine(ioe.StackTrace); return -3; catch(Exception ex) Console.WriteLine(ex.StackTrace); return -4; finally if (sw != null) sw.Close(); if (brMyfile ! brMyfile.Cl
19、ose(); if (fsMyfile ! fsMyfile.Close(); if (stream ! stream.Close(); return 0; / 测试通讯成功失败 public bool TestConnection() byte fileNameBytes = Encoding.Default.GetBytes( sw.Write(fileNameBytes, 0, fileNameBytes.Length); return true; return false;这个发送端有两个方法,其中第二个方法是测试连接用的,返回true即为测试通过,返回false连接异常。发送过程如下
20、:1.先把文件名写入流,供服务器端读取2.将文件内容写入流3.若发送完毕,返回0;给定文件不存在,返回-1;连接异常,返回-2;IO异常返回-3;其他异常返回-4。C#和JAVA虽然很相似,但是毕竟方向不同,各有各的长处,各有各的规范。使用socket时,也遇到了不太匹配的地方。比如开始用C#发送文件名的时候,我只把文件名转变为字节流,没有指定固定长度。这样使用JAVA接收时,导致文件最后一部分字节残留,使得第二次接收文件时,文件名不能正确显示。于是才在C#的发送端用Array.Copy方法,将文件名字节流补足了1K,才正常传输。3不同实现之间的对比在某大型项目中,客户要求不能用浏览器作为客户
21、端(即不能用B/S模式),而要采用桌面客户端的方式(服务端用SSH,客户端通过Web Service访问服务端应用,并且还要求能在客户端与服务端网络中断的情况下离线进行部分业务操作,例如查询)。这可给我们项目组提出了一个大问题:客户端应用开发的技术选型。1.flex做客户端Flex是基于MXML与Action script 3,在Flex Builder 3下开发,借助编译器可以在开发时发现编译异常,在运行时可以通过设置断点来分步调试,而MXML的底层实际上也是Action script 3,这无论从开发、设计还是调试方面都比传统的HTML+Java script 要强大的多。当客户端变得很慢
22、、内存泄露、甚至溢出时,我们往往只是对客户一笑,告诉他重启浏览器。由于不好的开发习惯,很多项目代码中充斥着垃圾回收机制无法回收的内存占用,这些内存浪费就是所谓的内存泄露,更可怕的是,当你的程序运行时间越长,会累积越来越多的内存泄露,最终导致内存溢出,系统崩溃。Flex的profile可以轻松帮助我们发现内存溢出的根源,帮助我们写出功能性能俱佳的代码。另外,利用Flex还有客户和服务器端部署方便,客户端与服务器完全独立,丰富的框架等优点2.c#做客户端在用C#做客户端得问题上,公司有些员工强烈建议用Java Swing,认为有一些框架可以利用,例如Spring RichClient(Swing)
23、,大家都对Spring比较熟悉,有亲近感;甚至可以考虑使用 Eclipse RCP富客户端平台(SWT),因为有Eclipse在前面作为成功标杆。并且公司开发人员绝大多是Java程序员,可以随时抽调精兵强将加入任务繁重的客户端开发中,解决技术难题,甚至突击编写普通业务功能。而C#人员要重新招聘,增加了很多不确定因素。但是采用Swing,缺点是界面比较难看,控件少得可怜,对客户端资源的控制能力差,开发难度肯定高,并且公司内部也没有积累(Java程序员都是做B/S应用的),并且在人力资源市场上,Swing方面但凡有点水平的开发人员工资都高得吓人(在51Job上查了一下);但好处就是应用服务端与客户端都是用的Java,两边的人手可以灵活配置(当然前题是开发人员对于SSH和Swing都要能上手,一是需要一段时间学习,二是人家技能多了,肯定会要