资源描述
个人文件标准管理系统的设计与实现
陕西理工大学数学与计算机科学学院实训报告
实训报告
题 目 个人文件管理系统____
项目组成员 韩建、王冬妮、李婧、高育坤、宋航
所在院(系) 数学与计算机科学学院
专业班级 信计1302班
指导教师 赵晖
完成地点 数计学院实训室
个人文件管理系统
摘要:
随着手机、平板等手持终端访问设备的普及,越来越多的用户希望通过网络平台进行管理文件,能更好的保存文件,及时的浏览和查找文件,而通过个人文件管理是一个更具有保密的方式。本课题是建立一个保密及时的管理文件系统,方便更好的保存文件,可以随时随地的访问和查看文件和增加文件,及删除不用的文件。这给我们带来了许多的便利。系统使用Java + JSP + Servlet + MySQL技术实现。本系统主要功能包括用户登录、用户注册、文件上传和文件管理。它具有检索迅速、查找方便、可靠性高、存储量大和成本低等优点。
关键词: 个人文件管理,B/S模式,Web应用,java,servlet
目 录
1系统开发概述 1
1.1系统开发的背景 1
1.2 系统开发目的和意义 1
1.3 系统设计指导思想 1
2 系统需求论述 2
3 系统分析与设计 4
3.1 系统的总体分析 4
3.2 分析类的获取 5
3.3 系统关键抽象概念的获取与分析 6
3.4 分析类交互 6
4 系统设计 6
4.1 系统运行平台的设计选择 7
4.2 系统数据库的结构设计 7
4.3 数据库操作的设计 7
4.4 用户界面设计 8
5 系统实现 11
注册登录的实现 16
上传文件的实现 18
搜索文件的实现 18
分类浏览的实现 20
删除下载的实现 21
6 软件测试与调试 23
6.1 软件测试的必要性 23
6.2 调试 23
结 论 25
参考文献 26
致 谢 27
27
1 绪论
1.1 系统开发的背景
去年某知名生产企业在生产产品时,误用了旧版生产设计稿件,发现后生产成品已经过全国各地的经销商流入市场,之后在产品使用中出现了严重的质量问题,此次赔损的经济补偿与浪费的生产原料金额高达数十亿,不仅如此,公司信誉还蒙受损失,严重影响到了今后的经济效益,其间接损失不可估量。
追根溯源,造成这样严重经济损失的根本原因,是文档管理工作没有做好。文档往往在更新内容后没有及时通知其它使用人员新版本文件的发布,而导致仍有大多数人在使用旧版本。一些重要的企业文档如:合同、报价单、方案等,经常出现版本混乱的情况:合作时签了旧版合同、生产时使用了旧版的设计资料、销售时提供错误的报价单等情况……不仅使企业信誉蒙受损失,还会给企业带来几十万甚至上百亿的巨大经济损失!
而且随着手机、平板等手持终端访问设备的普及,普适计算机越来越渗入人们的生活。跟随发展的就是个性化服务,如网络发布、签名、预约等都被极大地赋予了个人特色,越来越多的用户希望通过网络平台进行管理文件,能更好的保存文件,及时的浏览和查找文件。很多人对发生在自己身边的事以及对生活的一些感悟愿意用文字或图片的方式记录下来发到网络上保存起来,其中通过个人文件管理发布是一个使用频率较高的方式。本课题拟建立一个文件管理的系统,方便广大人民更好的管理好自己的文件,可以将个人生活经验或学习笔记心得等发布到系统中,方便自己随时查看。
1.2 系统开发的目的和意义
文档管理对于每个企业来讲都有着举足轻重的地位,版本控制和文档修订留痕是在文档管理中很重要的组成部分。然而企业该如何优化现有的版本管理手段呢?你可以使用个人文档管理,这些版本问题不再是问题!
1.3 系统设计指导思想
由于系统需要具有普适的特性,因此建立以Web服务为中心的系统是最优的架构。使用传统的B/S架构能接纳多种终端设备的访问,如使用笔记本电脑、台式计算机、手机、平板电脑等设备。其中以学生使用的实际情况看,PC终端和手机终端将是访问的主要设备,因此在系统架构上必须容纳传统的浏览器访问和手机终端访问方式。结合实际的需要,技术实现上将以普通Web的方式实现系统功能的访问,可以统一到Web服务器中一起管理[2,3]。
另外,从用户操作的角度出发,使用系统应该感受到较好的便捷性,即通常所说的系统设计以人为本的思想。综合考虑,对系统设计提出如下几点要求:
1.便捷性:系统以便捷的信息访问为首要目标,以方便用户使用为核心原则,需要充分考虑实际操作的各项细节,支持多种终端接入。这种追求近乎完美的操作体验正是著名的苹果公司创始人乔布斯先生所推崇的,当然本系统以这种指导思想为目标,努力做到尽善尽美,最终通过用户的不断反馈将及时调整,力争做到方便用户操作。在不需要查看操作帮助的情况下也能轻松直观的操作,并对操作流程有清晰的理解。
2.实用性:包括系统功能和系统信息呈现以实用为目标,不添加华而不实的部件与功能,既不丢失必要的信息,又能简单直观,以传达信息为核心,对文字记录和图片发布能提供较好的功能封装。另外通过系统能及时了解多方面多渠道的信息,体现系统的核心价值。
3.可靠性:由于多用户的同时访问,因此系统要具备可靠的性能处理要求,能支持多用户并发访问和并发操作。同时所有的用户数据都存放在服务器上,要求数据存取可靠安全,尽量避免丢失用户创建的资料或数据状态不一致现象。
4.可维护性:针对系统后期的功能调整或增删,应尽量减少维护的工作量。对用户来说,对系统中自己的资料的操作也应该方便查阅和维护。
2 系统需求论述
根据前面的分析与定位,本系统主要用于校内同学的使用,因此需求的重点也反映在同学平时生活中的明显的和一些潜在的期望。就主要功能来说,核心在于创建自己的文件空间,在文件空间中方便的发表文件,同时能方便地查阅自己的文件。同时由于潜在的需求期望增加获取信息的渠道。另外系统提供站内信功能,帮助简化互发消息的管理,这样系统能自主控制所有消息,并能保留消息的历史信息,方便消息维护。
这里为了方便叙述,特预先约定几个使用的名词术语的确切含义:
个人文件空间:指网上由一到多个页面组成的、由用户自己管理上传的。所有者可以设置其基本信息和呈现方式,可以在空间中发布自己的文档、图片、音频、视频信息。
文件:上传在文件空间的一条信息,可能是文字描述,可能是图片,也可能是音频、视频,也可能是混合形式。一般由文件空间的所有者上传。空间显示的时候一般按照时间由近到远的顺序进行显示。
用户:指登录进入系统的一般用户,可能是普通的注册用户,并没有开通自己的文件空间。这里泛指系统中的正常用户。
综合上述,得到系统的功能性需求如下图。
系统用户的用例图
其中各功能性需求简要说明如下:
简单的系统登入登出及注册功能在这里不再详述。
用户角色能操作的功能主要集中于自己的文件空间方面,主要包括:上传文件管理,查看文档、图片、音频、视频数据列表,关键字管理,文件管理。这几个模块的访问一般是用户本人才能操作。
对系统的非功能性需求方面的要求,主要体现在性能需求和可靠性需求两个主要方面,下面从这两个核心的角度加以说明。
性能需求:由于属于Web服务型项目,这必然要求系统能承受大量的同时在线用户访问的问题。目前来看,只要系统结构设计得当,只需要保障硬件平台的性能需求就能将并发访问需求控制在合理的承受范围。因此虽然访问量和发布量大,但相对独立,运用软件架构可以很好的处理,同时使用应用服务器自身提供的集群特性可以很好地解决压力承受的性能要求。[4,5,6]
可靠性需求:由于不是重要的支撑平台,即使系统停机较长时间,也不会带来太大的损失,但可能会给用户造成很大的困扰,因此可以将可靠性需求映射到底层的支撑软件平台上,如使用Java应用服务器和mySQL数据库服务器,其本身较高的可靠性要求可以大体上实现本系统对整体可靠性的要求,同时结合软件架构内合理的辅助型框架应该能较好的满足可靠性要求。[4,6]
3 系统分析与设计
基于系统的需求,这个章节主要陈述分析得出系统的分析模型和设计模型,从逻辑上理解系统的实现方式和操作方式。下面叙述中没有严格按分析和设计划分小节,而是大体按照几个主题进行了陈述,将分析结果与设计结果大体连贯起来,后续的章节将介绍具体的实现。
3.1 系统的总体分析
针对B/S结构来说,整个系统服务都集中于服务器端,对服务器的架构设计一般使用3层架构或多层架构,这在Java体系结构设计中非常普遍。本系统使用常见的三层架构,即界面表示层、业务逻辑层、数据持久层。
整个系统的总体结构
系统总体布局如上图,客户端如需求所述,可能是PC机上的浏览器,也可能是基于手机的客户端,通过使用Web访问。如果将Web接口包装成Web Service接口,则可以接入更多类型的访问设备。其中表示层的职责主要集中于处理Web页面的数据显示、接收用户输入和各类操作,属于整个系统的最前端,但其中没有系统的操作逻辑,仅仅包含简单的页面交互方面的处理逻辑,一般使用JavaScript脚本来生成浏览器端的交互逻辑,并使用脚本将输入数据或操作结果反馈到后台业务逻辑层。这部分内容借鉴了课程《Web程序设计》和《Java高级编程》中的知识,使用了Dreamweaver,这是一个针对专业网页设计师特别发展的视觉化网页开发工具,利用它可以轻而易举地制作出跨越平台限制和跨越浏览器限制的充满动感的网页,这极大地减轻了表示层开发的工作量。在设计的过程中,深深体会到了封装以及基于组件开发带来的好处,具体地体会到了《软件工程》课程中的原来较为抽象的思想。
下图显示了整个系统的架构图。
系统体系架构
3.2 分析类的获取
确定了主要的系统用例,接下来需要得出分析类模型,用于评估整个系统,也起到了承接分析与启下设计的作用。归纳一下系统的功能,并综合操作特性,得到如下几个综合的操作界面类型:
主页面(index.jsp):是系统的首页面,主要呈现登录模块、搜索模块、系统下载模块、关于我们等信息。
个人主页面(main.jsp):用于个人有关的信息设置与管理,包括个人文件汇总信息(一个用户可以有多个文件空间)、个人信息管理模块、搜索模块、登录模块。
搜索页面():主要用于站内的信息搜索,包括用户、文件空间、文件关键字、一般包含信息的搜索及其结果。
控制类的作用集中体现了系统的业务逻辑,因此最终的控制类大部分都映射到了业务逻辑层,根据用例模型中的系统功能性描述,经过统筹安排,得出系统中的控制类如下:
登录控制(LoginServlet):专门负责登录的控制逻辑。
注册控制(RegisterServlet):专门处理新用户注册的问题。
查找功能在各个对象上都有体现,最终界面将分类显示,因此查找功能这样组织:
文件操作(FileService):用于统一各类查询及文件的删除,下载。
文件类型控制(GetFile):用于查询不同类型的文件。
用户查询(UserService):用于对用户进行各类信息进行筛选查询。
文件上传(FileUploadServlet): 用于文件的上传。
3.3 系统关键抽象概念的获取与分析
3.4 分析类交互
下面选取一个简单的登录过程和发布帖子这两个用例来说明分析类的交互过程分析。
登录过程在所有系统中都有体现,功能也简单直观。一般在操作的设计中,首次登录的时候只需要输入用户标识和密码即可登录,当用户名或密码不正确时,在后续的界面上加入验证码来防止破解攻击,多次无效后(一般控制在10次)账户便被锁定。本系统中由于没有太大的安全性需求,因此即使多次登录失败账户也不需要锁定,只需加入验证码即可。
用户类不属于系统内部,只是用来交互做输入的,因此可以看出用户需要打开主界面,在登录模块中输入用户名、密码,点击登录即可,成功后在会话中记录用户信息,在系统主页面中记录安全信息,这样在各个页面间跳转的时候就可以共享安全状态和安全凭据了。
4 系统设计
系统设计中需要综合考虑功能性需求和非功能性需求,而且非功能性需求更重要。一些部分需要软件设计模式的加入,但本人对设计模式了解还不很透彻,因此设计中只是完成了功能操作,没有再细致地考虑调整其结构,让它满足设计模式的要求,当然过多运用设计模式也会带来一些负面的影响,比如其结构复杂,不太容易立即理解,因此后面的设计暂时以满足功能要求为第一目标,然后重点考虑实现非功能需求的便捷操作的要求。
4.1 系统运行平台的设计选择
整个系统使用Java语言作为开发的基础语言,Web界面部分搭配使用HTML、CSS、Javascript以及JSP技术来实现。最终发布的系统对平台没有特别大的强制要求,因为基于Java开发的Web型服务项目,可以选用流行的Tomcat服务器或者JBoss服务器或者GlassFish服务器来搭建,这些都是开源免费的平台。数据库可以使用MySQL数据库,它也是免费使用的数据库,很多大型网站都选用了MySQL作为自己的数据库支持平台。开发过程中,选择平台搭建于Windows XP系统下,当然发布时可以选择Windows平台或Linux平台,两者的环境下都有上述的开源软件。
对于硬件平台,基本上没有强制性要求,只要是可用的服务器硬件平台都能完成正常部署和使用,当然性能高的服务器对多用户支持的效果会更好。
4.2 系统数据库的结构设计
根据前面的需求描述及领域模型的系统关键数据抽象,分析得出系统的数据库需要用户信息表和文件信息表:
4.3 数据库操作的设计
为了简化数据库操作的代码,防止过度的重复数据库常规执行的初始代码,将数据库操作进行封装是很必要的,这也为后期数据库升级和系统功能升级提供便利。数据库操作的封装还能有效隔离软件对具体数据库的依赖。
在实际项目开发中可以用的框架较多,比如JPA框架、Hibernate框架、JDO访问等,这些框架支持强大,但使用起来需要配置和编程传递接口等,因此在大中型项目中使用是较为合理的,本系统针对数据查询和更新操作较为简单,没有过多的附加操作,因此使用Apache的开源项目JDBC可以很好的实现数据库的访问和操作。在项目中定义ConnDB访问数据源封装信息。
private static final String driver = "com.mysql.jdbc.Driver"; //数据库驱动
public Connection getConnection() {
Connection conn = null;
//加载数据库驱动
try{
Class.forName(driver);
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/hxj"
"?useUnicode=true&characterEncoding=utf8",
"root","123456");
}catch(Exception e){
e.printStackTrace();
}
System.out.println("数据库连接成功!");
return conn;
}
使用ConnDB中的类进行操作,简化了大量的数据库访问代码。比如要查阅回复情况,定义查询条件,可以直接调用ConnDB来创建连接数据库。比起常规的JDBC操作有了极大的简化。因此使用Apache的组件可以极大的提高开发的效率。
4.4 用户界面设计
用户界面部分总体上划分为以下几个方面:登录注册页首页面、个人中心页面、搜索页面、文件上传页,文件列表页。
主页页面:
登录页面:
注册页面:
个人主页:
搜索页:
文件上传页:
文件浏览页:
5 系统实现
系统实现中,主要是根据设计模式实现其中定义的方法和功能即可。在软件项目中实现的工作量比设计要轻很多,这也是《软件工程》课程中重点提醒的要重设计、轻实现的思想。这里选介绍具体实现过程,由于篇幅所限,只给出核心功能代码,页面样式代码省略。
首先给出本系统需要的两个基本实体类的设计,用户和文件,以及它们对应的操作类,后面的功能都是基于此实现的
用户类:
public class User {
private int id;
private String username;
private String password;
public User(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
}
文件类:
public class File {
private int id;
private String title;
private String type;
private String publishingtime;
public File(){
}
public File(int id,String title,String type,String publishingtime){
this.id=id;
this.title=title;
this.type=type;
this.publishingtime=publishingtime;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPublishingtime() {
return publishingtime;
}
public void setPublishingtime(String publishingtime) {
this.publishingtime = publishingtime;
}
}
用户信息操作类:
public class UserDao {
public void addUser(User user) {
Connection conn = new ConnDB().getConnection();
PreparedStatement pstmt = null;
try {
String sql = "insert into user(username,password) " +
"values('"+user.getUsername()+"','"+user.getPassword()+"')";
pstmt = conn.prepareStatement(sql);
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
conn.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public User getUserById(String id) {
Connection conn = new ConnDB().getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
User us = new User();
try {
String sql = "select * from user where id="+id+"";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if(rs.next()){
us.setId(rs.getInt("id"));
us.setUsername(rs.getString("username"));
us.setPassword(rs.getString("uassword"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
conn.close();
pstmt.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return us;
}
public List<User> getUserByUserName(String username) {
ConnDB myDB = new ConnDB();
User user = new User();
List<User> list = new ArrayList<User>();
String sql = "select * from user where username ='"+username+"'";
try{
ResultSet mySet = myDB.getResultSet(sql);
while(mySet.next()){
user.setId(mySet.getInt("id"));
user.setUsername(mySet.getString("username"));
user.setPassword(mySet.getString("password"));
list.add(user);
}
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}catch(ClassNotFoundException cnfEx){
cnfEx.printStackTrace();
}finally{
try{
myDB.releaseConnection();
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}
}
return list;
}
}
文件操作类:
public class FileDao {
public FileDao(){
}
public void addFile(File file) {
ConnDB myDB = new ConnDB();
String sql ="insert into file"+"(title,type,publishingtime) values('"+file.getTitle()+"','"+file.getType()+"','"+file.getPublishingtime()+"')";
try{
myDB.executeSQL(sql);
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}catch(ClassNotFoundException cnfEx){
cnfEx.printStackTrace();
}
}
public boolean deleteFile(int id){
ConnDB myDB = new ConnDB();
String sql ="delete from file where id='"+id+"'";
try{
myDB.executeSQL(sql);
return true;
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
return false;
}catch(ClassNotFoundException cnfEx){
cnfEx.printStackTrace();
return false;
}
}
public File getFileByTitle(String title){
ConnDB myDB = new ConnDB();
File file = new File();
String sql ="select * from file where title='"+title+"'";
try{
ResultSet mySet = myDB.getResultSet(sql);
while(mySet.next()){
file.setId(mySet.getInt("id"));
file.setTitle(mySet.getString("title"));
file.setType(mySet.getString("type"));
file.setPublishingtime(mySet.getString("publishingTime"));
}
}catch(ClassNotFoundException cnfEx){
cnfEx.printStackTrace();
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}finally{
try{
myDB.releaseConnection();
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}
}
return file;
}
public List<File> getFileByType(String type) {
String sql = "select * from file where type='"+type+"'";
return getFileBySqlString(sql);
}
public List<File> getAllFile() {
String sql = "select * from file";
return getFileBySqlString(sql);
}
public List<File> getFileBySqlString(String sql){
ConnDB myDB = new ConnDB();
List<File> list = new ArrayList<File>();
try{
ResultSet mySet = myDB.getResultSet(sql);
while(mySet.next()){
File file = new File();
file.setId(mySet.getInt("id"));
file.setTitle(mySet.getString("title"));
file.setType(mySet.getString("type"));
file.setPublishingtime(mySet.getString("publishingTime"));
list.add(file);
}
}catch(ClassNotFoundException cnfEx){
cnfEx.printStackTrace();
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}finally{
try{
myDB.releaseConnection();
}catch(SQLException sqlEx){
sqlEx.printStackTrace();
}
}
return list;
}
}
5.1注册登录的实现
注册功能主要实现往数据库存储用户信息:
<form action="servlet/RegisterServlet" method="post">
<p class="main1">
<label>用户名: </label>
<input type="text" name="username" value="" size="20" maxlength="20" onfocus="if (this.value=='Your name') this.value='';" />
</p>
<p class="main2">
<label>密 码: </label>
<input type="password" name="password" value="" size="20" maxlength="20" onfocus="if(this.value=='Your Password') this.value='';">
</p>
<p class="space">
<input type="submit" value="注册" class="register" style="cursor: pointer;"/>
</p>
</form>
控制处理层:
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter out=response.getWriter();
String username=request.getParameter("username");
String password = request.getParameter("password");
try{
User user = new User();
if(username !=null && password !=null){
user.setUsername(username);
user.setPassword(password);
UserService userService=new UserService();
//调用业务逻辑层的方法完成注册功能
userService.addUser(user);
out.write("注册成功!");
}else {
out.write("注册信息不完整!");
}
}
catch(Exception ex){
ex.printStackTrace();
out.write("注册失败!");
}
out.flush();
out.close();
}
}
登录功能主要通过一个表单提交用户信息给servlet,服务器查询数据库与之匹配,成功则跳转到主页,否则给出登录失败提示信息:
<form action="servlet/loginServlet" method="post">
<p class="main">
<label>用户名: </label>
<input type="text" name="username" value="" />
<label>密码: </label>
<input type="password" name="password" value="">
</p>
<p class="space">
<input type="submit" value="登录" class="login" /> <input type="reset" value="清空" style="cursor: pointer;"/>
</p>
</form>
控制处理层:
public class LoginServlet extends Ht
展开阅读全文