联系方式: 微信:biyebang QQ: 629001810
摘 要
极光办公自动化系统是针对南开创元信息技术有限公司开发的,专门用于企业内部员工信息交流的软件,其开发过程主要包括前端应用程序的开发和后端数据库的建立两个方面。对于前者要求应用程序功能完备操作简单,对于后者要求建立起数据一致性、完整性和安全性好的数据库。
本论文在对南开创元信息技术有限公司充分调研的基础上,针对该公司实际情况,采用Client/Server模式、利用JAVA语言进行系统的开发,以SQL Server 2000作为网络数据库,实现极光办公自动化系统。
系统用网络数据库将企业内员工的基本信息统一管理起来,形成集成的信息源,系统会根据员工所属部门对员工进行分类,这样有利于发送者快速找到发送目标,也能方便的进行信息的群发,在该系统中总经理具有最高的权限,负责对系统的管理。
该系统可使企业内员工之间信息的交流更高效,更便捷,也使企业内各部门之间员工的频繁往来减到最少,从而提高企业整体的办公效率,为企业节约成本,使企业在激烈的市场竞争中赢得优势,实现企业整体战略目标。
系统设计
作为一套应用系统,除了要能够完成预定的各种功能外,在设计时还必须遵循实用性、完备性、可靠性、安全性、兼容性、可扩充性等原则。具体要求原则如下:
(1)安全性 主要是指系统运行的安全性、数据的安全性和保密性等。同时,应根据用户的工作和业务流程为用户提供合理可靠的安全策略。
(2)实用性 是系统建设的主要目标。主要是指系统功能应能够满足当前和今后一段时间内企业办公的实际需要。
(3)可靠性 是指系统的数据结构合理、模块功能正确等,以保证数据处理和信息传输的正确可靠。
(4)友好性 是指界面的美观和使用的方便程度,即界面友好,有良好的引导功能、容错和查错功能。
(5)可维护性 是指系统应具有较好的可维护性,以方便系统管理员对系统进行维护。
(6)可扩充性 本系统目前还不是很完善以后需要改进的地方还很多。随着计算机在企业各部门应用的进一步深入,也后需要增加的功能还很多。另外,系统还应该留有一定的接口,以便将来扩充的方便等;
(7)可移植性和适应性 针对目前我国企业的实际情况,系统应具有较强的适应性和较好的可移植性,同时尽量避免对硬件的依赖。
极光办公自动化系统有五个子系统
(1)个人工作子系统
(2)信息中心子系统
(3)日常工作子系统
(4)流转中心子系统
(5)维护中心子系统
各子系统包含的功能模块如下:
个人工作子系统:电话簿、总经理工作计划信息中心子系统:信息交流、电子公告、规章制度、新闻信息日常工作子系统:资料管理、办公用品申领流转中心子系统:公文管理维护中心子系统:权限管理、注册管理
如图3.1为本系统的功能模块图
个人工作
提供员工个人工作中的基本功能,电话簿(允许当前用户创建属于自己的名片信息,分类、管理个人名片,查阅组织内用户的名片)、总经理工作计划(主要是记录了总经理近期的工作计划)等。
信息中心
是本单位发布信息与交流的平台,包括电子公告(用来向公告板上发布通知、制度、活动和会议等消息)、规章制度(数据库可以管理规章制度,用户可以看到已发布的规章制度)、新闻信息(企事业单位为让员工了解一些信息,而发布本单位的新闻信息,和录入一些国际国内新闻)等。
日常工作
根据各部门及其工作流程定制相关内容,资料管理(辅助管理公司内部的各种资料)、办公用品申领(主要用来对企业中办公用品的使用情况进行统计,办公用品领用申请,办公用品领用申请进行批阅,以及办公用品的领用办理)等。
流转中心
根据系统管理中设置的相应流程进行公文流转,最终实现无纸化办公,提供公文流转(实现了收、发文的管理、流转、批约、转出和归档)等功能。
系统管理
包括组织机构的设置、用户权限角色的定义等功能。把系统管理员从烦琐的管理工作中解脱出来。
一、硬件环境:服务器端:主频2G以上CPU,512MB内存,通过局域网接入Internet。客户端:主频1GHZ以上CPU,128MB以上内存,20G以上硬盘,内部人员通过Intranet访问系统。
二、软件环境:服务器端:windows2000 Server操作系统,SQLServer2000数据库客户端:windows 2000
数据库的设计分为逻辑设计和物理设计两部分。在数据库逻辑设计方面,可以遵循自顶向下的结构化设计方法,确定系统目标后,采用E—R图设计数据库的概念模型,然后根据此模型导出数据库的关系模型。
用户的需求集中体现在各种信息的提供、保存、更新和查询等方面,这要求数据库结构要充分满足各种信息的输出和输入。收集基本数据、数据结构以及数据处理的流程,组成一份详尽的数据字典,为后面的具体设计打下基础。
以下为本系统所用到的数据表:
1)ServerIP表位于本地数据库中用来存放数据库服务器的服务器名或服务器IP地址,它由系统自动生成,图3-2为该表的具体构成:
2)BuMen表位于数据库服务器中用来存放公司的所有部门情况,包括部门名称、部门简介。
图3-3为该表的具体构成:
3)XinXi表位于数据库服务器中用来存放用户不在线时,其他用户给其发送的信息。如图3-4为该表的具体构成。其中userName为发送者用户名,XinXiDuiXing为发送的目的地。
4)YongHu表位于数据库服务器中用来存放企业内部员工的信息,以及用户的状态等。如图3-4为该表的具体构成。其中UserName为用户名,Name为用户真实姓名,IPAddress为用户的IP地址,State为用户的状态(是否在线),BuMen
为用户所在部门,Zu为用户所在组,Port为用户使用的端口号。
5)信息记录表位于本地数据库中,用来存放用户的信息记录如图3-5为该表的具体构成。其中XinXiDuiXiang为用户交流的对象,XinXiJiaoHu为用户是发送数据还是接收数据。
系统实现
SUN公司的Java是一个广泛使用的网络编程语言,它是一种新的计算概念。首先,作为一种程序设计语言,它简单、面向对象、不依赖于机器的结构、具有可移植性、鲁棒性、安全性、并且提供了并发的机制、具有很高的性能。其次它最大限度地利用了网络,Java的小应用程序 (applet)可在网络上传输而不受 CPU和环境的限制。另外,Java还提供了丰富的类库,使程序设计者可以很方便地建立自己的系统。
由于Java语言在网络方面的优异表现,故本系统的实现Java是一个最好的选择,然而Jbuilder是业内开发java程序的最好的工具之一,所以我选择了Jbuilder作为java的开发工具。
作为标准的关系数据库,至少应具备以下特征:
(1)海量数据存储能力;
(2)快速有效的数据处理能力;
(3)优秀的多用户机制;
(4)完善的数据安全控制机制;
(5)具有开放性,并应与国际标准完全吻合;
(6)可靠性、容错性;
基于以上特征,我选择SQL Server2000作为我的数据库系统平台,这主要是因为SQLServer2000是Windows NT平台上性能较好的关系数据库,与NT平台在权限管理、目录服务、系统级配合等方面都可以很好地结合。
在数据库应用中,Java的解决方案是JDBC(JavaDatabase Connectivity)。JDBC建立在X/OpenSQL CLI(调用层接口)基础上,可以编写访问任何关系数据库的统一的纯Java应用程序,实现对Internet环境下各种异构关系数据库的访问。同时,因为Java的平台无关性,采用JDBC编写数据库应用程序的开发者可以真正做到“编写1次,随处运行”。
4.3.1 JDBC工作原理
JDBC主要包含2种接口,分别是面向驱动程序低层的JDBC Driver API和面向应用程序开发人员的JDBCAPI。
一 JDBCDriver API
JDBC Driver API是为数据库厂商提供的驱动程序的编程接口。JDBC驱动程序是JDBC结构的支柱,用于提供与数据源的接口,解释和执行来自应用程序中的SQL语句,并返回结果。JDBC驱动程序包括4类:第l类是JDBC-ODBCBridge Driver即JDBC桥加上ODBC驱动程序,在每个客户机上装入ODBC驱动程序,JDBC通过ODBC访问数据库。第2类是Native API(PartlyJava Driver),即本机API加上部分Java驱动程序,将JDBC调用转换为各种数据库系统的客户API调用。第3类是JDBC/Net(Pure JavaDriver),即JDBC Net加上Java驱动程序将JDBC调用翻译成独立于数据库网络协议,然后再由服务器翻译成数据库协议,可与各种不同的数据库相连。第4类是地native(PureJava Driver),即本机协议加上Java驱动程序,将JDBC调用转换为数据库使用的网络协议,由客户直接调用数据库服务器。
二 JDBC API
JDBC应用程序实现对数据库的访问需要建立与数据库的连接,发送SQL语句,返回数据结果给客户。应用程序开发人员利用JDBCAPI来完成这些工作。JDBC API在java.sql包中定义,包含JDBC访问数据库用到的所有类和接口,主要有:
(1)DriverManager类:用于装入驱动程序,定义在网络上需要访问的数据源的JDBCURL,根据定义的URL选择匹配的驱动程序、为建立数据库连接提供支持。
(2)java.sql.Connection接口:用于特定数据库的连接。
(3)java.Statement接口:为SQL语句提供一个容器,包括执行SQL语句、取得查询结果等方法。它包含2个重要的子类。一个是java.sql.PrepareStatement允许在SQL类中输入参数;另一个是java.sql.CallableStatement,用于执行SQL存储过程。
(4)java.sql.ResultSet接口:提供对结果集进行处理的手段。
JDBC应用程序结构
利用JDBC API进行数据库访问的应用程序基本结构如图3-1所示,主要包括下列部分:
(1)装载驱动程序:用DriverManager类提供的Class.forName()方法来加载驱动程序,例如用C1ass.forName(“sun.jdbc.odbc.JdbcOdbcDriver”)语句直接加载SUN公司的JDBC-ODBC桥接驱动程序。
用C1ass.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver")可以连接SQLServer2000数据库,由驱动程序负责向DriverManager注册,在与数据库相连时使用该驱动程序。
(2)建立与数据库的连接。用DriverManager类提供的getConnection
(URL、userName,PassWord)方法来建立与数据源的连接,返回一个Connection对象。其中URL参数格式为:jdbc:<subprotocol>:<subName>。<subprotocol>指支持数据库连接的驱动程序使用的子协议,例如ODBC引擎。<subName>指数据源的信息、例如数据源的IP地址、端口号、数据源名。
(3)创建语句对象。一旦建立了与数据库的连接,就可以利用Statement接口创建SQL语句对象,例如:Statementstmt=connect.createStatement()。根据需要还可以创建PrepareStatement对象来处理带参的SQL语句,或创建CallableStatement对象来处理SQL存储过程。
(4)执行SQL语句。利用创建的语句对象,用Statement.executedXXX方法来执行SQL语句,并返回一个ResultSet对象。例如:
ResultSetrs=stmt.executeQuery(“select * from YongHu”)执行对YongHu表的查询操作,并返回rs结果集。以下代码是结合本系统数据库访问的具体实现:
String SQLDriver ="com.microsoft.jdbc.sqlserver.SQLServerDriver";
String cUser = "jdbc:microsoft:sqlserver://" + serverName + ":1433;" +
"DatabaseName=User"; // serverName代表数据库服务器IP地址或服务器名
try {
try {
Class.forName(SQLDriver); //装载驱动
connR =DriverManager.getConnection(cUser, "sa", ""); //创建连接
stmR =connR.createStatement(); //创建SQL语句对象
}
catch (ClassNotFoundExceptiones) //捕获ClassNotFoundException异常
{
es.printStackTrace(); //打印异常抛出地点等信息
}
}
catch (SQLException ex) //捕获SQLException异常
{
ex.printStackTrace();
}
以上代码是实现数据库的连接,可以连接到服务器名为serverName的SQLServer2000网络数据库。
String updateStatePort = "update YongHuset State=1,Port="+port+"where UserName='" + userName +"'";
//设置用户为在线,将本地使用的Port在数据库服务器上更新的SQL语句
String updateIPAddresss = "update YongHu set IPAddress='"+localIP + "' where UserName='" + userName + "'"; //更新数据库服务器上用户的IP地址
int i = stmR.executeUpdate(updateState); //执行SQL语句
int l = stmR.executeUpdate(updateIPAddresss);//执行SQL语句
以上代码可以实现数据库的更新:当用户登录后,在网络数据库服务器上将其状态设为在线,即State为1,并将用户本地的IP地址,与端口号在表内更新。
C/S的概念
客户机/服务器网络中,以计算机主机或服务器为中心,其他计算机、工作站与服务器连接在一起。客户机之间要传递信息均要得到服务器的允许才能进行。在C/S模式中,将请求服务的一方称为客户(C1ient),将提供服务的一方称为服务器(Server)。服务程序一直在一个服务地址(端口)监听对该服务的请求,直到客户对这个服务地址提出请求,服务程序为客户请求作出适当的反应。
用Socket实现C/S编程
套接字(Socket)编程采用客户机/服务器的网络模式。服务器进程一直驻守在服务器上,客户进程向服务器进程发出连接请求,服务器进程响应并建立连接;服务进程与客户进程建立连接后,客户进程发送数据,服务进程处理这些数据并将处理结果返回给客户端进程。
JavaSocket
Java语言为实现其跨平台、制定Internet标准语言、增强与用户的互动等目标,在吸收BSD接口函数优点的基础上,加入Java跨平台、面向对象、支持Internet等特点,推出JavaSocket API软件——Java.net。
Java.net的API分为4类:处理URL的java.net.URL;处理主机名称和IP地址的java.net.InetAddress;处理UDP通信协议的java.net.DatagramPacket、java.net.DatagramSocket、java.net.DatagramSocketlmpl等;处理TCP通信协议的java.net.ServerSocket、java.net.Socket、java.net.Socketlmpl。
而我们的实际应用中很多程序是基于TCP/IP网络编程的,这些应用程序中服务器端和客户端要用到的SocketAPI有:
A)服务器端的API:
(1)java.net.ServerSocket设置通信端口。
(2)accept 侦听及接受客户端的连接请求,并建立与客户端的连接。
(3)read 接受来自客户端发送的数据。
(4)write 发送数据到客户端。
(5)close 关闭Socket及客户端的通信连接。
B)客户端的API:
(1)iava.net.Socket 建立客户端的Socket并尝试与服务器建立连接。
(2)read 接受来自服务器端发送的数据。
(3)write 将数据发送到服务器端。
(4)close 关闭Socket及与服务器端的连接。
Java Socket在C/S中的体系结构
服务器端程序用ServerSocket创建服务器进程,并用accept方法来进行监听并建立与客户端的连接,处理客户端请求,并将处理结果返回给客户端。客户端程序用Socket创建客户端进程并与服务器建立连接,发送数据给服务器端并接受服务器的处理结果。javaSocket在C/S模式中的进程交互过程如图3-3,Socket是网络编程的基础,无论是服务器端还是客户端程序,Socket都是不可缺少的元素。
极光办公自动化系统网络连接
voidjButton7_actionPerformed(ActionEvent e) { //发送按钮按下时触发的事件
String sendLine = jTextField1.getText(); //得到发送内容
for (int i = 0;i < listIP.size();i++) { //与listIP列表里的IP地址建//立连接
try {
Socket socket = newSocket(listIP.get(i).toString(), 8080);
//与对方的8080端口建立连接
out = new PrintWriter(new BufferedWriter(newOutputStreamWriter(
socket.getOutputStream())), true); //建立输出流
out.println(sendLine); //将发送内容输到输出流
socket.close(); //关闭连接
}
catch (Exception ex) {
try {
socket.close(); //如果发生异常也会关闭输出流
}
catch (IOException ec) {
}
ex.printStackTrace();
}
}
}
以上是客户端的代码。它可以实现:在主界面中,用户点击发送按钮,系统就会根据listIP里的IP地址与服务器建立连接,其中listIP中的地址会在用户点击JTree时生成。连接成功后,会与服务器端建立输出流,以便输出信息。
class ServerThread extends Thread { //建立内部类
public void run() { //内部类所执行的动作
try {
server = newServerSocket(ZhuFrame.PORT); //建立ServerSocket
while (true) {
socket = server.accept(); //等待客户端的连接
try {
String userName ="";
String userIP =socket.getInetAddress().toString().replaceAll("/","");
//得到连接成功后的客户端的IP地址
String selectUser="select UserName,State from YongHu where IPAddress='" +userIP +"'"; //根据IP地址查找用户名
ResultSet r5 =stmR.executeQuery(selectUser);
while (r5.next()) {
userName =r5.getString("UserName");
if(r5.getInt("State") == 1) {
in = newBufferedReader(new InputStreamReader
(socket.getInputStream())); //建立输入流
String getStr =in.readLine(); //在输出流中读数据
String str=userName + "对你说:" + getStr;
jdbTextArea1.append(str.replaceAll(" ","")+"\n");
//输出读到的内容
socket.close(); //关闭Socket
if(jTextArea2.getText().equals("请选择成员或部门")) {
jTextArea2.append("发送对象:" + userName);
list.clear(); //清空用户名列表
listIP.clear(); //清空IP地址列表
list.add(userName); //向用户名列表中加入发信息人的用户名
listIP.add(userIP); //向IP地址列表中加入IP地址
}
}
}
r5.close();
}
catch (Exception e) {
e.printStackTrace();
socket.close();
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
以上是服务器端的代码。它是一个线程,当调用accept方法后,进入等待状态,等待客户端程序的连接。当连接建立后会建立与客户机的输入流,以便接收信息。如果接受者处于等待状态那么会把发信息职员的用户名与IP地址分别保存到list与listIP两个表中以便接受者直接回复信息,节省查找用户的时间。
Java Swing的原理和特点
Java开发工具包(JDK)包含了一个复杂的图形API和用户接口API的集合,该集合的核心软件被称为Java的基础类(JFC)。JavaSwing是JFC中的一个重要的技术,其组合了大量的可用于构建复杂用户界面的轻量级组件。Swing组件是现有的抽象窗口工具包AWT组件的增强,但它又不完全取代AWT组件,这两种组件可以用在同一个界面上。本系统选择JavaSwing组件进行开发,是由于Swing组件具有两个很显著的特点:轻量级和可插入外观。
·轻量级组件并不是指其体积小,而是组件不依赖于“对等类”(“Peer”classes)而由Java的其他类所支持。所谓“对等类”是指本机系统类。因为JavaSwing中的大多数组件都有其自己的由Java外观类所支持的视图,而并不依赖于本机系统类。所以,Swing组件集都为轻量级组件。
·可插入外观组件(PluggableLook—and—feel)允许应用程序能够在不重新启动的情况下看到Swing组件的外观效果。通常,本机外观效果是针对程序所运行的特定系统平台来确定的(如Windows和Motif等)。而由于Swing支持跨平台的外观(也称为Java外观),使得应用程序不论在哪个操作系统平台上运行都具有同样的效果。固本系统所有的界面均选用JavaSwing进行开发。
用JTree实现公司部门人员分类
Jtree使用人们熟悉的文件夹和树叶图来显示分层的数据。应用最广泛的树组件无疑是WindowsExplorer,它包含一个用于导航目录的树组件。
树由许多类和接口组成,这些类和接口在swing.tree包中定义,swing包中的JTree类代表树组件。树由节点组成,节点可以是文件夹,也可以是树叶。文件夹可以是子节点,除根节点之外的所有节点都是只有一个父节点。查询树中的文件夹和树叶都来自数据库,因此树的结构很复杂。本系统树组件位于系统主界面的左侧,用于员工的分类查询,它可以清楚地描述各部门,各员工的层次关系,使企业的组织机构一目了然。本系统树组件实现的代码:
public JTree jbInit() throws Exception { //方法的返回类型为JTree
boolean flag = true;
String buMenName;
DefaultMutableTreeNode top = newDefaultMutableTreeNode("公司各部门成员一览");
//定义树根
String searchBuMenName ="select * from BuMen";
String searchBuMen;
String userName;
ResultSet r1 =stmR.executeQuery(searchBuMenName);
int i = -1; //使list可以取到
while (r1.next()) {
i = i + 1;
buMenName =r1.getString("BuMenName");
searchBuMen = "select *from YongHu where BuMen='" + buMenName + "'";
//从用户表里查找属于该部门的成员
ResultSet r2 =stmR.executeQuery(searchBuMen);
DefaultMutableTreeNode dmtn =new DefaultMutableTreeNode(buMenName);
//定义树枝
list.add(dmtn); //将树枝保存到list表中
while (r2.next()) {
userName =r2.getString("UserName");
DefaultMutableTreeNode dmtn1= new DefaultMutableTreeNode(userName);
//建立树叶
dmtn.add(dmtn1); //将树叶加到树枝上
}
r2.close();
r1 = stmR.executeQuery(searchBuMenName);
for (int j = 0;j <= i;j++) {
r1.next(); //使r1继续执行
}
top.add(dmtn); //把树枝与树叶加到根
}
r1.close();
tree = new JTree(top); //初始化JTree
JScrollPane jsp = newJScrollPane(tree);
//将JTree包含到JScrollPane中使JTree加上滚动条
return tree;
}
以上代码可以根据数据库服务器上的YongHu表动态的生成Jtree,这棵树可以清楚地体现整公司各部门,各员工之间的关系
在查询中,树节点选取是很重要的,当双击某一节点时,要能提取该节点的信息,并同时击活一个事件.下面结出了本系统的addMouseListener()和mousePressed()方法.
void jTree1_mouseClicked(MouseEvent e) { //树click
List getSelect =gouZaoJTree.treeConsult(e); //得到所选择的对象
list = getSelect;
jTextArea2.setText("");
if (list.size() == 1) { //发送对象为1个
jComboBox1.setVisible(false);
String listText =list.get(0).toString();
if (listText.equals("请选择成员或部门")) { //如果什么都没选
jTextArea2.setText("请选择成员或部门");
}
else { //选择一个对象的情况
jTextArea2.setText("发送对象:" +listText);
listIP.clear(); //清空listIP列表
searchIP = "selectIPAddress from YongHu where UserName='" + listText +
"'"; //找到选择用户的IP地址
String ipAddress;
try {
ResultSet r4 =stmR.executeQuery(searchIP);
while (r4.next()) {
ipAddress =r4.getString("IPAddress"); //得到IP地址
listIP.add(ipAddress); //将IP地址保存到列表中
}
r4.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
else if (list.size() ==gouZaoJTree.getChengYuanCount()) {
//发送对象为整个公司
jComboBox1.setVisible(false);
jTextArea2.setText("发送对象:公司所有成员");
listIP.clear();
searchIP = "selectIPAddress from YongHu";
String ipAddress;
try {
ResultSet r4 =stmR.executeQuery(searchIP);
while (r4.next()) {
ipAddress = r4.getString("IPAddress");
listIP.add(ipAddress);
}
r4.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
else { //发送对象为整个部门
jComboBox1.setVisible(true);
jTextArea2.append("发送对象:" +list.get(0).toString().replaceAll(" ",""));
for (int i = 1;i <list.size();i++) { //向用户基本资料里输出
jTextArea2.append("," +list.get(i).toString().replaceAll(" ",""));
}
jComboBox1.removeAllItems(); //选择要发送的组
jComboBox1.addItem("发送至部门内所有人");
listZu.clear();
for (int i = 0;i <list.size();i++) { //向选择组里输出
boolean flag = true;
String selectZu ="select Zu from YongHu where UserName='" +
list.get(i).toString() + "'";
try {
ResultSet r3 =stmR.executeQuery(selectZu);
String str = "";
while (r3.next()) {
str =r3.getString("Zu");
}
for (int j = 0;j <listZu.size();j++) {
if(str.equals(listZu.get(j))) {
flag = false;
break;
}
}
if (flag) {
listZu.add(str);
jComboBox1.addItem(str);
}
r3.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
当用户点击tree,它会根据具体的情况返回你点击的职员的资料,当点击部门时,用户可以选择部门下的某个组进行群发,也可以给整个部门群发,当点击某个用户时可以给该用户发送消息,当点击整个公司时可以给整个公司的成员进行群发。这样会节省发送人的很多时间。
源文件
版权所有© 帮我毕业网 并保留所有权利