分类

课内:
不限
类型:
不限 毕业设计 课程设计 小学期 大作业
汇编语言 C语言 C++ JAVA C# JSP PYTHON PHP
数据结构与算法 操作系统 编译原理 数据库 计算机网络 软件工程 VC++程序设计
游戏 PC程序 APP 网站 其他
评分:
不限 10 9 8 7 6 5 4 3 2 1
年份:
不限 2018 2019 2020

资源列表

  • 基于JSP和MYSQL的学生选课管理系统

    第一阶段:开发前的设置和思考1.1 题目要求建立一个学生选课系统, 编写应用程序完成系统开发。
    1.1.1 建立基本表
    学生(学号,姓名,性别,年龄,系别)
    课程(课程号,课程名,开课系,任课教师)
    学习(学号,课程号,成绩)

    1.1.2 要求有以下子系统
    基本信息查询子系统:能够显示出学生表、课程表、带参数学生详细信息和选课情况
    学生、课程信息维护子系统:能够维护学生表和课程表
    学生选课子系统:考虑参照完整性以及用户自定义完整性,实现学生选课功能
    系统维护

    1.2 需求分析根据描述,这个系统不仅是选课系统,而是有其他教务管理和信息查询和维护的教务管理系统,选课系统只是这个教务管理系统的一个子系统。
    使用教务管理系统的用户有三种,一种是学生,一种是任课教师,另外一种损失教务处的老师,可以认为是管理员,所以可以将用户也分为这三种,不同的用户登录到这个系统中要有不同的界面,不同的功能。
    学生登录后有相关的信息查询和部分信息修改的权限,信息查询包括查询自己的个人信息,(自己的学号,班级,专业,籍贯,政治面貌,邮箱,联系方式等)选课信息(选了哪些课,课程表查看,每门课上课的时间,地点,任课教师,教学周起始等),成绩信息(查看自己的成绩信息,包括课程名称,分数,哪一个学期选修的这门课,任课教师等)。修改权限包括学生部分个人信息的修改(比如学生的联系电话,qq和微信,家庭住址,政治面貌等),在选课阶段修改自己的所选课程信息(在选课阶段,自由的增加选课和取消选课),修改自己的登录密码等。另外,仿照现有教务管理系统,增加私信老师的功能,使得学生可以向老师提交反馈,老师可以根据反馈进行相应的操作,学生可以不用打电话或者到教务处办公室寻求帮助。
    任课教师登录后功能和学生不同,任课教师可以查看自己现在这个学期教授哪些课程,可以查看这门课的详细教学安排时间表,这门课的上课地点等信息,可以查看选修了这门课的所有学生的信息(教务相关等基本信息,其他私人信息不会看到,另外,只有选修了自己所教授课程的学生的信息老师才可以查看,其他学生的不可以),查看自己的个人信息,和学生一样。任课教师可以修改自己部分的个人信息,修改自己的登录密码,在一个时间范围内给选修了自己课程的学生进行评分以及修改分数等操作,另外,任课教师还可以申请新开一门课程,在得到教务处的允许后方可成为正式的课程。
    教务处教师登录后的功能比较多,可以审核通过任课教师提出的新课的审核,可以发布系统公告,查看学生的求助并作出相应的处理,可以进行课程的安排,可以创建每个专业的选课清单,可以对每个选课清单进行控制(停止选课和开始选课等),可以添加新的教职工信息和学生信息。
    所有的信息查看功能都有搜索功能,可以在信息比较多的情况下根据用户输入的学号,工号,专业,以及状态等进行结果的缩减,达到快速检索到信息的目的,支持模糊搜索。
    1.3 概念结构设计系统的ER图如下:

    1.4 逻辑结构设计1.4.1 实体(加粗表示主键)
    学生(学号,姓名,性别,学院,专业,班级,状态等)
    教师(工号,姓名,性别,学院,职称,地址,电话,类别等)
    管理员(工号,姓名,性别,学院,职称,地址,电话,类别等)
    课程(课程号,课程名称,开课学院,先修课程号,开课学院,简介,状态)

    1.4.2 联系(加粗表示主键)
    选修(学期,学号,课程号,成绩)
    教授(学期,工号,课程号,教学开始周,教学结束周,教学班容量,教室地址,状态)
    求助(消息id,学号,发送时间,标题,内容,状态)
    安排(学期,工号,课程号,教学开始周,教学结束周,教学班容量,教室地址,状态)

    1.5 数据库物理结构设计数据库名称为DB,数据表数量为11个。

    1.5.1 学生表
    1.5.2 教师表
    1.5.3 管理员(根据逻辑结构设计部分发现,教师和管理员其实可以合并)
    1.5.4 课程表
    1.5.5 选课表
    1.5.6 课程安排表
    1.5.7 教师授课表(研究发现,可以和安排表合并)
    1.5.8 课程时间表
    1.5.9 学期表
    1.5.10 消息表
    1.5.11 公告表
    1.5.12 选课清单表
    1.5.13 用户登录信息表
    第二阶段:开发编码调试工作2.1 开发环境相关
    开发后台服务语言:Java 版本1.8
    服务器: Tomcat 版本 9.0.14
    数据库:MySql 5.7
    操作系统:Windows10
    开发工具:Jetbrains Intelij IDEA

    2.2 开发所用技术
    Web前端:HTML,CSS,JavaScript,Jquery,Bootstrap
    Web后端:原生Java Web,Servlet,JDBC,JSTL,数据库连接池DHCP,JSP

    2.3 源代码目录简介
    .idea:IDEA编译器的配置文件,系统默认生成,无序关心
    lib和libs:自己下载的驱动包和第三方jar包,包括数据库驱动和jstl
    out:字节码文件,为Java虚拟机实际运行的文件,编译之后生成,无需关心
    sql:数据库备份文件,完整的数据表结构和部分数据
    src:Java代码编写处

    DB:存放有关数据库操作的类model:存放数据表结构相关的Java bean类servlet:存放业务逻辑处理的servlet类
    web:存放静态资源和网页模板的类

    app:放所有的jsp网页模板css:放所有的层叠样式表文件js:放所有的JavaScript脚本文件WEB-INF:系统自动生成 ,无需关心,是网站的配置信息文件


    2.4 项目典型代码讲解2.4.1 数据库连接工具类:DBpackage DB;import java.sql.*;public class DB { //初始化连接参数; public static String url="jdbc:mysql://localhost:3306/db?serverTimezone=UTC&useSSL=false&characterEncoding=utf8"; public static String user="root"; public static String password="root"; //初始化驱动加载: static{ try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() { try { Connection connection=DriverManager.getConnection(url,user,password); return connection; } catch (SQLException e) { e.printStackTrace(); } return null; } public static void close(Connection connection,Statement st,ResultSet rs) { try { connection.close(); st.close(); rs.close(); } catch(Exception e) { e.printStackTrace(); } } public static void close(Connection connection,PreparedStatement st) { try { connection.close(); st.close(); } catch(Exception e) { e.printStackTrace(); } } public static void close(Statement st) { try { st.close(); } catch(Exception e) { e.printStackTrace(); } } public static void close(Connection connection) { try { connection.close(); } catch(Exception e) { e.printStackTrace(); } } public static void close(ResultSet resultSet) { try { resultSet.close(); } catch(Exception e) { e.printStackTrace(); } }}
    以上类用于数据库的连接,获取连接对象,然后还有关闭连接的函数,对关闭连接的函数进行了重载,可以关闭连接对象,语句对象,结果集对象的任何一个子集组合,完善的异常处理机制,可以简化其他用到数据库连接的地方,减少代码量。
    2.4.2 登录Servletpackage servlets.publicfun;import DB.SemesterDB;import DB.StudentDB;import DB.TeacherDB;import DB.UserDB;import model.Student;import model.Teacher;import model.User;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;import java.sql.SQLException;@WebServlet("/LoginServlet")public class LoginServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String account=request.getParameter("account"); String password=request.getParameter("password"); String type=request.getParameter("type"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); if(account==""||password=="") { PrintWriter printWriter=response.getWriter(); printWriter.println("您的用户名或者密码为空,请重新登陆"); printWriter.flush(); printWriter.close(); } else { UserDB userDB=new UserDB(); User user=userDB.login(account,password,type); if(user==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('用户名或者密码错误!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); } if(type.equals("student".toString())) { //查询学生表详细信息,并设置session StudentDB studentDB=new StudentDB(); Student student=studentDB.getInfo(user.getAccount()); if(student==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('没有您的登录信息,请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); } else { SemesterDB semesterDB=new SemesterDB(); String semester=null; try { semester=semesterDB.getCurrentSemester(); } catch (SQLException e) { e.printStackTrace(); } if(semester==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('学期列表出现错误,请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); response.setStatus(500); } HttpSession session = request.getSession(); session.setAttribute("userinfo", student); session.setAttribute("type","student"); session.setAttribute("semester",semester); //重定向到另外一个servlet response.setStatus(302); response.sendRedirect("content"); } } else if(type.equals("teacher")) { //查询教师表详细信息,并设置session TeacherDB teacherDB=new TeacherDB(); Teacher teacher=teacherDB.getInfo(user.getAccount()); if(teacher==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('没有您的登录信息,请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); } else { SemesterDB semesterDB=new SemesterDB(); String semester=null; try { semester=semesterDB.getCurrentSemester(); } catch (SQLException e) { e.printStackTrace(); } if(semester==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('学期列表出现错误,请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); response.setStatus(500); } HttpSession session = request.getSession(); session.setAttribute("userinfo", teacher); session.setAttribute("type","teacher"); session.setAttribute("semester",semester); response.setStatus(302); response.sendRedirect("content"); } } else if(type.equals("root")) { TeacherDB teacherDB = new TeacherDB(); Teacher teacher = teacherDB.getInfo(user.getAccount()); if (teacher == null) { PrintWriter printWriter = response.getWriter(); printWriter.print("<script type='text/javascript'>alert('没有您的登录信息,请联系管理员!');window.location.href='" + request.getContextPath() + "/index.jsp'</script>"); printWriter.flush(); printWriter.close(); } else { //设置管理员身份标识 teacher.setType("root"); //设置管理员登录标识 SemesterDB semesterDB=new SemesterDB(); String semester=null; try { semester=semesterDB.getCurrentSemester(); } catch (SQLException e) { e.printStackTrace(); } if(semester==null) { PrintWriter printWriter=response.getWriter(); printWriter.print("<script type='text/javascript'>alert('学期列表出现错误,请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp'</script>"); printWriter.flush(); printWriter.close(); response.setStatus(500); } HttpSession session = request.getSession(); session.setAttribute("userinfo", teacher); session.setAttribute("type","root"); session.setAttribute("semester",semester); //重定向到另外一个servlet response.setStatus(302); response.sendRedirect("content"); } } } }}
    这里登录只是验证一下是不是用户名和密码都正确,同时保存用户登录的信息到session中,设置登录状态的标志,以后的所有界面如果没有session的话都会自动跳转到登录界面,保证了只有是系统已经登录成功的用户才可以进行相关的查询和修改操作。
    2.4.3 首页初始化Servlet因为所有首页登录进去之后都有一些数据是在数据库中取到的,所以要在加载页面之前从数据库中取出数据加到request域中,让前端可以访问并显示这些数据。因为教师,学生,管理员的首页界面不同,所以需要进行判断身份,然后连接不同的数据库,发送不同的信息到前端。
    package servlets;import DB.*;import model.*;import view.Course_select;import view.Course_teach;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;@WebServlet("/content")public class content extends HttpServlet { protected void doPost(HttpServletRequest request, ttpServletResponse response) throws ServletException, IOException { HttpSession session=request.getSession(); try { String type = (String) session.getAttribute("type"); if (type.equals("root")) { MessageDB messageDB = new MessageDB(); List<Message> result = messageDB.getAllUncomplete(); CourseDB courseDB = new CourseDB(); List<Course> courseapp = courseDB.getAllUncompleCourse(); request.setAttribute("helpList", result); request.setAttribute("newcourse", courseapp); request.getRequestDispatcher("app/content.jsp").forward(request, response); } else if (type.equals("student")) { Student student =(Student) session.getAttribute("userinfo"); String sno=student.getSno(); String semester=(String) session.getAttribute("semester"); if(semester==null) { response.setStatus(500); PrintWriter printWriter =response.getWriter(); printWriter.print("<script>alert('学期表出现错误!请联系管理员!');window.location.href='"+request.getContextPath()+"/index.jsp';</script>"); printWriter.flush(); printWriter.close(); } NoticeDB noticeDB = new NoticeDB(); StudyCourseDB studyCourseDB=new StudyCourseDB(); try { List<Notice> result = noticeDB.getNotice(); List<Course\_select> course\_table=studyCourseDB.getCourseTableList(sno,semester); List<StudyCourse> gradelist=studyCourseDB.getGradeList(sno,semester); request.setAttribute("noticelist", result); request.setAttribute("course\_table\_list",course_table); request.setAttribute("grade_list",gradelist); request.getRequestDispatcher("app/content.jsp").forward(request, response); } catch (SQLException e) { e.printStackTrace(); } } else if (type.equals("teacher")) { String semester=(String) session.getAttribute("semester"); Teacher teacher=(Teacher) session.getAttribute("userinfo"); String tno=teacher.getTno(); NoticeDB noticeDB = new NoticeDB(); Course\_teacheDB db=new Course\_teacheDB(); ArrayList<Course\_teach> teach\_list=db.getTeachList(semester,tno); List<Notice> result = noticeDB.getNotice(); request.setAttribute("noticelist", result); request.setAttribute("teachlist",teach_list); request.getRequestDispatcher("app/content.jsp").forward(request, response); } } catch (Exception e) { PrintWriter printWriter=response.getWriter(); printWriter.println("<script>window.location.href='"+request.getContextPath()+"'</script>"); printWriter.flush(); printWriter.close(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); }}
    第三阶段:系统演示和说明3.1 用户登录
    3.2 学生相关3.2.1 学生首页
    3.2.2 修改密码
    3.2.3 选课

    3.2.4 查看课表
    3.2.5 查看个人信息
    3.2.6 联系老师
    3.2.7 成绩查询
    3.3 教师相关3.3.1 教师首页
    3.3.2 个人信息维护(同学生版页面)
    3.3.3 修改密码(同学生版页面)
    3.3.4 申请新课
    3.3.5 课程评分和修改

    3.3.6 查看公告
    3.3.7 查看学生信息(需要选课之后才可以看)
    3.3.8 授课查看

    3.4 管理员相关3.4.1 管理员首页
    3.4.2 安排课程
    3.4.3 添加人员
    3.4.4 运行控制
    3.4.5 创建选课清单
    3.4.6 新课审核
    3.4.7 学生求助信息
    3.4.8 发布公告
    3.4.9 课程信息
    第四阶段:总结与反思通过学习数据库原理这门课,我学到的不仅仅是技术方面的东西,更加重要的是学会了如何去进行需求分析,对系统开发有了一个清晰的认识,对数据库的设计有了更深层次的认知,或许只有真正自己开发了之后才会有很深刻的理解吧,或许这就是数据库原理课程设计的目的所在。这门课程我从零开始学习Java web开发,从零开始学习JDBC,感谢老师给了我机会在同学们面前展示自己,锻炼自己。
    2 评论 17 下载 2019-11-17 11:39:36 下载需要15点积分
  • 基于C++实现校园卡管理系统

    1 实验目的
    本实验面向 C++语言的初学者
    主要让实验者熟悉面向对象的编程思想以及类的使用

    2 实验环境本实验可基于Visual Studio 或Eclipse 或Devc++平台开发,参考主流的编码规范,如Google C++Style Guide(中文版)
    2.1 编程语言和开发工具
    编程语言: ANSI C++
    开发工具: dev cpp

    2.2 编码规范要求遵循良好的程序设计风格来设计和编写程序。基本编码规范:

    标识符的命名要到达顾名思义的程度
    关键代码提供清晰、准确的注释
    程序版面要求:

    不同功能块用空行分隔一般一个语句一行语句缩进整齐、层次分明

    3 实验内容编写校园卡管理系统,进行对校园卡,储蓄卡的管理和绑定,其中包括新建,消费,转账,查询,存款等操作。
    4 分析与设计简要描述程序设计的过程,包括设计思路,设计要点及特色;程序的不足与改进等。要求画出程序的简单流程图。
    4.1 需求分析校园卡的消费,查询;储蓄卡的消费,转账,查询,其中可转账给其他储蓄卡或者校园卡,可以透支;绑定卡的校园卡可以在无存款时透支储蓄卡上的金额。
    4.2 类结构设计类关系图

    4.3 细节设计数据成员
    class Account{ //流水账类 public: string adress; double amount; long id; long time; bool xaiofei=0; bool zhuanru=0; bool zhuanchu=0; bool cunru=0; };class Card{ //基类 card 类 public: card(){} long id; string name; double overage; int listnum; Account *listarray; virtual void pay(){} virtual void inquire(){} };class Campuscard:public Card{ //继承类校园卡类 public: campuscard(); void pay(string adress, double amount); void inquire(); string school; bool isbinding; long bindid;};class Debitcard:public Card{ //继承类储蓄卡类 public: debitcard(); void pay(string adress,double amount); void inquire(); void transfers1(Debitcard &othercard); void transfers2(Campuscard &othercard); void debit(double amount); int getYear(){ return year; } int getMon(){ return mon; } int getDay(){ return day; } private: long timee; double limit; //透支额度 double moneyed; //已用透支数额 double surplus; //剩余额度 };
    成员函数
    virtual void pay(){} virtual void inquire(){} card(){}campuscard(); void pay(string adress,double amount); void inquire();debitcard(); void pay(string adress,double amount); void inquire(); void transfers1(Debitcard &othercard); void transfers2(Campuscard &othercard); void debit(double amount);
    5 设计心得上课要认真听讲,下来要多练习,然后其实也不太会。其实还是学到了很多,尤其是在不太懂的地方请教别人。本来说用文件输入输出,结果发现自己还是不会,然后就放弃了。感觉看看自己前两个项目又会收获很多。
    6 程序主界面
    2 评论 114 下载 2018-11-05 21:43:13 下载需要5点积分
  • 基于α-β剪枝算法实现的AI五子棋游戏

    一、对抗问题对抗问题:顾名思义,博弈双方是带有对抗性质的。博弈的任何一方都希望局面尽量对自己有利,同时局面也应该尽量令对方不利。通常这一类问题可以通过 Minimax 算法解决。
    Minimax 算法又名极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。Minimax 算法常用于棋类等由两方较量的游戏和程序,这类程序由两个游戏者轮流,每次执行一个步骤。为了执行 Minimax 算法,我们可以通过穷举的方式,枚举所有的状态空间,从而使得我们可以在游戏刚一开始,就预测到输赢。但是,在实际情况下,游戏的状态空间都是异常庞大的。很显然,我们不能将以穷举方式实现的 Minimax 算法用于实际应用。
    二、α-β减枝通过分析可以发现,在利用穷举方法执行 Minimax 算法中有许多的无效搜索,也就是说,许多明显较劣的状态分支我们也进行搜索了。我们在进行极大值搜索的时候,我们仅仅关心,下面最大的状态,对于任何小于目前值的分支也都是完全没有必要进行进一步检查的。(α减枝)

    通过上图,我们可以发现,我们可以减去大量无用的状态检查,从而降低我们的运算量。
    同时,我们在进行极小值搜索的时候,我们仅仅关心,下面最小的状态,对于任何大于目前值的分支都是完全没有必要进行进一步检查的。(β 减枝)

    通过上图,我们可以发现,我们可以减去大量无用的状态检查,从而降低我们的运算量。
    将上述所提到的 α 减枝与 β 减枝进行综合就可以得到 α-β 减枝。对于对抗搜索而言,我们需要精心设计其估值函数,不然我们的 α-β 减枝将毫无用武之地。
    三、五子棋问题五子棋:是一种两人对弈的纯策略型棋类游戏,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成 5 子连线者获胜。

    这里,我们采用了极大极小博弈树(MGT),来实现 AI。这里用一张井字棋的搜索示意图来说明。

    上图很清晰的展示了对局可能出现的所有情况(已经去除了等价的情况),如果让这个图延展下去,我们就相当于穷举了所有的下法,如果我们能在知道所有下法的情况下,对这些下法加以判断,我们的 AI自然就可以选择具有最高获胜可能的位置来下棋。极大极小博弈树就是一种选择方法,由于五子棋以及大多数博弈类游戏是无法穷举出所有可能的步骤的(状态会随着博弈树的扩展而呈指数级增长),所以通常我们只会扩展有限的层数,而 AI 的智能高低,通常就会取决于能够扩展的层数,层数越高,AI 了解的信息就越多,就越能做出有利于它的判断。
    为了让计算机选择那些获胜可能性高的步骤走,我们就需要一个对局面进行打分的算法,越有利,算法给出的分数越高。在得到这个算法过后,计算机就可以进行选择了,在极大极小博弈树上的选择规则是这样的:

    AI 会选择子树中具有最高估值叶子节点的路径
    USER 会选择子树中具有最小估值叶子节点的路径

    这样的原则很容易理解,作为玩家,我所选择的子一定要使自己的利益最大化,而相应的在考虑对手的时候,也不要低估他,一定要假设他会走对他自己最有利,也就是对我最不利的那一步。
    接下来,我们实现关键的局面评分步骤:直接分析整个棋面是一件很复杂的事情,为了让其具备可分析性,我们可以将其进行分解,分解成易于我们理解和实现的子问题。
    对于一个二维的期面,五子棋不同于围棋,五子棋的胜负只取决于一条线上的棋子,所以根据五子棋的这一特征,我们就来考虑将二维的棋面转换为一维的,下面是一种简单的思考方式,对于整个棋盘,我们只需要考虑四个方向即可,所以我们就按照四个方向来将棋盘转换为 15 * 6 个长度不超过 15 的一维向量(分解斜向的时候,需要分为上下两个半区),参考下图:

    我们的目的是为了为其评分,那么我们就还需要评估每个线状态,将每个线状态的评分进行汇总,当做我们的棋面评分:

    接下来我们所要做的就是评价每一条线状态,根据五子棋的规则,我们可以很容易穷举出各种可能出现的基本棋型,我们首先为这些基本棋型进行识别和评价,并且统计每个线状态中出现了多少种下面所述的棋型,并据此得出评价值,得到如下图所示的静态估值表:

    根据这个表以及我们之前所谈到的规则,我们就可以得到一个可以运行的AI了。
    四、进一步的优化注意到,如果我们搜索到第四层,总共需要搜索:224 + 224 223 + 224 223 222 + 224 223 222 221 = 2 461 884 544 个状态节点,搜索如此多的状态节点的开销是十分可观的,因此,我们提高效率的方式就锁定到了:如何减少需要搜索的状态节点。
    我们可以采取以下方法来减少需要搜索的状态节点:

    我们可以利用经典的α-β剪枝算法对博弈树剪枝
    我们可以每次搜索仅搜索落子点周围 2*2 格范围内存在棋子的位置,这样可以避免搜索一些明显无用的节点,而且可以大幅度提升整体搜索速度
    避免对必胜/负局面搜索,当搜索过程中出现了必胜/负局面的时候直接返回不再搜索,因为此时继续搜索是没有必要的,直接返回当前棋局的估价值即可
    加入随机化AI的下棋方式,普通的AI算法对于给定的玩家下棋方式会给出固定的回应,这就导致玩家获胜一次之后只要此后每次都按此方式下棋,都能够获胜。为了避免这种情况,可以在 AI选择下子位置的时候,在估值相差不多的几个位置中随机挑选一个进行放置,以此增加 AI的灵活性

    规划搜索顺序,有很多有价值的下子点存在于更靠近棋盘中央的地方,如果从棋盘中央向外搜索的话,则能够提高α-β剪枝的效率,让尽可能多的分支被排除
    五、实验成果

    六、实验总结通过本次实验,加强了组员之间的沟通协调能力,同时也提高了我们对αβ减枝算法的了解。我们更了解了五子棋相关的游戏规则以及一些技巧,拓宽了我们的知识面,有助于我们在未来的生活中更好的与人交流。
    同时,经过此次实验,我们深入了解了棋类人工智能算法,进一步的提升了我们的专业水平,有助于我们在未来的就业与科研岗位上走的更远。
    虽然α-β减枝实现起来非常容易,但是五子棋的局势估计却十分的有挑战性,其局势估计的准确与否直接影响了程序的运行结果是否令人满意,AI是否能够展现出足够的智能。
    2 评论 64 下载 2019-06-20 11:16:55 下载需要12点积分
  • 基于JSP SSM框架的城市公交查询系统的设计与实现

    摘 要公交查询系统是为了方便人们查询公交的信息,并且能够及时的做到信息更新,其主要是要做到方便人们的使用,信息的可维护性和程序的稳定性 。本系统采用了JAVA编程语言,数据库使用Mysql。计算机技术不断发展,逐渐适应用于各领域,给人们的学习工作生活带来了便利,在公交查询系统也是这样。纸质的公交指南或繁杂的网络版公交指南,都在不同程度上限制了市民出行的方便性。本论文介绍的是一个城市的公交查询系统,方便市民用最简约的方式,查询到最实用的公交信息。本论文是在此系统经过测试并且所有功能都实现的基础上完成的,主要涉及软件,数据库与网络技术等。
    关键词:城市公交查询系统;数据库;JAVA;SSM
    AbstractThis city buses inquiry system aims to make the resident inquire city buses information more convenient and must achieve the information not too lag, but its main idea is the system administrate user-friendly, the data processes reliability, the maintainability, as well as procedure toughness. The system uses the JAVA programming language and MYSQL as database. Along with computer technology’s unceasing development, the computer applies in each big domain, and has brought the enormous convenience to people’s life, the city buses referral system is also. The departed paper city buses guide or the numerous and diverse online edition city buses guide, has limited the conveniences which in the different procedure when a resident goes on a journey. This thesis introduces a city buses referral system, by facilitates the resident with the briefest way and inquires the most useful city buses information. This thesis that is based on the system has been tested and functions all come true mainly involves software, database and networking and so on.
    Key words: City Buses inquiry system; Databases; JAVA; SSM
    1 概述1.1 项目开发背景和现状的研究1.1.1 开发背景随着城市建设的飞速发展,生活节奏的加快,公交系统对城市来说越来越重要。而政府在这方面的投入也是加大了力度,城市中的公交系统也是日益完善,公交系统的不断更新,却又导致了市民无法从原来的公交指南上看到现如今的信息,从而产生了很多不必要的麻烦。所以需要提供一个高效的公交查询系统,才是问题的根本所在。
    现在,随着计算机技术和通信技术的发展,与网络相结合是现如今的重要发展方向,特别是在网络普及,上网极为方便的网络信息时代,通过上网来查询公交信息是公交查询系统的发展方向。
    1.1.2 研究现状公交查询系统是为了方便人们查询公交的一些信息,并且能够做到信息的及时更新,主要是要方便人们的使用,信息的可维护性和程序的稳定性 。本系统采用JAVA,数据库使用的是Mysql。计算机技术的不断发展,逐渐适应用于各领域,给人们的学习工作生活带来了便利,在公交查询系统也是这样。纸质的公交指南或繁杂的网络版公交指南,都在不同程度上限制了市民出行的方便性。本论文介绍的是一个城市的公交查询系统,方便市民用最简约的方式,查询到最实用的公交信息。
    1.2 项目开发目的与意义1.2.1 系统开发的目标本系统是基于J2EE的公交查询系统,其中包括了公交查询系统的基本功能,并提供了用户留言的功能,方便根据用户提供的留言信息或是提出的建议对系统进行修改和完善,并提供了管理员用户后台维护公交信息的功能,做到能够实时添加和删除公交车次站点。除主要功能以外本系统还附带发布寻物启示与失物招领模块,方便用户。 本系统目标是方便市民进行公交信息查询,并且要做到信息不滞后,其主要思想是做到系统管理的人性化,数据处理的可靠性,可维护性,以及程序的健壮性[2]。系统提供了用户留言的功能,根据用户提供的留言信息或提出的建议提高公交公司的服务质量。基于J2EE的城市公交查询系统,它采用B/S模式。该系统不仅可以用于公交公司管理系统中,也可以单独作为公交管理系统的一个模块存在,并可以制作成城市公交信息系统查询网,放置于城市的主要场所[3]。这样不仅可以体现出一个城市的智能公交系统的水平,更显示出城市的数字化,信息化水平。
    1.2.2 系统开发的意义Internet 是城市公交信息查询系统得以实现的基础。在当今社会,网络大为普及,上网极为方便,通过网络查询公交信息更是城市公交信息查询系统的发展方向,与网络相结合是大势所趋[4]。城市公交信息查询系统旨在应用现代的信息网络化为广大乘客提供一种方便快捷的乘车线路服务,让网络惠及更多的人。提高市民的出行效率,促进社会的和谐。
    本论文主要涉及软件,数据库与网络技术等。涵盖知识面广,可有效地提高学生综合运用所学知识分析解决问题的能力,增强学生对事物的理解与掌握能力,培养学生掌握科学的研究方法,正确的设计思想,独立思考,勇于进取,探索创新,为今后进一步学习与工作奠定了良好的基础。
    1.3 本论文研究的主要内容本论文采用软件工程思想来进行城市公交信息查询系统的设计与实现。
    首先,介绍当前形势下大多数城市公交路线查询系统存在的诸多问题。在此基础上提出本系统的现实意义以及必要性。对城市公交信息查询系统进行了可行性分析,确定了本系统的功能、性能、界面等。
    其次,对城市公交信息查询系统进行模块分解,确定软件结构,模块功能和模块间的接口,以及数据库的设计。及根据需求分析中提出的思路来设计系统,对各个模块的设计进行了描述。然后给出了城市公交信息查询系统的整体结构图以及各个模块的实现流程图以及数据库设计时需要的表结构。
    再次,对本系统进行详细设计,在此基础上对各个模块的实现进行了介绍,给出了本系统的效果图,并且对重要功能给出了主要代码。
    最后,对系统进行了测试及分析。本文对软件测试的概念和方法进行了概要说明,并对系统的设计和实现进行了总结,提出了对城市公交信息查询系统的展望和具体的改进建议。
    2 需求分析2.1 需求分析2.1.1 系统需求由于本系统面向广大市民和公交公司管理本系统等非计算机专业人士的需求,因此要求硬件配置不能太高,任何一个普通的计算机用户都能很快的熟悉整个软件的使用。本系统要做到所耗费的资源常小,任何用户只需要在一般的电脑上面,就能够通过浏览器使用这个软件。公交公司管理人员能够简单、方便、快捷、远程的实现对系统实时维护和管理。
    2.1.2 技术需求本系统是以互联网为基础,采用SSM框架MySQL数据库开发模式,服务器采用Tomcat 6.0。服务器由数据库服务器、Web服务器等服务器组成,通过客户端网络连接进行系统的管理和维护,数据库服务器中的数据要实现实时更新,数据库要可靠稳定。
    2.1.3 安全需求本系统面向社会,因此对系统的安全性有较高的要求。对数据库要设置不同的用户权限,数据的操作需要用户身份验证,只有取得合法的身份才能进行操作,还应避免数据并发现象,防止数据库无法响应操作。
    2.2 系统可行性分析2.2.1 技术可行性现在,随着计算机技术和通信技术的发展,与网络相结合是以后的重要发展方向,特别是在网络大为普及,上网极为方便的网络信息时代,通过网络查询公交信息更是公交查询系统的发展方向。特别是在网络大为普及,上网极为方便的网络信息时代,通过网络查询公交信息更是查询系统的发展方向。基于Web的新型公交信息查询系统,数据信息更新更为准确、及时,用户可以利用计算机、手机等平台通过有限或无线的网络连接方式对系统进行访问,得到快捷的服务[5]。SSM(Spring + Springmvc +Mybatis)框架中Mybatis提供了多种常用的数据库应用程序,通过少量代码的编写,就能够实现数据库的访问[6]。系统采用MYSQL作为开发数据库。MYSQL是一种客户机/服务器结构的关系数据库管理系统[7]。在技术难度方面,有指导老师的指导、周围同学的热心帮助,加上对很多相关文献的参考,能够解决开发过程中所遇到的困难。因此,技术是可行的。
    2.2.2 经济可行性如今,随着计算机的大量普及,各种软件的开发成本越来越低,价格也越来越底。本系统也是这样,开发成本较低,只是需要一台配置一般的计算机,该系统运行时占计算机的资源也不多,但并不会因为开发成本低而造成系统功能性能的下降。相反,随着计算机技术的发展,各种实用软件的性能日渐提高。任务管理系统廉价的开发成本,却能够为用户带来相当大的实惠和方便。主要表现在:

    本系统可以说是一个拥有多种实用功能的系统,它集成了多种功能,具有较强的实用性和方便性
    本系统的运行可以大大提高查询信息的效率,减少不必要的人力和物力

    2.3 功能分析要设计一个良好的公交查询系统,就必须首先明确该应用环境对系统的要求。公交查询系统的应用背景为:方便市民搭乘公交车出行;手动(目前)、自动(将来)、及时更新查询数据。
    2.3.1 查询功能分析系统需要提供几种不同方式的查询手段,以实现灵活方便地管理整个系统。其中包括:

    线路查询:可以获得要查询公交所通过的所有站点
    站点查询:通过输入指定站点查询经过该站点的公交车
    公交换乘模块:主要体现那些不可直达需要转车的线路的所有换发

    2.3.2 数据的更新以及修改分析
    更新:系统允许管理员级别的用户对数据进行更新、修改并且存盘操作
    编辑:系统允许管理员级别的用户对数据进行编辑、删除的操作,保证数据的真实性与实时性

    系统采用采用B/S(Browser/Server)结构。整个系统最关键的就是数据库系统,一个强大的数据库可以支持完善一个优秀的软件设计,通过软件系统与数据库系统的连接来实现通过软件界面观察和处理操作数据[8]。通过软件系统与数据库系统的连接来实现通过软件界面观察和处理操作数据,如图2-1所示。

    系统采用三层结构,在客户端用户通过浏览器完成数据下载与模拟操作,浏览器端的表现逻辑通过JAVA网页完成[9]。而系统内部复杂的业务逻辑主要通过JavaBean的组件(Component)实现,JavaBean组件在WWW服务器上运行,通过JAVA返回到客户浏览器。通过表现逻辑与业务逻辑的分离,使网页内容简洁,系统的可维护性和可扩充性增强。在服务器端,系统使用JDBC中间件访问数据库,数据库服务器定义了本系统所需要的事务逻辑和数据逻辑。本系统使用JAVA技术作为表现手段,服务器采用Tomcat6.0作为JAVA引擎,系统业务逻辑由JavaBean 组件完成,使用JDBC 3.0 驱动程序访问数据库[10]。由于系统测试需要成熟的数据库支持,因此系统采用MySQL数据库作为数据库服务器。
    3 系统关键技术3.1 JAVA技术JAVA是由Sun微系统公司于1999年6月推出的一项技术,是基于JavaServlet以及整个Java体系的Web开发技术,利用这一技术可以建立先进、安全和跨平台的动态网页技术[11]。JAVA技术在多个方面加速了动态Web页面的开发。
    与微软公司的ASP技术相比,JAVA具有如下优点:

    开放的技术:JAVA技术基于平台和服务器的相互独立,技术支持来自广泛的、专门的、各种工具包,有服务器的组件和数据库产品开发商提供。相比之下,JAVA技术主要依赖MICROSOFT支持
    平台和服务器的独立性:JAVA编写的代码可运行在任何符合JAVA语法结构的环境中。这样JAVA就能够运行在多种WEB服务器上并支持来自多家开发商提供的各种工具包
    开放的开发过程,开放的源码:自1995年以来,SUN用开放过程方法同国际JAVA组织合作开发和修改JAVA技术和规范
    JAVA标记可扩充性:JAVA技术能够为开发者扩展JAVA标记,充分利用与XML兼容的标记技术强大的功能,大大减少对脚本语言的依赖
    JAVA跨平台的可重用性:JAVA组件(EJB,JavaBean或定制的JAVA标记)都是跨平台可重用的

    3.2 Java Bean技术JAVA作为一个很好的动态网站开发语言得到了越来越广泛的应用,在各类JAVA应用程序中,JAVA + JavaBean的组合成为了一种事实上最常见的JAVA程序的标准[12]。JavaBean是描述Java的软件组件模型,有点类似于Microsoft的COM组件概念。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生成新的应用程序。对于程序员来说,最好的一点就是JavaBean可以实现代码的重复利用,另外对于程序的易维护性等等也有很重大的意义。JavaBean通过Java虚拟机(Java Virtual Machine)可以得到正确的执行,具有平台无关性[13]。一个JavaBean有三个部分组成:
    属性(Property)
    Bean的属性就是对象的属性,但提供了属性读取和设置的接口支持。例如一个时钟Bean可以有时区和镇铃属性,日历Bean可以有年份和月份属性。每个属性通常遵守简单的方法命名规则。这样可以很方便的找出Bean提供的属性,然后查询属性值或改变属性值,对Bean进行操作。
    方法(Method)
    由于Bean本身是Java对象,调用这个对象的方法是与其交互作用的唯一途径。JavaBean严格遵守面向对象的类设计逻辑,不让外界访问其任何实例字段(没有Public字段)。这样,方法调用的是接触Bean的唯一途径。
    事件(Event)
    Bean与其他软件组件交流信息的主要方式是发送和接收事件。这与对象之间通过消息通信类似。JavaBean传统的应用在于可视化的领域,如AWT下的应用。自从JAVA诞生后,JavaBean更多的应用在非可视化领域,在服务器端应用方面表现出来了越来越强的生命力。利用非可视化JavaBean, 来封装事务逻辑、数据库操作等等,可以很好地实现业务逻辑和前台程序(如JAVA)的分离,使得系统具有更好的健壮性和灵活性。
    3.3 JDBC技术JDBC是Java的开发者——Sun的Java Soft公司制定的Java数据库连接Java Data Base Connectivity技术的简称,是为各种常用数据库提供无缝联接的技术[14]。JDBC在Web和Internet应用程序中的作用和ODBC在Windows系列平台应用程序中的作用类似。JDBC有一个非常独特的动态连接结构,它使得系统模块化。使用JDBC来完成对数据库的访问包括以下四个主要组件:Java的应用程序、JDBC驱动器管理器、驱动器和数据源。简单地说,JDBC能完成下列三件事:

    同一个数据库建立连接
    向数据库发送SQL语句
    处理数据库返回的结果

    JDBC是一种可用于执行SQL语句的Java API(Application Programming Interface,应用程序设计接口)。它由一些Java语言写的类、界面组成。JDBC给数据库应用开发人员、数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。
    通过使用JDBC,开发人员可以很方便地将SQL语句传送给几乎任何一种数据库。也就是说,开发人员可以不必写一个程序访问MySQL,写另一个程序访问Oracle,再写一个程序访问Microsoft的SQLServer。用JDBC写的程序能够自动地将SQL语句传送给相应的数据库管理系统(DBMS)。不但如此,使用Java编写的应用程序可以在任何支持Java的平台上运行,不必在不同的平台上编写不同的应用。Java和JDBC的结合可以让开发人员在开发数据库应用时真正实现“Write Once,Run Everywhere![15]”。
    Java 具有健壮、安全、易用等特性,而且支持自动网上下载,是一种很好的与数据库线连接而使用的编程语言。它所需要的是Java应用如何同各种各样的数据库连接,JDBC正是实现这种连接的关键。
    JDBC扩展了Java的能力,如使用Java和JDBC API就可以公布一个Web页,页中带有能访问远端数据库的Applet。或者企业可以通过JDBC让全部的职工(他们可以使用不同的操作系统,如Windows, UNIX)在Internet上连接到几个全球数据库上,而这几个全球数据库可以是不相同的。
    3.4 Springmvc技术Springmvc虽然是在Struts1的基础上发展起来的,但它实质上是以WebWork为核心的,其次它为传统的Struts1注入了WebWork的先进设计理念,是在Struts和WebWork的技术基础上进行合并后的一种全新框架。它全新的体系结构与Struts1的体系结构差别很大,Springmvc以WebWork为核心,在Springmvc中大量使用拦截器机制来处理用户请求,采用这种设计的优势表现在:业务逻辑控制器能够与Servlet API 完全分离,避免了Struts1与Servlet API的严重耦合。
    Springmvc对Struts1进行了巨大的改进,主要表现在以下几个方面:

    线程模型方面:Springmvc的Action是一个请求对应一个实例,而Struts1用一个Action的实例处理所有的请求,它的Action工作在单例模式,存在线程安全问题
    Action实现方面:Struts1要求统一扩展自Action类,而Springmvc中可以是一个普通的POJO(Plain Old Java Objects)。POJO指简单的Java对象,实际就是普通Java Beans
    Servlet依赖方面:Struts1的Action依赖于Servlet API,例如Action的execute方法的参数包括request和response对象,使得程序难以测试,而Springmvc的Action不再依赖于Servlet API,便于测试
    封装请求参数:在Struts1中强制使用ActionForm对象封装请求参数而在Springmvc中可以直接使用Action的属性或者选择使用JavaBean来封装要请求的参数
    在数据校验方面: Struts1中支持覆盖validate方法或者使用Validator框架,而在Springmvc中支持重写validate方法或者使用XWork的验证框架
    在Action执行控制方面:Struts1支持每一个模块对应一个请求处理,但是模块中的所有Action必须共享相同的生命周期,而Springmvc支持通过拦截器堆栈为每一个Action创建不同的生命周期

    3.5 Mybatis技术Mybatis是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得开发人员可以随意的使用对象编程思想来操纵数据库,最具特色的是它可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任[16]。
    Mybatis 核心接口有Session、SessionFactory、Transaction、Query、Criteria和Configuration等6个。通过这六个核心接口,不仅可以对持久化对象进行存取,还能够进行事物控制。以下是对这6个核心接口的介绍:

    Session接口:该接口负责执行持久化对象的CRUD(Create Read Update Delete)操作,需要特别指出的是Session对象时非线程安全的
    SessionFactory接口:该接口负责初始化Mybatis。它的职能是负责创建Session对象,并充当数据存储的代理。这里用到了工厂模式,需要注意的是SessionFactory 并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory 就够了,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory
    Transaction接口:该接口负责事物相关的操作。它是可选的,开发人员可以根据自己的需要来编写自己的底层事物处理代码
    Query和Criteria接口:Query和Criteria接口负责各种数据库查询。它们可以使用SQL语句和HQL语言两种方式,本系统采用SQL语句

    3.6 JavaScript技术JavaScript是适应动态网页制作的需要而诞生的一种脚本语言。它具有交互性,能够包含更多活跃的元素,如今已经广泛地应用于Internet网页制作[17]。JavaScript是由Netscape公司开发的一种脚本语言(Scripting Language)。在HTML基础上,使用JavaScript可以开发交互式网页。它的出现使得网页和用户之间实现了一种实时性的、动态的、交互性的关系,使网页包含更多活跃的元素和更精彩的内容。
    JavaScript可以嵌入到HTML文件中,它的出现增强了网页的互动性,JavaScript简化了HTML文段中的有规律重复的部分,缩短了网页加载时间。
    3.7 MVC设计模式MVC模式是目前广泛流行的设计模式,包括三类对象。它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器[18]。
    3.7.1 模型(Model)模型就是业务流程、状态的处理以及业务规则的制定,业务流程的处理过程对其它层来说就是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件。在MVC的三个部件中,模型处理的任务最多。模型的好处在于代码可以被多个视图重用,因此简化了代码。
    3.7.2 试图(View)视图代表用户交互界面,对于Web应用来说,可以概括为HTML界面。由于一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上业务流程的处理。业务流程的处理交予模型处理。
    3.7.3 控制器(Controller)控制器可以理解为从用户接收请求,将模型与视图匹配在一起,共同完成用户的请求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
    3.8 系统运行环境服务器端的最低配置是由建立站点所需要的软件来决定的,在最底配置的情况下,服务器的性能往往不进人意,现在硬件性能已经相当出色,而且价格也很便宜,因此通常应给服务器端配置高性能硬件。
    本系统的配置要求如下:

    处理器:1.5GHZ以上
    内存:512MB
    硬件空间:160GB

    题目主要采用的开发环境及技术:

    开发环境

    Windows XP Professional(以上版本)Internet Explorer6.0(以上版本)
    开发工具包:JDK Version1.6
    脚本语言:JavaScript
    数据库工具:MYSQL
    JAVA开发工具:MyEclipse8.5

    4 系统总体设计4.1 系统总体设计概述本系统设计使用了面向对象技术和模块化技术。面向对象技术是一种软件开发和程序设计技术,其所开发的程序是面向对象程序,直接描述客观世界的对象及其相互关系。对象是封装了数据和操作的程序块。所谓封装是为这个程序块建立显示的界面,其它对象只能向这个界面发消息,不能访问内部的私有数据和操作。因此,内部的数据和实现操作的算法若有改动,对其它程序对象没有任何影响。封装使程序局部化、易修改、好维护,但许多对象有相同的功能时免不了重复,所以面向对象技术有继承的机制。此外,由于对象自己操作自己的数据,对同一消息不同的对象均以自己的方式响应使得一种消息可有多种响应方式,这就是多态性。封装、继承、多态是面向对象程序的主要特征[19]。正是这些特征使程序安全、可靠、可重用、易维护。因而面向对象技术也成为当今计算机的新兴技术。
    4.2 系统功能结构图根据上述设计思想进行分析,确定了系统的基本框架,如图4-1所示。

    可以看出城市公交信息查询系统的相关功能,这为系统开发及功能模块化提供了清晰地设计思路与方向,基于系统需求分析,以下为该系统的详细功能:
    登录模块
    普通登陆成功后进入用户个人主界面并选择各种操作,否则会返回到登录界面重新进行登录。管理员登录成功进入管理员主界面选择相应操作。
    公交系统查询模块
    无需登录,进入系统首页根据自己需要进行公交查询。有包括车次查询、站点查询和查询公交换乘方案等。车次查询即为根据车次号查询车次经过的站点,该车次开收车时间,等基本信息;站点查询为经过该站点的车次信息;公交换乘方案查询即分别输入起始站点和目的站点并查询公交乘车方案。
    公告管理模块
    普通用户登录系统后,进入公告管理模块,用户可以提出自己的一些看法意见和对本公交系统的建议,能查看以前的留言。除此之外系统还提供事物认领模块。
    用户个人信息管理模块
    用户登录成功后即可进入到用户的个人主界面,在个人主界面中,用户可以查看个人详细信息,包括用户名账号,保护邮箱等信息,并可以自行修改密码等个人信息,最后注销登录返回到系统登录界面。
    站点信息管理模块
    管理员登录系统后进入相应管理员主界面,在管理员主界面中,可对公交站点信息进行添加和删除,实时更新公交变动信息。
    车次信息管理模块
    管理员登录系统后进入相应管理主界面,在管理员主界面中,可对公交车次信息进行添加和删除,实时更新公交变动信息。
    4.3 系统流程图4.3.1 系统操作流程系统操作流程图详细阐述了该系统的整体操作流程,如图4-2所示。

    用户进行登录,选择登录身份是普通用户或者管理员,如果用户名和密码正确则进入到相应的用户个人主界面,否则返回登录界面重新进行登录。在用户个人主界面,用户可以进行各自需要的操作。若用户为普通用户,则可以进行查询公交信息,留言,注销和更改个人信息等操作;用户为管理员,可添加删除公交信息。最后,用户操作完毕,即可退出本系统,整个系统操作流程到此结束。
    4.3.2 数据增加流程添加信息时,编号字段由系统自动生成,且不能修改,其他信息由用户输入,之后对数据进行合法判断, 合法则写入保存至数据库,不合法则重新输入数据。数据增加流程图如图4-3所示。

    4.3.3 数据修改流程在修改信息时,先选中一条待修改的记录,然后直接输入数据,判断合法性,合法则保存至数据库,不合法重新输入。数据修改流程图如图4-4所示。

    4.3.4 数据删除流程当用户选定一条记录时,单击删除按钮,会提示用户是否确定删除,然后删除数据库相关内容。数据删除流程图如图4-5所示。

    4.4 数据流分析管理员登录系统后,可进行车次管理、站点管理、线路管理、删除用户等操作。普通用户注册登录后,进入查询界面通过系统数据库,可进行公交信息查询、留言版留言。如图4-6所示。

    4.5 业务流分析城市公交信息查询系统工作流程为:输入首页网址进入首页界面,游客只能查询公交信息,游客可以通过注册成为普通用户。普通用户除了具备游客权限外还可以管理个人资料以及发布信息。管理员拥有最高权限,可以对系统信息增删改查,以及对普通管理员的管理,系统业务流程图如图4-7所示。

    5 系统详细设计5.1 后台数据库设计数据库技术是信息资源管理最有效的手段。数据库设计是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,有效存储数据,满足用户信息要求和处理要求[20]。
    毕业设计城市公交信息查询系统需要对大量的数据完成搜集、分析、整理、存储、交换等工作,这就需要设计一个较为强大的数据库来对这些数据进行管理。在这里本着实用、方便、安全、可靠的原则,采用MySQL作为本系统数据库的支持。本系统主要数据表有:普通用户表、管理员表、车次信息表、站点信息表、中间站点关联表、留言信息表等。
    为了满足系统存储数据需要,方便进行插入,更新,统计分析等操作,数据一共设计为两个部分,第一部分为满足插入,更新,删除较多的数据存储。第二部分为满足查询和统计分析。
    管理员信息表:该表主要保存管理员信息,包含管理员编号、管理员姓名、账户名、密码。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    管理员编号(主键)


    adminName
    varchar
    50

    管理员姓名


    loginName
    varchar
    50

    账户名


    passWord
    Varchar
    50

    密码



    公交线路信息表:该表主要保存公交线路信息,包含线路编号、正向途经站点、反向途经站点、公交线路名称、始发时间与末班时间。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    线路编号(主键)


    content
    varchar
    255

    正向途径站点


    content2
    varchar
    255

    反向途径站点


    name
    varchar
    50

    线路名称


    title
    varchar
    255

    始末发车时间



    失物信息表:该表主要保存用户发布的信息,包括启示编号、启示内容、发布时间、启示标题、启示类别。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    启示编号(主键)


    contents
    varchar
    20

    启示内容


    inputTime
    varchar
    255

    发布时间


    title
    varchar
    255

    启示标题


    type
    int


    启示类型



    找回密码表:该表主要保存找回密码所需信息,包括编号、问题答案内容、问题类型。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    编号(主键)


    content
    varchar
    255

    答案内容


    title
    int


    问题类型



    公告表:该表主要保存发布的公告信息,包括公告编号、公告内容、发布时间、公告标题。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    公告编号(主键)


    contents
    varchar
    20

    公告内容


    inputTime
    varchar
    255

    发布时间


    title
    varchar
    255

    公告标题



    用户信息表:该表主要保存用户注册信息,包括编号、用户地址、用户邮箱、用户姓名、登录密码、用户名、用户电话、附加信息。



    列名
    数据类型
    字段大小
    可否为空
    说明




    id
    int


    用户编号(主键)


    address
    varchar
    255

    用户地址


    contents
    varchar
    255

    附加信息


    email
    varchar
    50

    邮箱


    loginName
    varchar
    255

    用户名


    passWord
    varchar
    50

    密码


    userName
    varchar
    50

    用户姓名


    tel
    varchar
    20

    用户电话



    5.2 系统模块设计5.2.1 注册与登录用户注册界面,要求用户必须输入姓名、用户名、密码、联系电话以及邮箱等必填信息以及联系地址等选填信息。当信息填完后点击保存按钮完成注册工作,进入用户登录界面,点击返回按钮返回到首页,如图5-1所示。

    登录界面,分为普通用户登录和管理员登录。普通用户或系统管理员在用户对应的文本框中输入用户名,在密码对应的文本框中输入密码,然后选择相应的用户类型。如果用户名和密码同时与数据库中的用户名和密码相对应,点击确定后进入系统主界面,如果输入的信息不正确,则给出提示。
    用户要登录本系统需要提供用户名和密码,在这里就是要检验用户是否满足输入的要求,即检验用户名和密码文本框是否为空,若为空,则提示用户输入用户名和密码。检验用户名是否存在或密码是否正确,即是否存在用户输入的用户名,并且密码是否正确,如图5-2所示。

    输出:登录成功,进入用户的系统使用资源页面,不成功则显示错误信息页面,管理界面如图5-3所示。

    5.2.2 公交信息查询用户根据自己的实际情况选择按站点查询、按线路查询也可以根据其实位置和终点位置进行查询,在相应的位置进行输入,然后提交给系统,系统会自动查找线路表所有相匹配的信息,并返回给用户要查询的公交信息,如图5-4所示。

    查询公交信息数据库相关操作代码:
    public String zz() throws Exception { String cd = request.getParameter("textfield3").trim(); String zd = request.getParameter("textfield4").trim(); ArrayList al = (ArrayList) indexDao.checkCDZD(cd, zd); System.out.println("al.size=" + al.size()); HttpSession session = request.getSession(); if (al.size() > 0 && al != null) { //如果有直达的车辆(也就是不用转车) session.setAttribute("zzMore", al); //直达的车辆的信息 session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 return "zzone"; } else { ArrayList arrMiddleAll = indexDao.checkMiddle(cd, zd); if (arrMiddleAll.size() > 0 && arrMiddleAll != null) {//查询一个中转站可以到达目的地的方法 session.setAttribute("zzMoreMiddleAll", arrMiddleAll); //得到一个中转站可以到达目的地的所有信息 session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 System.out.println("=======================zztwo"); return "zztwo"; } else { //也就是要倒两次以上车 ArrayList arrTwoMiddleAll=indexDao.checkTwoMiddle(cd,zd); if (arrTwoMiddleAll.size() > 0 && arrTwoMiddleAll != null) { session.setAttribute("zzMorecd", cd); //您输入的起点名 session.setAttribute("zzMorezd", zd); //您输入的终点名 session.setAttribute("zzMoreTwoMiddleAll", arrTwoMiddleAll); //得到二个中转站可以到达目的地的所有信息 System.out.println("=======================zzthree"); return "zzthree"; }else{ System.out.println("======================= - zzerror - "); return "zzerror";}
    5.2.3 寻物启事和失物招领普通用户进入该模块可以发布寻物启示以及失物招领信息,如图5-5所示。

    数据库操作相关代码:
    public String noteSSMow() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 NotesEntity pe = indexDao.noteSSMow(request); request.setAttribute("NotesEntity", pe); return "noteSSMow"; } // 公告管理:修改信息 public String notesUpdList() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 List list = indexDao.notesList(request); request.setAttribute("notesUpdList", list); return "notesUpdList"; } // 公告管理:修改单个信息 public String notesUpd() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 NotesEntity notesEntity = indexDao.noteSSMow(request); request.setAttribute("getNotesView", notesEntity); return "notesUpd"; } // 公告管理:修改保存到数据库 public String notesUpdDB() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 indexDao.notesUpdDB(request); return "notesUpdList"; } // 公告管理:删除信息 public String notesDelList() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 List list = indexDao.notesList(request); request.setAttribute("notesDelList", list); return "notesDelList"; } // 公告管理:删除单个信息 public String notesDel() throws Exception { if (request.getSession().getAttribute("loginmessage") == null) return "noLogin";//判断是否登录 indexDao.notesDel(Long.valueOf(request.getParameter("id"))); return "notesDelList"; }
    5.2.4 用户个人信息管理普通用户登录成功后可以进入到个人主界面,该界面实现的功能为:查看个人详细信息、修改个人信息,如图5-6所示。

    5.2.5 公交线路管理此模块需要系统管理员权限,在管理员主界面中,可对公交线路进行添加、删除以及对公交变动信息实时更新。如图5-7所示。

    5.3 连接池配置在城市公交信息查询系统中采用数据库连接处技术提高访问数据库的效率。在数据源中建立了多个数据库连接,这些连接保存在数据库连接池中。Java程序访问数据库时,只需要从连接池中取出空闲的数据库连接,程序访问数据库完毕之后,再将数据库连接池放回连接池,具体实现是在applicationContext.xml中加入:
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://127.0.0.1:3306/buscity</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value></value> </property></bean>
    5.4 SSM框架的整合为实现Spring 整合Mybatis和Springmvc,需要配置applicationContext.xml文件,配置完成后系统就可以通过Springmvc的action直接调用了。Mybatis访问数据库的操作都在Spring中实现了,而Spring的调用是在Springmvc的action中实现。SSM框架整合具体如下:
    首先在web.xml文件中添加Spring配置、新增一个监听器(Linstener)。监听器的作用是启动 Web 容器时,自动装配 ApplicationContext 的配置信息。因为它实现了ServletContextListener这个接口,在Web.xml完成这个监听器的配置后,启动容器时,就会默认执行它实现它的方法。实现代码如下:
    <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/applicationContext.xml </param-value> </context-param><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
    配置数据源、SessionFactory。连接池的数据源和分配 sessionFactory 对象是通过Spring 管理的。Spring 通过建立一个LocalSessionFactory对象来完成对Mybatis 的配置,这是一个工厂 bean 的实现。然后就可以通过继承 Spring 为 我们提供MybatisDaoSupport(MybatisDao层都需要继承extends它)来对数据库的 DAO 模式管理。代码如下:
    <!-- 配置数据源 DBCP 提供的BasicDataSource --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://127.0.0.1:3306/buscity</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value></value> </property> </bean> <!-- Mybatis配置 --> <bean id="sessionFactory" class="org.springframework.orm.Mybatis3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="MybatisProperties"> <props> <prop key="Mybatis.dialect">org.Mybatis.dialect.MySQL5Dialect</prop> <prop key="Mybatis.show_sql">true</prop> <prop key="Mybatis.format_sql">true</prop> <prop key="Mybatis.hbm2ddl.auto">update</prop> </props> </property> <property name="packagesToScan" value="com.Mybatis" /> </bean>
    将sessionFactory 对象作为属性注入到这个服务类中去。代码如下:
    <bean id="indexDao" class="com.struts.dao.IndexDao"> <property name="sessionFactory" ref="sessionFactory"></property></bean>
    装配事务管理器,使用annotation定义事物、自动注册bean。代码如下:
    <!-- 事务管理器配置,单数据源事务 --> <bean id="transactionManager" class="org.springframework.orm.Mybatis3.MybatisTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> <context:annotation-config /> <!-- 使用annotation 自动注册bean,并保证@Required,@Autowired的属性被注入 --> <context:component-scan base-package="com.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan>
    配置struts.xml的Action。
    6 系统调试与测试6.1 程序调试在设计系统的过程中,存在一些错误是必然的。对于语句的语法错误,在程序运行时自动提示,并请求立即纠正,因此,这类错误比较容易发现和纠正。但另一类错误是在程序执行时由于不正确的操作或对某些数据的计算公式的逻辑错误导致的错误结果。这类错误隐蔽性强,有时会出现,有时又不出现,因此,对这一类动态发生的错误的排查是耗时费力的。
    6.2 程序的测试6.2.1 测试的重要性及目的测试的重要性
    软件的测试在软件生命周期中占据重要的地位,在传统的瀑布模型中,软件测试学仅处于运行维护阶段之前,是软件产品交付用户使用之前保证软件质量的重要手段。近来,软件工程界趋向于一种新的观点,即认为软件生命周期每一阶段中都应包含测试,从而检验本阶段的成果是否接近预期的目标,尽可能早的发现错误并加以修正,如果不在早期阶段进行测试,错误的延时扩散常常会导致最后成品测试的巨大困难。
    测试是所有工程学科的基本组成单元,是软件开发的重要部分。自有程序设计的那天起测试就一直伴随着。统计表明,在典型的软件开发项目中,软件测试工作量往往占软件开发总工作量的40%以上。而在软件开发的总成本中,用在测试上的开销要占30%到50%。如果把维护阶段也考虑在内,讨论整个软件生存期时,测试的成本比例也许会有所降低,但实际上维护工作相当于二次开发,乃至多次开发,其中必定还包含有许多测试工作。
    在实践中,软件测试的困难常常使人望而却步或敷衍了事,这是由于对测试仍然存在一些不正确的看法和错误的态度,这包括:
    认为测试工作不如设计和编码那样容易取得进展难以给测试人员某种成就感;
    以发现软件错误为目标的测试是非建设性的,甚至是破坏性的,测试中发现错位是对责任者工作的一种否定;
    测试工作枯燥无味,不能引起人们的兴趣;
    测试工作是艰苦而细致的工作;
    对自己编写的程序盲目自信,在发现错误后,顾虑别人对自己的开发能力的看法。
    这些观点对软件测试工作是极为不利的,必须澄清认识、端正态度,才可能提高软件产品的质量。
    测试的目的
    如果测试的目的是为了尽可能多地找出错误,那么测试就应该直接针对软件比较复杂的部分或是以前出错比较多的位置。
    软件测试是为了发现错误而执行程序的过程,测试是为了证明程序有错,而不是证明程序无错误,一个好的测试用例是在于它能发现至今未发现的错误,一个成功的测试是发现了至今未发现的错误的测试。
    这种观点可以提醒人们测试要以查找错误为中心,而不是为了演示软件的正确功能。但是仅凭字面意思理解这一观点可能会产生误导,认为发现错误是软件测试的唯一目,查找不出错误的测试就是没有价值的,事实并非如此。
    首先,测试并不仅仅是为了要找出错误。通过分析错误产生的原因和错误的分布特征,可以帮助项目管理者发现当前所采用的软件过程的缺陷,以便改进。同时,这种分析也能帮助我们设计出有针对性地检测方法,改善测试的有效性。其次,没有发现错误的测试也是有价值的,完整的测试是评定测试质量的一种方法。
    6.2.2 测试的步骤与内容与开发过程类似,测试过程也必须分步骤进行,每个步骤在逻辑上是前一个步骤的继续。大型软件系统通常由若干个子系统组成,每个子系统又由若干个模块组成。因此,大型软件系统的测试基本上由下述几个步骤组成:

    模块测试:在这个测试步骤中所发现的往往是编码和详细设计的错误
    系统测试:在这个测试步骤中发现的往往是软件设计中的错误,也可能发现需求说明中的错误
    验收测试: 在这个测试步骤中发现的往往是系统需求说明书中的错误

    测试的主要内容:
    为了保证测试的质量,将测试过程分成几个阶段,即:代码审查、单元测试、集成测试、确认测试和系统测试[21]。
    单元测试
    单元测试集中在检查软件设计的最小单位—模块上,通过测试发现实现该模块的实际功能与定义该模块的功能说明不符合的情况,以及编码的错误。
    集成测试
    集成测试是将模块按照设计要求组装起来同时进行测试,主要目标是发现与接口有关的问题。如一个模块与另一个模块可能有由于疏忽的问题而造成有害影响;把子功能组合起来可能不产生预期的主功能;个别看起来是可以接受的误差可能积累到不能接受的程度;全程数据结构可能有错误等。
    确认测试
    确认测试的目的是向未来的用户表明系统能够像预定要求那样工作。经集成测试后,已经按照设计把所有的模块组装成一个完整的软件系统,接口错误也已经基本排除了,接着就应该进一步验证软件的有效性,这就是确认测试的任务,即软件的功能和性能如同用户合理期待的那样。
    系统测试
    软件开发完成以后,最终还要与系统中其他部分配套运行,进行系统测试。包括恢复测试、安全测试、强度测试和性能测试等。
    6.2.3 单独对系统的测试单独对系统的测试主要从以下几个方面入手:

    功能测试:测试是否满足开发要求,是否提供设计所描述的功能,是否用户的需求都得到满足。功能测试是系统测试最常用和必须的测试,通常还会以正式的软件说明书为测试标准
    强度测试及性能测试:测试系统能力最高实际限度,即软件在一些超负荷情况下功能实现的情况
    安全测试:验证安装在系统内的保护机构确实能够对系统进行保护,使之不受各种非常的干扰。针对本系统主要是对权限系统的测试和对无效数据、错数据、和非法数据干扰的能力的测试

    6.3 测试分析本系统主要实现了公交查询功能,并附有用户留言的功能,同时具有管理员后台维护公交信息等功能。但由于本人能力不足以及所学知识的缺乏,再加上时间有限,该系统还不够健全。该系统虽然基本实现了所要求的功能,但是还存在很多不足,有待于进一步的完善和改进。经过上述的测试过程对软件进行测试后,软件基本满足开发的要求,测试宣告结束。
    结束语本文通过本系统设计与开发感触颇深,总结如下:
    学习一门新技术,最重要的是实践,只有多动手才能尽快掌握它。一个系统的开发,经验是最重要的,经验不足,就难免会有许多考虑不周之处。要想吸引更多的用户,系统的界面必须要美观、有特色、友好,功能要健全。不过由于经验不足,我设计的图形界面比较简单。只是对基本功能进行了开发。
    本次开发,我参考了很多本系统的例子,吸取了一些别的本系统的长处,对自己的毕业设计进行了完善,但是还有很多的不足之处,有待以后进一步学习。实践证明,本系统有着很好的发展前景,经测试运行。本文所制作的系统界面友好、使用灵活、操作简单、功能齐全、表现方式独特,已基本具备了成熟的技术理论。
    由于时间仓促,本次设计由我完成本系统的制作,对我这样一个JAVA新手而言所制作的模块还有不完善的地方。数据库的设计也比较简单。还有很多毕业设计中用到JAVA语言的知识也不够全面,还有很多地方不能够作到完全的理解和掌握。通过这次毕业论文的设计制作使本人受益匪浅。由于是毕业设计是独立完成的,因此在毕业设计的过程遇到了很多的困难,我求教了不少老师和同学,在这个过程中让我体会到了,一个团队的重要性。
    参考文献[1] BruceEckel. JAVA编程思想[M].北京:机械工业出版社,2003
    [2] 赛奎春. JAVA工程应用与项目实践[M]. 北京:机械工业出版社, 2002
    [3] 陈守学、刘电霆.中小城市公交线路查询系统设计方法研究[M]. 桂林航天工业高等专科学校学报,2007.12
    [4] 刘晓妍. 基于J2EE公交查询系统的研究[D].上海:华东师范大学软件学院,2010.4
    [5] 吴永军、蔡永香、郭庆胜. 城市公交查询系统的设计与实现[D].武汉:武汉大学资源与环境科学学院,2006.5
    [6] 周继芳. 基于J2EE的公交线路查询系统的设计与实现[D].西昌:西昌卫星发射基地,2009.5
    [7] 孙一林,彭波. JAVA数据库编程实例[M]. 北京:清华大学出版社,2002
    [8] 萨师煊,王珊. 数据库系统概论[D].高等教育出版社,2002
    [9] 耿祥义,张跃平. JAVA实用教程[M]. 北京:清华大学出版社,2003
    [10] 蔡剑,景楠. Java Web应用开发J2EE和Tomcat[M]. 北京:清华大学出版社, 2005
    [11] Brown等. JAVA编程指南(第二版)[M]. 北京:电子工业出版社 ,2003
    [12] 沈雄. 基于SSM的分布式公交运营管理系统设计与实现[EB/OL].http://wenku.baidu.com/view/c49946293169a4517723a3cc.html,2011-05-09/2012-03-28
    [13] JAVA 程序设计论坛http://techbbs.zol.com.cn/subcate_list_8.html,2010-11-04/2012-03-29
    [14] 徐国志,汪孝宜等. SQL Server数据库开发实例精粹[M].北京:电子工业出版社,2006
    [15] 岳昆、王晓玲、周傲英. Web服务核心支撑技术[J]:研究综述.软件学报,2004,18(1):16-20
    [16] 冯锐. SSM权威指南[M].北京:中国电力出版社,2003
    [17] 月影. JavaScript王者归来[M].北京:清华大学出版社,2008
    [18] 孙卫琴. 精通Struts:基于MVC的Java Web设计与开发[M]. 北京:电子工业出版社,2004
    [19] 张存保等. 基于WebGIs的城市公交问路系统.武汉理工大学学报,2004,23(1):20-24
    [20] Paul Simith. Database Appliction[J]. 北京:电子工业出版社,2001
    [21] 王水,张晓民.软件工程素质导论[M].河南:河南科学技术出版社,2011
    3 评论 55 下载 2019-05-14 11:17:31 下载需要16点积分
  • 基于JAVA和Oracle数据库实现的项目信息管理系统

    1 需求分析1.1 背景项目管理系统,是反映公司员工资料,项目负责部门和项目进度,设备采购软件系统,是管理项目的有效工具。
    面向用户:对项目进度跟踪,公司人员信息管理和设备管理的公司。只能由公司内部查看数据库中的数据。要求使用本系统的用户管理系统的使用有所了解,知道基本的操作和使用过程的注意事项。
    1.2 系统目标系统对外部封闭,不允许外部人员访问公司项目管理系统中的数据库。能够安全的访问系统独立的数据库。程序实现数据库数据的直观显示,保证数据库的能够为公司提供较为方便和基础的项目管理服务,能够为公司管理层提供监督渠道。
    数据分析:员工的基本信息,部门的基本信息,项目的基本信息,设备基本信息
    1.3 功能分析项目管理系统应该能够提供以下功能:管理员登陆、员工信息管理、部门信息管理、项目信息管理、设备信息管理。

    管理员登录:项目管理系统采用Oracle数据库连接的服务名,用户名和口令(密码)验证模式,进入项目管理系统前项目管理员必须在登陆界面输入验证信息方可进入项目管理系统的主界面进行相应的操作
    学生信息管理:学生信息管理包含五个模块:学生信息的浏览、添加、删除、查询、修改
    部门信息管理:包含一个模块:部门经理信息查询
    项目信息管理:包含两个模块:根据项目经理的姓名查询项目的完成情况、查询某个项目的设备购买情况
    设备信息管理:包含三个模块:设备费用查询、设备供应商查询、添加设备

    1.4 性能需求分析
    系统易操作性:项目管理系统应该做到操作简单,界面友好,使得用户可以快速上手使用,不受到专业知识的限制
    系统可维护性:由于系统涉及的信息比较多,数据库中的数据需定期修改,系统可利用的空间及性能也随之下降,为了使系统更好地运转,用户可以对系统数据及一些简单的功能进行独立的维护及调整

    2 概念设计2.1 概念模型(E-R图)
    2.2 数据字典数据字典包括的项目有数据项、数据结构、数据流、数据存储、加工逻辑和外部实体。可使用一些符号来表示数据结构、数据流和数据存储的组成。
    2.2.1 员工表


    数据元素
    数据类型
    数据长度
    数据描述




    w_id
    VARCHAR2
    4
    员工编号


    w_name
    VARCHAR2
    16
    员工姓名


    sex
    CHAR
    2
    员工性别


    age
    CHAR
    20
    员工年龄


    contract_date
    DATE

    合同日期


    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    post
    VARCHAR2
    6
    员工职务



    2.2.2 部门表


    数据元素
    数据类型
    数据长度
    数据描述




    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    m_id
    VARCHAR2
    4
    部门经理编号


    m_name
    VARCHAR2
    8
    部门经理姓名


    w_num
    NUMBER

    员工人数



    2.2.3 项目表


    数据元素
    数据类型
    数据长度
    数据描述




    p_id
    VARCHAR2
    4
    项目编号


    p_name
    VARCHAR2
    16
    项目名称


    d_id
    VARCHAR2
    4
    部门名称


    w_id
    VARCHAR2
    4
    项目经理编号


    fund
    FLOAT
    126
    项目经费


    type
    VARCHAR2
    4
    项目类型


    signing_time
    DATE

    签订时间


    complete_time
    DATE

    应完成时间


    check_time
    DATE

    验收时间


    remarks
    VARCHAR2
    8
    备注



    2.2.4 设备表


    数据元素
    数据类型
    数据长度
    数据描述




    e_id
    VARCHAR2
    4
    设备编号


    e_name
    VARCHAR2
    12
    设备名称


    fee
    FLOAT

    设备费用


    supplier
    VARCHAR2
    12
    供应商


    p_id
    VARCHAR2
    4
    项目编号


    remarks
    VARCHAR2
    8
    备注



    2.3 数据流图数据流图(Data Flow Diagram)是一种图形化技术,它描绘信息流和数据从输入到输出的过程中所经受的变换。根据数据流图,可以分析出程序所需的模块和模块之间的调用关系。
    如下图所示,在项目管理系统,在用户界面捕捉用户的操作,接受事务后数据流流向不同的模块。

    3 逻辑结构设计3.1 关系描述
    员工与部门的关系:n:1一个员工只能属于一个部门,一个部门可以有多个员工
    部门与项目的关系:1:n一个部门可以负责多个项目,一个项目只能由一个部门负责
    员工与项目的关系:m:n一个员工可以实现多个项目,一个项目可以由多个员工实现
    员工与设备的关系:1:n一个员工可以采购多个设备,一个设备只能由一个员工采购
    项目与设备的关系:1:n一个项目可以使用多个设备,一个设备只能由一个部门使用

    3.2 系统结构图
    3.3 流程图
    4 系统实施4.1 建表语句/*==============================================================*//* Table: "worker" *//*==============================================================*/create table "worker" ( "w_id" VARCHAR2(4) not null, "w_name" VARCHAR2(8), "sex" CHAR(2), "age" CHAR(2), "contract_date" DATE, "post" VARCHAR2(8), "d_id" VARCHAR2(4), constraint PK_WORKER primary key ("w_id"));/*==============================================================*//* Table: "department" *//*==============================================================*/create table "department" ( "d_id" VARCHAR2(4) not null, "d_name" VARCHAR2(16), "m_id" VARCHAR2(4), constraint PK_DEPARTMENT primary key ("d_id"));/*==============================================================*//* Table: "project" *//*==============================================================*/create table "project" ( "p_id" VARCHAR2(4) not null, "p_name" VARCHAR2(16), "fund" FLOAT(126), "type" VARCHAR2(4), "signing_time" DATE, "complete_time" DATE, "check_time" DATE, "m_id" VARCHAR2(4), "remarks" VARCHAR2(256), constraint PK_PROJECT primary key ("p_id"));/*==============================================================*//* Table: "equipment" *//*==============================================================*/create table "equipment" ( "e_id" VARCHAR2(4) not null, "e_name" VARCHAR2(16), "fee" FLOAT(126), "supplier" VARCHAR2(16), "p_id" VARCHAR2(4), "remarks" VARCHAR2(256), constraint PK_EQUIPMENT primary key ("e_id"));
    4.2 插入数据4.2.1 worker表INSERT INTO "worker" VALUES ('1008', '马化腾', '男', '29', TO_DATE('20171229201245', 'YYYYMMDDHH24MISS'), '经理', '11');INSERT INTO "worker" VALUES ('1011', '雷军', '男', '21', TO_DATE('20171220085418', 'YYYYMMDDHH24MISS'), '职员', '11');INSERT INTO "worker" VALUES ('1006', '司马懿', '男', '56', TO_DATE('20171229202106', 'YYYYMMDDHH24MISS'), '职员', '13');INSERT INTO "worker" VALUES ('1005', '王超', '男', '38', TO_DATE('20171018161809', 'YYYYMMDDHH24MISS'), '经理', '14');INSERT INTO "worker" VALUES ('1001', '张三', '男', '26', TO_DATE('20171026143550', 'YYYYMMDDHH24MISS'), '职员', '11');INSERT INTO "worker" VALUES ('1002', '李四', '男', '25', TO_DATE('20171026143733', 'YYYYMMDDHH24MISS'), '职员', '12');INSERT INTO "worker" VALUES ('1003', '李玲', '女', '27', TO_DATE('20171026144030', 'YYYYMMDDHH24MISS'), '经理', '13');INSERT INTO "worker" VALUES ('1004', '王五', '男', '25', TO_DATE('20171026144412', 'YYYYMMDDHH24MISS'), '经理', '14');
    4.2.2 department表INSERT INTO "department" VALUES ('11', '采购部', '1008');INSERT INTO "department" VALUES ('12', '销售部', '1002');INSERT INTO "department" VALUES ('13', '策划部', '1003');INSERT INTO "department" VALUES ('14', '人事部', '1004');
    4.2.3 project表INSERT INTO "project" VALUES ('004', '跨海大桥', 300000000, '桥梁', TO_DATE('20160226150155', 'YYYYMMDDHH24MISS'), TO_DATE('20170326150206', 'YYYYMMDDHH24MISS'), TO_DATE('20171001150213', 'YYYYMMDDHH24MISS'), '1004', NULL);INSERT INTO "project" VALUES ('001', '京沪高速', 300000, '建筑', TO_DATE('20170901145036', 'YYYYMMDDHH24MISS'), TO_DATE('20171026145042', 'YYYYMMDDHH24MISS'), TO_DATE('20171027145048', 'YYYYMMDDHH24MISS'), '1005', NULL);INSERT INTO "project" VALUES ('002', '青藏铁路', 1500000, '建筑', TO_DATE('20170701145439', 'YYYYMMDDHH24MISS'), TO_DATE('20170901145459', 'YYYYMMDDHH24MISS'), TO_DATE('20171026145505', 'YYYYMMDDHH24MISS'), '1008', NULL);INSERT INTO "project" VALUES ('003', '鸟巢', 30000000, '工程', TO_DATE('20170801145900', 'YYYYMMDDHH24MISS'), TO_DATE('20170901145906', 'YYYYMMDDHH24MISS'), TO_DATE('20171004145911', 'YYYYMMDDHH24MISS'), '1003', NULL);
    4.2.4 equipment表INSERT INTO "equipment" VALUES ('101', '挖掘机', 100000, '徐工', '001', NULL);INSERT INTO "equipment" VALUES ('102', '玻璃', 10000, '通用', '003', NULL);INSERT INTO "equipment" VALUES ('103', '铝合金', 20000, '上汽', '002', NULL);INSERT INTO "equipment" VALUES ('104', '液晶', 50000, '京东方', '004', NULL);INSERT INTO "equipment" VALUES ('105', '台式机', 100000, '清华同方', '003', '办公专用');INSERT INTO "equipment" VALUES ('108', 'A4纸', 200, '华润', '003', NULL);INSERT INTO "equipment" VALUES ('109', '键鼠套装', 1000, '达尔优', '003', NULL);
    5 运行维护转储:定期进行静态转储,动态转储,海量转储。
    数据库中可能发生各种各样的故障,大致可以分为以下几类:

    事务故障的恢复策略主要是:反向扫描日志文件,查找该事物的更新操作;对该事物的更新操作执行逆操作;继续反向扫描日志文件,查找该事物的其他更新操作,并做同样处理;如此处理下去,直至读到此事物的开始标记,事物故障恢复就完成了。
    系统故障的恢复策略主要是:正向扫描日志文件,找出在故障发生前已经提交的事务,将其事务标识记入重做队列。同时找出故障发生时尚未完成的事务,将其事务标识记入撤消队列;对撤消队列的各个事务进行撤消处理;对重做队列的各个事务进行重做处理。
    介质故障的恢复策略主要是:装入最新的数据库后备副本,使数据库恢复到最近一次转储的一致性状态。装入相应的日志文件副本,重做已完成的事物。

    6 用户手册6.1 安装及配置本系统基于Java开发,要使用本系统在本机上必须安装有Java开发环境,数据库使用Oracle。
    6.2 使用方法登录界面

    主界面

    6.3 基本操作运行程序之后首先进入登陆界面,在登录界面中输入服务名,用户名(数据库的用户名,比如SCOTT),密码。例如我的数据库的服务名是orcl,用户名是CHAN。经过正确的连接即可进入到程序的主界面。

    如下图所示,应用程序界面包括 “切换卡 (用来切换页面)”,“显示区 (显示基本信息)”,“查询区 (用来进行数据查询)”,“控制按钮 (用来进行基本操作)”。

    员工页面,点击打开表格可以查看所有员工的基本信息,关闭表格可以清空页面上的表格显示。

    点击添加信息可以添加某个员工的信息:

    点击修改可以修改某个员工的信息(注意:员工的编号在数据库中是唯一的,被修改的员工的编号在数据库中必须存在)

    点击删除信息可以删除某个员工的信息(同样编号必须存在)

    在部门页面可以通过部门名称查询部门经理的信息:


    在项目页面

    点击查询完成情况可以查询某项目经理(姓名)完成合同的情况

    点击查询设备采购可以某个项目设备采购情况

    在设备页面有一下几个查询:

    7 附录对客户端进行响应的逻辑处理函数大部分通过在客户端中调用数据库的存储过程完成。
    客户端程序逻辑处理的核心代码如下(界面代码在提交的工程中):
    import com.connectdb.ConnectDB;import oracle.jdbc.OracleTypes;import java.sql.*;import java.text.SimpleDateFormat;import java.util.Vector;import java.util.Date;public class ProjectFunction { /** * 添加员工信息 * @param */ public static boolean addWorker(String wId,String dId,String wName,String sex,String age,String date,String dName,String post){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); System.out.println(wId+dId+wName+sex+age+date+dName+post); try { CallableStatement c = conn.prepareCall("{call p_addworker(?,?,?,?,?,?,?)}"); c.setString(1,wId); c.setString(2,wName); c.setString(3,sex); c.setString(4,age); System.out.println("传入的时间是 "+date); c.setString(5,date); c.setString(6,post); c.setString(7,dId); //c.setDate(6,Date.valueOf(date)); //执行Oracle存储过程 c.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return true; } /** * 删除员工信息 * @param */ public static void deleteWorker(String wId){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); try { CallableStatement c = conn.prepareCall("{call p_delworker(?)}"); c.setString(1,wId); //执行Oracle存储过程 c.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } } /** * 查询员工信息 * @param */ public static Vector<Vector<String>> queryWorker(String sql){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); ResultSet rs=null; Vector<Vector<String>> list=new Vector<Vector<String>>(); int i=0; try { Statement st = conn.createStatement(); rs = st.executeQuery(sql); System.out.println("执行查询"); // 判断结果集是否有效 while(rs.next()){ // 数据库存在,返回结果集 System.out.println(rs.getString("w_id")); System.out.println(rs.getString("w_name")); System.out.println(rs.getString("sex")); System.out.println(rs.getString("post")); Vector<String> result=new Vector<String>(); result.add(rs.getString("w_id")); result.add(rs.getString("w_name")); result.add(rs.getString("sex")); result.add(rs.getString("d_name")); result.add(rs.getString("post")); result.add(rs.getDate("contract_date").toString()); list.add(i,result); i++; } // 释放此 ResultSet 对象的数据库和 JDBC 资源 rs.close(); // 释放此 PreparedStatement 对象的数据库和 JDBC 资源 st.close(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return list; } /** * 修改员工信息 * @param */ public static boolean updateWorker(String wId,String dId,String wName,String sex,String age,String date,String dName,String post){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); System.out.println(wId+dId+wName+sex+age+date+dName+post); try { CallableStatement c = conn.prepareCall("{call p_updateworker(?,?,?,?,?,?,?)}"); c.setString(1,wId); c.setString(2,wName); c.setString(3,sex); c.setString(4,age); System.out.println("传入的时间是 "+date); c.setString(5,date); c.setString(6,post); c.setString(7,dId); //c.setDate(6,Date.valueOf(date)); //执行Oracle存储过程 c.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return true; } /** * 获取员工列表 * @param */ public static Vector<Vector<String>> getWorkerList(){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); ResultSet rs=null; Vector<Vector<String>> list=new Vector<Vector<String>>(); int i=0; try { Statement st = conn.createStatement(); String sql="SELECT * FROM \"worker\""; rs = st.executeQuery(sql); // 判断结果集是否有效 while(rs.next()){ // 数据库存在,返回结果集 Vector<String> result=new Vector<String>(); result.add(rs.getString("w_id")); result.add(rs.getString("w_name")); result.add(rs.getString("sex")); result.add(rs.getString("post")); result.add(rs.getDate("contract_date").toString()); result.add(rs.getString("d_id")); list.add(i,result); i++; } System.out.println("长度 "+list.size()); rs.close(); // 释放此 PreparedStatement 对象的数据库和 JDBC 资源 st.close(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return list; } /** * 查询部门经理 * @param */ public static Vector<String> queryManager(String dName){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); String wId="",wName="",sex="",age="",post="",contractTime=""; Vector<String> list=new Vector<String>(); try { CallableStatement c = conn.prepareCall("{call P_FDMANAGER(?,?,?,?,?,?,?)}"); c.setString(1,dName); c.registerOutParameter(2, OracleTypes.VARCHAR); c.registerOutParameter(3,OracleTypes.VARCHAR); c.registerOutParameter(4,OracleTypes.CHAR); c.registerOutParameter(5,OracleTypes.CHAR); c.registerOutParameter(6,OracleTypes.DATE); c.registerOutParameter(7,OracleTypes.VARCHAR); //执行Oracle存储过程 c.execute(); wId=c.getString(2); wName=c.getString(3); sex=c.getString(4); age=c.getString(5); contractTime=c.getDate(6).toString(); post=c.getString(7); System.out.println("执行查询"); list.add(wId); list.add(wName); list.add(sex); list.add(age); list.add(contractTime); list.add(post); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return list; } /** * 查询项目设备采购信息 * @param */ public static Vector<String> getEqubyPro(String pName){ Vector<String> result=new Vector<String>(); // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); String eNmae="",eSupplier=""; float eFee; try { CallableStatement c = conn.prepareCall("{call P_GETEBYP(?,?,?,?)}"); c.setString(1,pName); c.registerOutParameter(2, OracleTypes.VARCHAR); c.registerOutParameter(3,OracleTypes.FLOAT); c.registerOutParameter(4,OracleTypes.VARCHAR); //执行Oracle存储过程 c.execute(); eNmae=c.getString(2); eFee=c.getFloat(3); eSupplier=c.getString(4); result.add(eNmae); result.add(String.valueOf(eFee)); result.add(eSupplier); System.out.println("查询设备 "+eNmae+eFee+eSupplier); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return result; } /** * 查询设备采购费用信息 * @param */ public static float getEquFee(String eName){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); float eFee=0; try { CallableStatement c = conn.prepareCall("{call P_GETEFEE(?,?)}"); c.setString(1,eName); c.registerOutParameter(2,OracleTypes.FLOAT); //执行Oracle存储过程 c.execute(); eFee=c.getFloat(2); System.out.println("查询设备 "+eName+eFee+"----"); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return eFee; } /** * 添加设备 * @param */ public static void addEqu(String eId,String eName,float fee,String supplier,String remarks,String pId){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); System.out.println(eId+eName+fee+supplier+remarks+pId); try { CallableStatement c = conn.prepareCall("{call p_addequ(?,?,?,?,?,?)}"); c.setString(1,eId); c.setString(2,eName); c.setFloat(3,fee); c.setString(4,supplier); c.setString(5,pId); c.setString(6,remarks); //执行Oracle存储过程 c.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } } /** * 查询设备供应商信息 * @param */ public static String getEquSup(String eName){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); String eSupplier=""; try { CallableStatement c = conn.prepareCall("{call P_GETESUP(?,?)}"); c.setString(1,eName); c.registerOutParameter(2,OracleTypes.VARCHAR); //执行Oracle存储过程 c.execute(); eSupplier=c.getString(2); System.out.println("查询设备 "+eName+eSupplier); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return eSupplier; } /** * 查询项目员工信息 * @param */ public static void getWerbyPro(String pName){ // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); String wNmae="",wId=""; float eFee; try { CallableStatement c = conn.prepareCall("{call P_GETEBYP(?,?,?,?)}"); c.setString(1,pName); c.registerOutParameter(2, OracleTypes.VARCHAR); c.registerOutParameter(3,OracleTypes.FLOAT); c.registerOutParameter(4,OracleTypes.VARCHAR); //执行Oracle存储过程 c.execute(); wNmae=c.getString(2); wId=c.getString(4); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } } /** * 查询项目完成情况 * @param */ public static Vector<String> queryComplete(String ManagerName){ Vector<String> result=new Vector<String>(); // 获取数据库连接Connection对象 Connection conn = ConnectDB.getConnection(); String date1="",date2="",pName="",isComplete=""; try { CallableStatement c = conn.prepareCall("{call P_ISFINISHED(?,?,?,?)}"); c.setString(1,ManagerName); c.registerOutParameter(2, OracleTypes.DATE); c.registerOutParameter(3, OracleTypes.DATE); c.registerOutParameter(4, OracleTypes.VARCHAR); //执行Oracle存储过程 c.execute(); date1=c.getString(2).toString(); date2=c.getString(3).toString(); pName=c.getString(4); System.out.println("签订时间是:"+date2); System.out.println("应完成时间是:"+date1); //pName=c.getString(4); Date date; date=c.getDate(2); System.out.println("应完成时间是 "+date1); System.out.println("时间格式 "+date); Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//可以方便地修改日期格式 String hehe = dateFormat.format( now ); System.out.println(hehe); if(date1.compareTo(hehe)<0){ isComplete="已完成"; System.out.println("已经完成"); } else { isComplete="未完成"; } result.add(pName); result.add(date2); result.add(date1); result.add(isComplete); } catch (Exception e) { e.printStackTrace(); }finally{ // 关闭数据库连接 ConnectDB.closeConnection(conn); } return result; }}
    8 总结8.1 遇到的问题Oracle数据库与之前接触过的数据库SQL语句有些不一样,除了常用的增删查改与其他主关系型数据库相似,其他的语句还是有一些区别的。在实习中经常因为在SQL语句中少个双引号或者将双引号写成单引号而出错,所以在刚开始写存储过程中用了不少时间。可见Oracle数据库对语法的要求比较严格。
    8.2 存在的问题
    在这次实习中,我发现自己的数据库设计能力还稍有不足,对项目管理系统的几个表的设计不是很合理,表中有些字段的类型和长度可能与实际应用不相符。在进行数据库设计时应该考虑实际项目中的应用,这样才能设计出满足实际需求的数据库管理系统。
    客户端程序中的程序设计时没有很好地采用架构来实现。使用三层逻辑架构时没有做到完全的层次分离,在表现层中还存在一些业务逻辑层的代码。数据库中每个表都应该用一个类来封装,然后对类中的成员变量也就是数据库表中的每个字段分别设置set()和get()方法。
    程序尚存在一些已知和未知的BUG,反映出自己在程序设计时对问题的考虑不够全面,对于在实际中可能存在的情况没完全把握。

    8.3 收获
    通过完成数据库课程设计,加深了我对数据库理论知识和在实际应用方面的认识,在实践中发现了自己在数据库设计和程序设计上的不足,对于提高自己的编程能力很有帮助。实习中的数据库设计部分可以巩固在实用数据库中的知识,让我学会在实际场景中更好地使用数据库。
    这次实习让我学习了在项目中经常使用到的主流关系型数据库Oracle,掌握Oracle的特征和基本使用方法。在项目中使用Oracle可以实现对SQL语句的封装,不仅提高程序的执行效率还提高了数据的安全性。当对数据库进行复杂操作时(如对多个表进行 Update, Insert, Query, Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
    5 评论 172 下载 2018-11-05 15:14:59 下载需要4点积分
  • 基于Java的网上书城

    主要技术关键字:JSP、servlet、Ajax、jstl、JavaScript、注册登录、分页、购物车、增删改查
    开发环境:Eclipse、MySQL 5.7、Tomcat 8.0
    数据库表结构设计
    books表结构:

    items表结构:

    orders表结构:

    userinfo表结构:

    项目包结构
    MVC设计模式M(model层)
    biz包:业务处理
    dao包:数据访问,对数据库的一些封装操作
    entity包:实体类,javabean构建,View层和数据库之间的桥梁作用

    V(view层)1. Jsp页面:与用户进行交互的界面。

    C(controller 层)1.servlet包:控制层,处理View层Jsp页面发来的请求。
    注册登录模块Register
    注册页面中form表单
    验证用户名、验证密码、验证邮箱
    <form method="post" action="RegisterServlet" onsubmit="return checkRegister()"> <dl> <dt>用 户 名:</dt> <dd><input class="input-text" type="text" id="username" name="username" onblur="isUsernameLegal()"/><span id="usernull"></span><span id="alreadyExsits"></span></dd> <dt>密  码:</dt> <dd><input class="input-text" type="password" id="password" name="password" onblur="isPasswordLegal()" /><span id="nullpassword"><font color=\"green\">密码至少8位</font></span><span id="simplepassword"></span></dd> <dt>确认密码:</dt> <dd><input class="input-text" type="password" id="rePassword" name="rePassword" onblur="isRepasswordLegal()" /><span id="nullrePassword"></span><span id="uneq"></span></dd> <dt>Email地址:</dt> <dd><input class="input-text" type="text" id="email" name="email" onblur="isEmailLegal()" /><span id="nullemail"><font color=\"green\">请输入正确格式的邮箱</font></span><span id="errorInput"></span></dd> <dt></dt> <dd class="button"><input class="input-reg" type="submit" name="register" value="" /></dd> </dl> </form>
    Ajax(异步 JavaScript 和 XML ):验证用户名是否已被注册,页面部分数据刷新,而无需加载整个网页,提高网站的访问效率。
    /** * Ajax检查用户是否已经被注册 * 异步:发送请求时不等返回结果,由回调函数处理结果 * @returns {Boolean} */function isExists() { var xmlHttp; //定义 xmlHttp XmlHttpRequest对象从服务器异步获取数据后通过javascript修改页面局部信息 try { //根据不同浏览器初始化不同的xmlHttp浏览器对象 //IE6以上浏览器 xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { //FireFox xmlHttp = new XMLHttpRequest(); } catch (e) { try { //IE5.5+ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("您的浏览器不支持Ajax"); return false; } } } var username = document.getElementById("username").value; //获取用户名 /** * open(提交方式[get|post],url(servlet路径),同步或异步[false|true]) * RegisterServlet: servlet路径 * 打开和后台服务器的链接 */ xmlHttp.open("POST", "RegisterServlet?action=check&username="+username, true); //路径中不能有空格 xmlHttp.send(null); //传送数据 /** * onreadystatechange:调用回调函数 * readyState:请求状态,代码是未初始化,1:初始化,2:发送请求,3:开始接受数据,4:接受结果完毕 * status: http状态码 200成功,404路径错误,500后台代码错误, */ xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState==4 && xmlHttp.status==200) { var usernull = document.getElementById("usernull"); var result = xmlHttp.responseText; //接受服务器端传过来的数据,写出来的数据都是String类型 if(result == "true") { usernull.innerHTML = "<font color='red'>当前用户名已被注册</font>"; return false; } else if(result == "false") { usernull.innerHTML = "<font color='green'>当前用户名可用</font>"; return true; } } }}
    Login
    LoginServlet中doGet方法:
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username");//获取页面传过来的参数 String password = request.getParameter("password"); //登录操作 boolean flag = userBiz.checkLogin(username, password); if(flag) { request.getSession().setAttribute("loginuser", username);// response.sendRedirect("main.jsp"); response.sendRedirect("SearchServlet"); //首页直接显示 } else {//登录失败 response.setContentType("text/html;charset=utf-8");// response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println("<script type='text/javascript'>"); out.println("alert(\"登录失败!请重新登录\")");//反斜杠转义 out.println("open(\"login.jsp\", \"_self\");");//重新打开新的页面, _self在原窗口打开 out.println("</script>"); out.close(); } }
    网站首页及搜索图书模块
    分页展示Jstl标签库 c:forEach,循环遍历展示图书信息。
    <c:forEach var="book" items="${books }"> <tr> <td><input type="checkbox" name="bookId" value="${book.bid }" /></td> <td class="title">${book.bookname }</td> <input type="hidden" name="title" value = "${book.bid }:${book.bookname}"/> <td>¥${book.b_price }</td> <input type="hidden" name="price" value = "${book.bid }:${book.b_price}"/> <!-- b_price跟数据库字段名相对应 --> <td>${book.stock }</td> <input type="hidden" name="stock" value = "${book.bid }:${book.stock}"/> <td class="thumb"><img src="${book.image }" /></td> <input type="hidden" name="image" value = "${book.bid }:${book.image}"/> </tr></c:forEach>
    <!--分页开始--> <%if(request.getAttribute("current") != null) { %> <div class="page-spliter"> <a href="SearchServlet">首页</a> <%for(int i = 1; i <= totalPage; i++) { %> <%if(i==no) { %> <!-- 如果不是当前页显示为链接 --> <span class="current"><%=i %></span> <%continue;} %> <a href="SearchServlet?currentPage=<%=i %>"><%=i %></a> <%} %> <a href="SearchServlet?currentPage=<%=totalPage %>">尾页</a> </div> <%} %><!--分页结束-->
    servlet处理
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String currentPage = request.getParameter("currentPage");//获取当前页 int no = currentPage == null?1:Integer.parseInt(currentPage);//如果当前页为空,则默认为1,否则转化为相应的int// String currentSearchPage = request.getParameter("currentSearchPage"); String bookname = request.getParameter("keywords");//获取你输入的书名 List<Book> books = null; if(bookname==null || bookname.equals("")){ books=bookbiz.findAll(3, no);//查询所有。3:代表每页显示的条数,no:当前显示页面 request.setAttribute("totalPage", (bookbiz.count()/3 + 1));//将总页面数存入request } else { books = bookbiz.findBookByName(bookname,3, no);//根据书名模糊查询出数据 System.out.println(books.size()); request.setAttribute("totalPage", (books.size()/3 + 1));//将总页面数存入request } request.setAttribute("books", books);//将查询出的数据存入request request.setAttribute("current", no);//将当前页存入request request.getRequestDispatcher("main.jsp").forward(request, response);//页面转发 }
    关键字匹配查询输入“Java”关键字,展示搜索结果

    购物车模块增
    注意:
    当库存不足时,防止库存数被减到负值。
    if(oneStock > 0) {//如果库存大于0 //查看当前图书是否已经存在于购物车中 //查看购物车列表是否已经存在该图书,对比两个图书id for (int j = 0; j < bookcart.size(); j++) { Book existBook = (Book) bookcart.get(j); if(existBook.getBid() == bid) {//如果购物车中的id==被选中的图书id,则购物车中的数量+1 bookcart.remove(j); existBook.setCount(existBook.getCount()+1);//购物车中商品数量+1 double totalPrice = existBook.getPrice(); bookcart.add(existBook);//商品总价 System.out.println("总价"+totalPrice); isNotExists = false; //修改库存 isOrNotChangeStock = bookbiz.changeStock(bid, "-1"); break; } } if(!isNotExists) { continue; } book.setBid(bid); //判断当前获取的图书信息是否为指定bid下的信息 for (int j = 0; j < title.length; j++) {// request.setCharacterEncoding("utf-8"); //解决页面图书标题中文显示乱码 String title_temp =new String(title[j].getBytes("ISO-8859-1"),"utf-8");//取标题 if(title_temp.indexOf(bids[i]+":")<0) {//indexOf匹配bids是否包含在title_temp中,如果没有返回-1 continue; } if(image[j].indexOf(bids[i]+":")<0) { continue; } if(price[j].indexOf(bids[i]+":")<0) { continue; } if(stock[j].indexOf(bids[i]+":")<0) { continue; } //添加指定bid下的图书信息 book.setBookname(filter(title_temp, bids[i])); book.setImage(filter(image[j], bids[i])); book.setPrice(Double.parseDouble(filter(price[j], bids[i])));// book.setPrice(Double.valueOf(filter(price[j], bids[i]))); book.setStock(filter(stock[j], bids[i])); book.setCount(1); //修改库存 bookbiz.changeStock(bid, "-1"); bookcart.add(book); } }
    删移除操作
    protected void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取图书id String bid = request.getParameter("bid"); //2.获取购物车 List<Book> bookcart = (List<Book>) request.getSession().getAttribute("bookcart"); //3.循环查找购物车中相同的图书id for(int i = 0; i< bookcart.size(); i++) { Book book = bookcart.get(i); if(Integer.valueOf(bid) == book.getBid()) { //4.移除图书 bookcart.remove(i); //5.修改库存 bookbiz.changeStock(Integer.parseInt(bid), book.getCount()+""); break; } } //6.将购物车保存到session中// request.getSession().setAttribute("bookcart", bookcart); request.getSession().setAttribute("bookcart_count", bookcart.size()); System.out.println(request.getSession().getAttribute("bookcart_count")); }
    改1.前端shopping.jsp页面,添加onblur失去焦点事件,当鼠标离开输入框时执行JavaScript代码,调用update方法。
    <c:set value="1" var="count"></c:set> <c:forEach var="book" items="${bookcart }"> <tr> <input type="hidden" id="hidden_bid_${count }" name="hidden_bid_${count }" value="${book.bid }"/> <td class="thumb"><img src="${book.image }" /></td> <td class="title">${book.bookname }</td> <td><input class="input-text" type="text" id="nums_${count }" name="nums_${count }" value="${book.count }" onblur="update(${bookcart_count}, ${count }, ${book.bid })"/></td> <!-- onblur事件 --> <input type="hidden" id="hidden_${count }" name="hidden_${count }" value="${book.price }"/> <td>¥<span id="price_${count }"></span></td> <input type="hidden" id="hidden_book_total_price_${count }" name="hidden_book_total_price_${count }" /> <td><span id="remove_${count }"><a href="#" onclick="del(${book.bid})">移除</a></span></td> <!-- href链接, --> </tr> <c:set value="${count+1 }" var="count"></c:set></c:forEach>
    2.异步更新图书购买量数据,并向控制层Servlet中返回一个“update”
    /** * Ajax修改购物车中的数量 */function update(size_str, i, bid_str) { //初始化XMLHttpRequest对象 var xmlHttp; try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new XMLHttpRequest(); } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { e.message(); alert("你的浏览器不支持Ajax"); } } } //2.获取修改后的数量 var num_str = document.getElementById("nums_"+i); //3.打开服务器链接 xmlHttp.open("POST", "ModifyCartServlet?action=update&bid="+bid_str+"&count="+num_str.value, true); //4.传值 ,无参传null值 xmlHttp.send(null); //5.设置回调函数 xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { count(size_str);//调用Servlet中的方法 } }}
    3.servlet中通过前端返回的请求调用相应的方法。
    String action = request.getParameter("action");if(action.equals("update")) { updateCart(request, response);}else if(action.equals("remove")) { remove(request, response);}
    4.控制层Servlet更新购物车数据,并修改库存。
    protected void updateCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取图书id和修改后的数量 String bid = request.getParameter("bid"); String count = request.getParameter("count"); //2.获取购物车 List<Book> bookcart = (List<Book>) request.getSession().getAttribute("bookcart"); //3.查找购物车中修改过的图书,并修改相应的信息 for (Book book : bookcart) { if(Integer.valueOf(bid) == book.getBid()) { //4.获取修改前的图书数量 int old_count = book.getCount(); //5.设置当前图书的新数量 book.setCount(Integer.valueOf(count)); System.out.println("当前图书新数量"+count); int nowStock = 0; try { nowStock = basedao.queryStock(Integer.parseInt(bid)); } catch (Exception e) { e.printStackTrace(); } //6.修改库存 bookbiz.changeStock(Integer.parseInt(bid), (old_count-Integer.parseInt(count))+""); break; } } }
    查与搜索图书模块类似
    我的订单模块
    1.获取订单信息,存入List中
    <% List orders = (List) request.getAttribute("orders"); %>
    2.订单展示
    <c:forEach var="order" items="${orders }"> <tr> <td id="id_${td_id}">${order.oid }</td> <td id="user_${td_id}">${order.username }</td> <td id="crdt_${td_id}">${order.createdate }</td> <td id="total_${td_id}">${order.total_price }</td> <td class="thumb"><img src="${order.image }" /></td> <td>${order.bookname }</td> <td>${order.b_price }</td> <td>${order.total_price/order.b_price }</td> </tr></c:forEach>
    用户退出当用户退出登录,清空session。
    <%--用户退出登录 --%><% request.getSession().removeAttribute("loginuser"); request.getSession().removeAttribute("bookcart"); request.getSession().removeAttribute("bookcart_count"); response.sendRedirect("login.jsp");%>
    一些注意细节1.为防止游客非法访问页面,在每一个前端页面body之后加上登录检测代码。
    <% String username = (String)session.getAttribute("loginuser"); if(username == null) { response.sendRedirect("login.jsp"); }%>
    2.当库存不足时,防止库存数被减到负值。
    if(oneStock > 0) {//如果库存大于0 //...}
    3.href中加上空链接,否则该页面中的session不会刷新,必须手动刷新。
    <span id="remove_${count }"><a href="#" onclick="del(${book.bid})">移除</a></span>
    网站云部署一个经过部署的网站才是一个完整的网站
    阿里云平台
    租用ecs云主机,搭建Java运行环境,jdk、mysql、Tomcat
    域名解析
    项目打包成.war文件上传至云服务器。
    启动服务器
    通过域名访问并测试网站:http://ycuer.xin:8080/books/
    5 评论 142 下载 2019-02-12 08:15:38 下载需要7点积分
  • 基于SSM的网上购物系统的设计与开发

    摘 要本论文主要对网上购物商城的设计与开发进行了一些论述,包括了系统的设计和实现一共两个大部分,设计部分主要对系统和数据库的分析与设计进行了描述;实现部分主要包括系统的各个功能的实现。
    网上购物商城包括两大模块:前台用户模块和后台管理员模块,前台用户可以通过浏览器客户端页面进行登陆和一系列的购物操作。后台管理员可以查看所有用户的所有信息;可以对网站中所有的商品分类进行修改,同时也可以对所有用户的订单状态进行查看。
    系统前台通过JSP页面来来展示数据,后台基于java技术和eclipse (朱诺)和tomcat 7.x开发,前台运用html+css技术渲染页面,后台使用springmvc、spring、myBatis对数据进行封装和操作,该系统运用MySql 5.X 数据库进行数据的维护。页面美观,使用方便。
    关键词:MySql数据库; JAVA; SSM;网上购物商城
    AbstractThis paper mainly focuses on the clothing sales system design and development of a number of paper, including the system design and implementation of a total of two parts, part of the system design and database analysis and design were described; the realization part includes the various functions of the system.
    Clothing sales system includes two modules: front user module and the background administrator module, the front desk users can browse through the browser client page and a series of shopping operations. The background administrator can view all the information of all users can be on the site of all the clothing category to modify, but also for all users to view the order status.
    In front of the system through the JSP page to display the background data, Java technology and based on eclipse (Zhu Nuo) and Tomcat 7.x development, the use of html+css technology to render the page, the background using springmvc, spring, myBatis package and operation of data, the system uses MySql 5.X database for data maintenance. Beautiful page, easy to use.
    Keywords: MYSQL DB;JAVA;SSM;CLOTHING SALES SYSTEM
    1 绪论1.1 研究背景在如今这个信息时代,“网上购物”这种购物方式已经为越来越多的人所接受。在这种背景之下,一个安全稳定并且强大的网络购物平台不可或缺,在这种成熟的市场需求的推动下,在先进的信息技术的支持下,商品产品销售系统应运而生。它可以使消费者和商家更紧密地联系起来,以更快地满足顾客的需求,也可以让用户选择自己真正喜欢的商品。目前市面上已经有此类的网上购物商城,但是现有商品网站系统或多或少存在着功能比较单一、维护比较复杂、操作比较繁琐等问题。有的系统甚至直接采用静态网页发布商品商品信息,这些因素在一定程度上限制了网上购物商城在目前市场上的推广。如何开发出费用低廉、功能强大的系统正是我们需要解决的课题。
    1.2 目的和意义本软件旨在降低商品销售商家的工作强度,提高工作效率,大大地减少了操作员手工录入数据的工作量,极大限度的避免了人力浪费,有效避免重复操作时间消耗;而且此软件方便了用户对自己所需商品的查询和购买,打破了传统的销售模式,极大限度的方便了用户。商家应用此软件之后,可以拓展销售门路,增加销售业绩。应用此软件是为了在传统销售模式之外,再开辟一条销售通路,减少库存堆积,利用网络共享和互动的优点,结合地面销售的优点,借助数据库管理技术,开发此平台,是为了实现规范化、个性化、人性化的商品网上销售。此软件的数据统计分析功能灵活完善,稳定安全、使用方便、界面友好、操作简单,可以成为一个能真正帮助商品销售行业管理发展的有力工具。
    1.3 开发工具及技术该网上购物商城前端使用了jsp来实现数据的展示,后端通过java代码来对数据进行一系列的操作,前端使用了原生的html页面技术进行渲染,同时也加入了jquery技术制作了一下控件效果,后端使用了经典的spring技术对整个系统进行统一调度,使用springMvc框架实现了前端和后端的交互。开发工具使用了Eclipse以及tomcat服务器,同时使用了Mysql数据库对数据进行存储和维护。
    在该系统实现的过程中,使用spring和springMvc的同时后端还使用了MyBatis技术对数据进行封装和操作。前端还采用了dtree框架规范了页面的显示。整个系统的架构也是基于经典的mvc设计模式来设计的。
    Mybatis是一个经典的后端开源框架,它的前身就是iBatis,MyBatis的执行原理是应用程序根据XML配置文件创建出SqlSessionFactory,然后SqlSessionFactory根据配置文件或者注解创建出SqlSession,SqlSession这个对象包含了所有的执行sql所需要的所有方法,可以通过SqlSession这个实例执行所有的方法对数据库进行操作,操作结束后执行相应的事物控制,本系统中的事物控制全部交由spring容器进行统一调度,本次采用的是spring的申明式 方式。MyBatis相对于 其他的ORM框架具有很多的优点,比如mybatis本身属于轻量级框架简单易学,没有第三方的依赖。mybatis比较灵活,开发人员可以自己编写sql语句来对数据进行操作。mybatis提供了xml标签,支持编写动态sql.
    dtree框架就是一个简单的树形菜单js组件,开源免费,自身不需要复杂的操作,同时也支持动态的将数据引入jsp页面。
    MVC模式是一种软件架构模式。它将系统分为三个部分:模型,视图和控制器。MVC模式出现的目的就是方便了后续程序的修改和扩展简化,同时使系统中某一段代码的重复利用成为可能。此模式降低了模块之间的耦合度,对自身各个部分进行了分离的同时也使得各个部分具备了应有的功能。
    Spring是从实际开发中抽取出来的开源框架,为企业的开发提供一个轻量级的解决方案。该解决方案包括:基于Ioc(控制反转)的核心机制,以及AOP(面向切面编程)的思想,能与多种持久层技术的整合,是优秀的Web MVC框架等。Spring致力于Java EE应用各层的解决方案而不是仅仅专注于某一层的方案,它贯穿表现层、业务层、持久层,降低各层组件的耦合度,实现软件各层的解耦.Spring内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的。还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过配置类达到的。Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。
    2 需求分析2.1 功能需求分析2.1.1 网站前台功能
    首页:提供一个网站首页,显示该企业的商标,该网站用户的登录,注册,所有商品的一级分类,热门商品和最新商品的展示等
    用户的注册:针对还未注册的用户完成注册功能的使用,在注册的过程中涉及数据的合法性校验,以及利用ajax完成用户名是否已被注册的异步校验
    用户的登录:对于已经注册并且激活的用户提供的登录操作
    用户的退出:对于已经登录的用户,退出系统
    首页商品展示:展示出最新商品和热门商品
    分类页面商品展示:根据一级分类和二级分类去展示该分类下的所有商品
    商品详情展示:点击某个商品时可以展示该商品的具体详细信息
    购物车:用于存放用户的购物内容,用户可根据自己的情况修改自己的购物车
    订单:对于已经登录的用户可以对购物车内容进行付款生成订单,可以为自己的订单进行付款或者查看
    留言评价分享:网站单独开辟了留言分享区域,供登录的用户自由发表评价分享心得信息,进行交流互动

    2.1.2 网站后台功能
    管理员登录:管理者根据账户和密码进行登录
    商品一级、二级分类管理:管理者可以对前台显示的一级、二级分类进行管理,包括添加、删除、修改操作
    商品管理:管理者可以对前台显示的商品进行管理包括添加,修改,删除,查询的功能,也可以上传商品的图片
    用户管理:管理者可以查看该网站中已经注册过的所有用户的所有信息

    2.2 性能分析响应时间:忽略网络、硬件以及插件的因素,以本地测试为准,前台响应时间为0.8秒,后台操作响应时间:0.9秒。
    2.3 系统用户用例图用户用例图
    用户为系统的使用者,可以通过前台注册激活登录后进行一系列的购物操作。

    管理员用例图
    管理员是整个系统的最高权限拥有者,他用于对所有用户的所有信息的查看,网站商品显示的增删改查,更换图片,所有商品所属一级二级分类的修改。

    3 系统设计3.1 系统的总体设计该系统的开发采用B/S模式,整个系统的构建基于ssm(Spring+SpringMvc+MyBatis)整合框架。
    深入研究JavaEE体系结构,所项目的技术选型中选取的个个框架分别进行分析和研究。SpringMvc是一个web端框架。Mybatis是一个轻量级的持久层框架,以面向对象的方式提供了持久化类到数据库之间的映射,是一种优秀的ORM框架。Spring也是一种轻量级框架,它的IOC和AOP思想,值得架构师学习。通过三大框架的整合,可以很方便的构建出可扩展,可移植,可维护的软件系统。
    SSM框架是目前J2EE领域中最热门而且用的比较成熟的一套开源框架,它是基于MVC设计模式之上,充分发挥了MVC的优点。SSM是一套轻量级框架,相对于EJB而言,SSM继承了它的优点的同时,在开发和执行效率上也有了明显的提高,而对于开发者而言,它比EJB更加易学和掌握。目前SSM框架也正在不断地进行优化和维护,运行也是越来越稳定。
    根据以上功能分析,得到系统功能模块结构图如图3-1所示:

    3.2 数据库的分析与设计数据库,我们可以形象的将它称为一个仓库,因为它一般被用来存放汉字、字符、数据、货币、日期等信息,并且对这些信息按照一定规则存放,对数据进行安全、低冗余性、规范的进行集成化管理。从发展的历史历程来看,数据库可以看成是由文件管理系统发展而来的。
    数据库的基本结构可以分为三个层次包括物理数据层、概念数据层、逻辑数据层。数据库不同层次之间的联系是通过映射进行转换的,数据库的特点包括实现数据共享、减少数据的冗余度、数据的独立性、数据实现集中控制、数据一致性和可维护性。
    本系统采用的的数据库是Mysql5.0,本系统所有与数据库相关的开发都遵循Mysql5.0数据库开发原则。
    3.2.1 数据库概念设计用户实体
    用户实体包括编号、用户账号、姓名、联系方式、性别、用户状态、用户邮箱和密码等属性。用户实体的实体联系图(E-R图)如下所示:

    管理员实体
    管理员实体包括编号、账号和登录密码属性。管理员实体的实体联系图(E-R图)如下所示:

    商品实体
    商品实体包括商品id、商品名称、市场价、商场价、商品图片、商品描述、上架日期、所属二级分类id。商品实体的实体联系图(E-R图)如下所示:

    订单实体
    订单实体主要包括订单id、订单总价、订单状态、收货人、收货地址、收货电话、下单时间、购买者id、购买商品id。订单实体的实体联系图(E-R图)如下所示:

    3.2.2 数据库物理结构为该系统设计了7张表,在这里列出7张表分别为如下所示:



    数据表
    描述




    adminuser
    后台管理员表


    category
    一级分类表


    categorysecond
    二级分类表


    orderitem
    订单项表


    orders
    订单表


    product
    商品表


    user
    前台用户表



    管理员表主要记录了管理员的基本消息,表结构如表3-1所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    id
    int(11)
    YES
    YES
    账号


    username
    varchar(1000)
    NO
    NO
    用户名


    password
    varchar(1000)
    NO
    NO
    密码



    一级分类表主要记录了一级分类的基本信息,表结构如图3-2所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    cid
    int(11)
    YES
    YES
    一级分类ID


    cname
    varchar(1000)
    NO
    NO
    一级分类名



    二级分类表主要记录了二级分类的基本信息,表结构如图3-3所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Csid
    int(11)
    YES
    YES
    二级分类id


    Csname
    varchar(1000)

    NO
    二级分类名称


    cid
    varchar(1000)

    NO
    所属一级分类id



    订单项表主要记录了订单项的基本信息,表结构如图3-4所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Oiid
    int(11)
    YES
    YES
    订单项id


    count
    varchar(1000)


    购买数量


    subtotal
    double


    单项总价id


    Pid
    int(11)


    所购商品id


    cid
    int(11)


    所属订单id



    订单表主要记录了订单的基本信息,表结构如图3-5所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    oid
    int(11)
    YES
    YES
    订单id


    money
    double


    订单总价


    state
    Int(11)


    订单状态


    Receiveinfo
    Varchar(255)


    收货地址


    phonum
    Varchar(255)


    收货人电话


    Order_time
    datetime


    下单时间


    Uid
    Int(11)


    所属用户id



    商品表主要记录了商品的基本信息,表结构如图3-6所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Pid
    int(11)
    YES
    YES
    商品id


    Pname
    Varchar(255)


    商品名称


    Market_price
    Int(11)


    市场价


    Shop_price
    Varchar(255)


    商城价


    image
    Varchar(255)


    商品图片


    Pdesc
    Varchar(255)


    商品描述


    Is_hot
    int(11)


    是否热门


    Pdate
    datetime


    商品上架日期


    csid
    int(11)


    所属二级分类id



    前台用户表主要记录了前台用户的基本信息,表结构如图3-7所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Uid
    int(11)
    YES
    YES
    用户id


    Username
    Varchar(255)


    用户名


    password
    Varchar(255)


    用户密码


    Name
    Varchar(255)


    用户真实姓名


    Email
    Varchar(255)


    用户游戏


    Phone
    Varchar(255)


    用户手机号


    Addr
    Varchar(255)


    用户地址


    State
    int(11)


    用户状态



    3.3 小结本章主要是对数据库进行了设计和说明。对数据库的概念设计思路和物理结构进行了详细的说明,并对数据库中涉及到的实体进行了说明。
    4 系统主要功能实现4.1 系统注册页面实现4.1.1 客户端用户注册用户登录网站出现页面,点击“注册”,进入注册页面,填写数据,点击注册按钮进行注册,注册完之后保存数据库表中,即可登录网站。
    注册效果如图4-1所示:

    var username = document.getElementById("username").value;var xmlHttp = creatXMLHttpreauest();xmlHttp.open("GET","${pageContext.request.contextPath}/registFindByid.action?username="+ username, true); xmlHttp.send(null); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { document.getElementById("span1").innerHTML = xmlHttp.responseText;
    服务器端二次数据合法性校验(此处采用的配置文件加注解的方式)
    user.username.length.error=用户名的名字的长度必须是1至30user.email.notNull=邮箱不可为空@Size(min=2,max=30,message="{user.username.length.error}") private String username; @NotNull(message="{user.email.notNull}") private String email;
    4.2 系统登录页面实现4.2.1 用户登录用户在注册后,在客户端登录页面输入正确的用户名和密码,进入网站进行购物。 程序运行如下图4-2所示:

    设计思路
    编写用户登录的页面login.jsp,用户在首页点击“登录”按钮后,浏览器跳转到登录页面,用户可以填写用户名和密码进行登录,当用户填写用户名并使光标移开 时,触发onblur()事件,进行ajax异步请求,判断用户名是否可以登录,用户在填写验证码时可以点击图片,进行跟换验证码,触发onclick=”change()” 事件进行更换,当用户点击“登录”按钮时,服务器进行数据判断,如果用户名和密码都正确则跳转到首页并显示该用户的用户名,如果有错误则跳转到msg.jsp全局页面显示错误消息。
    4.2.2 管理员用户登录后台管理员通过访问正确的路径之后进入到管理员登录页面,如果访问的不是正确页面但出现了admin路径则自动跳转到admin页面,然后输入正确的用户名和密码进行登录,如果出错,服务器会将错误信息回显到登录页面,如果正确则跳转到管理员页面。
    程序运行结果如图所示,图4-3显示了管理员登录的页面,图4-4则是管理员登录成功后的主页面:


    4.3 系统前台功能实现系统前台页面包括以下几个部分:首页一级分类,热门商品,最新商品的显示,二级分类的显示,已登录用户的订单以及用户所操作过的购物的展示,其中一级分类和二级分类在各个页面中都有所设计,因此这里采用的是页面包含技术。
    4.3.1 一级分类模块查询一级分类描述
    本系统中首页显示的一级分类都是存放于数据库中,当用户访问该网站首页的同时就查询了一级分类。一级分类显示效果如图4-5所示:

    设计思路
    一级分类展示于系统的首页,当用户访问index.action时,最终跳转至系统首页即index.jsp,跳转之前,服务器内部已经进行了一级分类的查询,并将已经查询到的以及分类存放于List集合中,最终存放于session域中。
    查询某个一级分类描述
    用户在进入系统首页时,当点击一级分类时就要求查询系统在下一个页面中显示出该一级分类中包含的所有二级分类。查询某个二级分类的效果图如图4-6所示:

    设计思路
    当用户点击首页中的一级分类时系统则根据此一级分类的id查询出该一级分类下所有的二级分类,并存放于session域中,将页面进行跳转,并进行展示。
    主要代码
    request.getSession().setAttribute("cid",cid);PageBean<Product> proPageBean = productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);return "category";
    4.3.2 商品模块查询最热商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最热的商品。程序运行结果如图4-7所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最热商品显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的热门商品,因此使用了findHotProduct()这个方法,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前段控制层代码
    List<Product> hList= productService.findHotProduct();
    service层代码
    List<Product> list = productMapper.selectByExample(example);
    查询最新商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最新的商品。程序运行结果如图4-8所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最新商品和最热商品一样都是显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的最新商品,因此使用了findNewProduct()这个方法,查询最新商品的依据是商品被上传的时间,根据时间来进行排序,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前端控制层代码
    List<Product> nList =productService.findNewProduct();
    service层代码
    ProductExample example = new ProductExample();ProductExample.Criteria criteria = example.createCriteria();example.setOrderByClause("pdate DESC");example.setBeginPage(0);example.setEnd(10);
    查询分类商品描述
    用户在点击首页的一级分类时,系统自动跳转页面,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-9所示:

    设计思路
    首先导入页面,页面和查询二级分类下的商品使用的是同一个页面category.jsp。当用户点击按钮时,客户端向服务器请求发送请求并携带一级分类的主键id,因此服务器端应该接受参数并使用这个参数来调用方法然后去数据库进行查询数据,最后将查询出的数据把保存于Model中,最后跳转页面。
    由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层代码
    //根据一级目录查找二级目录下面的商品productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);
    Servive层代码
    int totlePage = 0;totlePage = productMapper.countProducyByCid(cid);if(Math.ceil(totlePage % limitPage)==0){totlePage=totlePage / limitPage;}else{totlePage=totlePage / limitPage+1;pageBean.setTotlePage(totlePage);int beginPage= (page-1)*limitPage;
    查询二级分类商品用户在点击首页的一级分类时,系统自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-10所示。

    设计思路
    首先编写页面category.jsp,这个页面用来显示某个二级分类下的所有的商品,当用户点击二级分类时系统访问对应的action,并且携带参数(相应二级分类的主键id),到前端控制层,然后findCategorySecond1()方法接收主键id和分页的数目去product表查询商品,最终将查询到的结果存放于Model中。由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层
    // 根据csid来分页查询商品PageBean<Product> proPageBean = productService.finbProductByCsid(csid,page);model.addAttribute("pageBean",proPageBean);
    查询商品信息用户再浏览该商场,查看某个商品的详细信息。程序运行结果如图4-11所示:

    设计思路
    首先编写页面,这里使用的是product.jsp,在这个页面中显示了以及分类的信息,还有每个一级分类下的二级分类,右下方是某个商品的具体信息,其中包括商品的名称,商品的商城价和市场价,包括一个选择框,用于用户选择购买数量,最下面则是商品的具体介绍。当用户点击某个想要查看的商品图片时,其实就是点击了某个超链接,向服务器发送链接并携带参数(商品的主键id),服务器端接收这个参数,并使用这个参数去数据库中查看这个商品的具体信息最后封装于product中,最终存放于Model中。
    前端控制层接收参数并调用service层,Service层直接调用Mybatis提供的mapper接口
    //根据pid来查询商品Product product = prodcutService.productFindByPid(pid);model.addAttribute("product", product);
    4.3.3购物模块添加到购物车对于已经登录的用户,可以将看中的商品具体信息保存于自己的购物车中。

    设计思路
    首先编写cart.jsp用于显示登录用户的购物车,如果用户没有登录会有提示,用点击查看商品的详情之后会出现一个“加入购物车”按钮,当点击此按钮时,自动访问服务器,并通过隐藏表单携带参数(商品的主键id),服务器端在接受此参数,并接收用户选购的数量,最终保存于我们为每个用户在session域中创建的cart。最后进行页面跳转,在cart.jsp中展示购物车的信息,主要包括:商品的具体信息和每项的价格和购物车的总价。对于已登录用户的页面,可以看到一个购物车的图标,用户可以查看自己的购物车。
    主要代码
    //添加到购物车Product product = productService.finbProductByPid(pid);//存进一个购物项CartItem cartItem = new CartItem();cartItem.setCount(count);cartItem.setProduct(product);cartItem.setSubtotle(count*product.getShopPrice());//存进购物车Cart cart=getCart(request);cart.addCart(cartItem);
    从购物车中移除商品用户点击购物车页面中每个购物项后面的删除按钮即可删除该购物项。程序运行结果如图4-13所示:

    设计思路
    当用户点击 “删除”按钮时,向服务器端进行请求,并携带参数(商品的主键id),服务器端在设计购物车时采用的是用Map集合存储的,key值即商品的id,因此删除的时候只需从session中拿到购物车直接根据主键删除,最后将页面重定向到cart.jsp.
    主要代码
    Cart cart=getCart(request);cart.delProFromCart(pid); //删除某个购物项
    清空购物车用户点击“清空购物车”按钮,购物车里面的购物项全部删除。程序运行结果如图4-17所示:

    设计思路
    当用户点击 “清空购物车”按钮时,向服务器端进行请求,服务器端收到请求之后,从session域中取出cart购物车,由于cart在设计的时候使用的是Map集合,所以只需调用Map中的clear()方法即可,并且还需将购物车的总价改为0,最后将页面重定向到cart.jsp.
    主要代码
    // 清空购物车Cart cart=getCart(request);cart.clearCart();
    4.3.4 订单模块生成订单当用户点击“生成订单”按钮时,页面跳转至order.jsp,并让用户填写相关信息。程序运行结果如图4-15所示:

    设计思路
    首先编写order.jsp页面,其中包含用户的购物信息和收货地址、收货人和联系方式。当用户点击cart.jsp中的生成订单按钮时,向服务器发送请求,服务器端从session域中拿到cart中的信息,并将这些信息保存于order表中,此时,需要清空购物车并且将订单信息保存到session域中,最后跳转到order.jsp页面让用户填写相关信息,并付款。
    主要代码
    Orders orders = new Orders();Cart cart = (Cart) request.getSession().getAttribute("cart");User loginUser = (User) request.getSession().getAttribute("loginUser");if(loginUser==null){ model.addAttribute("message", "对不起您还没有登录"); return "msg";}//生成订单
    我的订单用户对自己的选购的商品所生成的订单项进行付款。即可生成订单,进入我的订单列表界面;程序运行结果如图4-16所示:

    设计思路
    为订单付款页面还是使用的是order.jsp,当用户点击cart.jsp中的提交按钮时,页面进行跳转并显示相关的订单信息,此时,用户可以暂时不对订单进行付款,此时订单的状态为0。如果用户在生成订单的同时一并付款,或者点击用户的最上方右边的红色字体“我的订单”时,页面会进行跳转,并显示该用户的所有订单和订单的状态,此时想要付款则点击按钮“付款”,也会跳转到order.jsp,此时需要用户填写订单的具体信息,包括收货地址、收货人、联系方式以及付款的银行,此时客户端和服务器端一样会进行非空和数据合法性校验,当用户填写好信息并点击“付款”按钮时,其实就是服务器端拿订单的具体信息,并将订单的状态改为“1”,同时将用户填写的关于收货的信息保存于数据库order表中,最终服务器端会将页面重定向到orderList.jsp,向用户展示他的所有的订单以及订单的具体信息。在orderList.jsp中展示该用户的所有订单时采用的是分页查询,在订单的右下角同时也设置了按钮,方便用户查看自己的所有按钮。
    4.3.5 留言模块留言板当用户点击“留言板”按钮时,页面跳转至messageList.jsp,并让用户填写相关信息。程序运行结果如下图所示:

    4.4 系统后台功能实现4.4.1 用户模块查询用户管理员进入后台管理页面之后,当他点击“用户管理”按钮时,则在主页面中显示所有用户的详细信息。程序运行结果如图4-17所示:

    设计思路
    先编辑list.jsp页面,当用户点击“用户管理”按钮时,服务器端收到请求,调用service层的admin_findAll()方法由service 层调用myBatis提供的mapper接口,返回一个list集合,最终所有信息封装于Model中将页面跳转到list.jsp并进行展示。
    主要代码
    if(adminuserLogin==null){ request.getSession().setAttribute("message","对不起您还没有登录"); return "admin/index";
    4.4.2 一级分类模块添加一级分类此功能属于管理员的权限范围内,用户管理员为网站添加新的一级商品系别。程序运行结果如图4-18所示:

    设计思路
    首先编写add.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至add.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要添加的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的addCategory()方法,将新增的一级分类保存到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    主要代码
    Category addCategory = new Category();addCategory.setCname(cname);categoryService.addCategory(addCategory);
    修改一级分类此功能属于管理员的权限范围内,管理员用户修改网站中各大服饰的一级分类的名称。程序运行结果如图4-19所示:

    设计思路
    首先编写edit.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至edit.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要修改的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的adminCategory_update()方法,将修改的一级分类更新到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    删除一级分类后台管理员点击每个一级分类后面的删除按钮即可删除该一级分类。程序运行结果如图4-20所示:

    设计思路
    当用户点击每个一级分类后面的“删除”按钮时,服务器接收到请求然后接收携带过来的参数(一级分类主键id),当我们准备删除一级分类时,如果删除了改一级分类那么相应的二级分类和二级分类下的商品就得全部删除,因此我们根据myBatis的规则。先根据外键删除二级分类然后再删除一级分类,因此首先调用adminCategorySecond_deleteByCid(cid)删除二级分类然后再调用categoryService.deleteCategoryByCid(cid);删除一级分类,最终将页面重定向到list.jsp页面。
    主要代码
    categorySecondService.adminCategorySecond_deleteByCid(cid); categoryService.deleteCategoryByCid(cid);
    查询一级分类管理员点击“一级分类管理”按钮时,展示所有的一级分类的详细信息。程序运行结果如图4-21所示:

    设计思路
    首先编写list.jsp页面,当管理员用户点击“一级分类管理页面”按钮时,服务器端接收请求然后调用adminbFindCategory()方法最终由service层调用myBatis提供的Mapper接口将所有的一级分类的信息查询出来保存到list集合中,最终保存到Model中并将信息进行展示。考虑到一级分类比较多,这里使用了分页查询,在页面展示的效果就是每页显示固定的个数,并在右下角提供了相应的按钮方便用户进行查看其他的一级分类。
    主要代码
    List<Category> categoryList = categoryService.adminbFindCategory();model.addAttribute("categoryList", categoryList);
    4.4.3 二级分类模块添加二级分类管理员用户为新增加的一级分类添加二级分类。程序运行结果如图4-22所示:

    设计思路
    首先编写二级分类添加页面add.jsp,管理员用户点击“添加”按钮时,页面跳转到add.jsp,同时服务器端将查询出所有的一级分类的名称,用于管理员选择新增的二级分类的归属,这在add.jsp页面中通过一个下拉列表进行显示。管理员用户在填写好新增的二级分类的名称并选择好所属的一级分类之后点击“确定”按钮,服务器端接收新增的二级分类名称和所属的一级分类的主键id,然后调用adminCategorySecond_save()方法将新增的Categorysecond保存于数据库的categorysecond表中。最后将页面重定向到二级分类的list.jsp页面进行展示。
    主要代码
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCid(cid);categorySecondService.adminCategorySecond_save(categorysecond);
    修改二级分类管理员用户可以为网站中所有的二级分类的名称进行编辑。程序运行结果如图4-23所示:

    设计思路
    首先编写二级分类修改页面edit.jsp,管理员在list.jsp点击“编辑”按钮时,页面跳转到edit.jsp页面,跳转之前,服务器端查询到对应的二级分类的名称并将二级分类的名称保存到edit.jsp对应的表单中,这样方便用户知道自己修改的是哪个二级分,增加了用户体验度
    查询出对应的二级分类的名称存放于表单中,增加了用户体验
    Categorysecond findByCsid = categorySecondService.findByCsid(csid);model.addAttribute("findByCsid", findByCsid);
    更新修改的二级分类
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCsid(csid);CategorySecondService.adminCategorySecond_update(categorysecond);
    删除二级分类后台管理员根据查询出的二级分类列表对二级分类进行操作,根据系统的要求,管理员用户在删除二级分类的同时应该删除该二级分类下的所有商品。
    设计思路
    管理员用户在点击“二级分类用户”按钮时,在管理员页面展示所有的二级分类,当用户点击“删除”按钮时,服务器端收到客户端发来的请求,并接受客户端传来的数据(二级分类的主键id),然后根据二级分类的主键id调用adminCategorySecond_delete(csid)方法,删除二级分类,然后根据外键删除商品。最后将页面重定向到二级分类的list.jsp页面。
    主要代码
    // 删除二级分类,二级分类关联二级分类下面的商品categorySecondService.adminCategorySecond_delete(csid);categorySecondService.adminProduct_deleteByCsid(csid);
    查询二级分类管理员通过点击“二级分类管理”来查看网站中所有的二级分类。程序运行结果如图4-24所示:

    设计思路
    首先得编写二级分类的list.jsp页面。管理员用户点击“二级分类管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的二级分类,这里创建了一个pageBean对象用于封装查询出来的数据,包括二级分类的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为二级分类较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过二级分类的list.jsp页面右下方的按钮来查看所有的二级分类。
    4.4.4 商品分类模块添加商品管理用户通过点击商品展示页面list.jsp上的“添加”按钮可给网站添加新的商品。程序运行结果如图4-25所示:

    设计思路
    首先编写商品添加页面add.jsp。管理员用户点击商品展示页面list.jsp上的“添加”按钮之后客服端跳转到add.jsp页面,在客户端页面跳转之前,服务器端需要查询出所有商品的二级分类,方便上传用户选择该商品所属的二级分类。管理员需要填写页面上的信息包括商品名称、选择是否热门、市场价格、商城价格、上传商品图片、选择所属二级分类和编写商品描述这些信息。管理员用户点击“确定”按钮之后客户端将数据提交给服务器,客户端在上传上传组件时必须将上传组件表单type设置为file类型,这样服务器端才能正确的识别。最后服务器端接收到数据之后封装于product对象中,并调用adminProduct_save(product);将新上传的product保存到数据库中的product表中,最后将页面重定向到商品的list.jsp页面。
    主要代码
    product.setPdate(new Date());if (file != null) { String path = request.getServletContext().getRealPath("/products"); String uploadFileName = file.getOriginalFilename(); String fileName = UUIDUtiils.getUUID()+uploadFileName; File diskFile = new File(path + "//" + fileName); product.setImage("products/" + fileName);
    删除商品管理员用户点击“商品管理”来到展示所有商品页面,通过点击页面上的删除按钮即可删除指定的商品。
    设计思路
    这个功能是基于商品的展示页面list.jsp进行开发的,展示用户页面时pageBean里面封装了product的所有信息,当用户在点击“删除”按钮时即向服务器发送请求并携带参数(商品的主键id),服务端在接收到请求之后,根据客户端传来的参数进行删除该商品,最终将页面重定向到商品的展示页面list.jsp.
    jsp页面方法主要代码
    function deletecs(pid) { window.location.href = " ${pageContext.request.contextPath}/ admin/adminProduct_deletecs.action?pid="+pid;
    查询商品管理员通过点击“商品管理”按钮来查看本网站中所有的商品信息。程序运行结果如图4-26所示:

    设计思路
    首先编写商品下面的list.jsp页面,管理员用户在点击“商品管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的商品信息,这里创建了一个pageBean对象用于封装查询出来的数据,包括商品的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为商品个数较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过商品文件夹里面的list.jsp页面右下方的按钮来查看所有的是商品信息。
    主要代码
    // admin的商品管理(查询所有的商品)PageBean<Product> allProPageBean = productService.findAllProduct(page);model.addAttribute("allProPageBean", allProPageBean);
    4.4.5 留言管理模块管理用户通过点击留言管理链接,即可打开前台顾客的留言列表界面,并且可以删除不合时宜的留言信息。程序运行结果如图4-26所示:

    5 系统测试与维护5.1 系统测试环境5.1.1 硬件环境
    CPU:英特尔酷睿四核
    内存:4G

    5.1.2 软件环境
    操作系统:windows 7
    服务器:Tomcat 7
    浏览器:Mozilla Firefox 和chrome

    5.2 系统测试内容使用eclipse编程软件编写Java源程序是遇到语法错误会自动报错,需要及时修改错误。对系统进行测试视为系统能有效运行并且没有异常产生。
    在程序模块编写时,每编写完一个模块需要进行模块单元测试,保证单元模块功能正常,在所有单元测试进行结束之后,需要进行整个系统的集成测试。本系统需要做如下的测试:

    登录注册测试:多次注册用户并且登录。则表达式检验的文本框输入错误信息,检测代码是否可行,注册成功后,检验用户是否可以正常显示,并查看数据库,检验数据是否成功插入。登录时,交叉使用正确和错误的密码进行登录测试,校验是否有异常
    查询一级分类测试:测试当用户访问index.action时,是否可以至系统首页即index.jsp,测试成功
    查询二级分类测试:测试用户在点击首页的一级分类时,系统是否会自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类
    购物车测试:测试已登录的用户是否可以将商品添加到购物车、移除购物车内商品、清空购物车
    订单模块测试:测试是否可以正常生成订单、取消订单、为订单付款

    5.3 系统维护系统维护是为了让系统能够在正常运行的基础上,对系统中的一些小问题进行修复并且不断完善的过程,通过系统维护能够使系统保证在不同的运行环境下均可以正常的工作,各个模块功能正常运行。
    由于本系统的本质就是一个电子商城,所以难免会有很多过期的没用的数据。所以需要定期进行“垃圾”信息的删除,对于系统中重要的一些内容如用户和商品等。要定期对数据库备份,保证数据的正确性。本系统的维护就是为了使本系统能够稳定的运行,所以需要定期维护,并且备份数据。
    小结:本章首先介绍了系统的测试环境,接下来详细介绍了单元模块测试的方法和整体集成测试的主要内容,最后介绍了系统维护的方案。
    6 总结如今,JavaEE是一个非常优秀的企业信息化开发平台,由于其拥有一些很好的性质包括稳定的性能、良好的开发性和非常高的安全性因此被广泛运用于企业级开发。这篇论文基于当前比较流行的电商系统为项目背景,遵循javaEE应用软件的规则进行开发,将系统划分为四个层次包括模型model层,持久层,业务逻辑service层和表现层,并整合了目前在企业中广泛运用的spring、springMvc和myBatis框架进行开发。Spring用于整个系统的统一调度,贯穿于各层之间,springMvc框架着重于mvc模式的实现,myBatis框架完成数据的映射和持久化工作,myBatis的逆向工程极大的方便了dao层的开发,也方便了系统dao层的维护。
    本论文主要完成了以下的任务:

    正确分析了电商目前的发展形势,特别是对网购的发展进行了深入的调查和研究
    深入明确了系统的总体架构,在技术选型上选取了三个主流的框架,对三者的功能,整合做了详细的描述
    系统项目的开发严格遵循软件的开发规范,制定了详细的系统开发步骤,开发之前做了大量的工作包括:需求分析、技术选型、架构设计等
    完成了预期赋予系统的功能的实现

    本文虽然完成了预期研究和目标,但后期还有很多工作需要完成:,随着web应用的快速发展,处于信息时代下会有更多的技术应运而生,不光需要对框架进行深入学习和研究还要对系统的架构进行研究。目前客户端技术正在崛起,我们需要认真做调查和研究做出一能让用户体验度更好的产品。以上只是目前的构想,接下来会继续深入研究并作进一步的完善和设计开发。
    7 参考文献[1] 杨开振等. Java EE互联网轻量级框架整合开发— —SSM框架(Spring MVC+Spring+MyBatis)和Redis实现[M]. 电子工业出版,2017.07.
    [2] 李俊民.HTML 5+CSS 3网页设计经典范例[M].电子工业出版,2010.
    [3] 邹红霆. 基于SSM框架的Web系统研究与应用[J]. 湖南理工学院学报(自科版), 2017, 30(1):39-43.
    [4] 王珊 萨师煊 数据库系统概论[M] 北京:高等教育出版社 2007
    [5] 陈雄华 Spring企业级应用开发详解[M] 北京:电子工业出版社 2009
    [6] 原著施奈德 成栋翻译 电子商务[M] 北京:机械工业出版社 2008
    [7] 阿里巴巴网络技术有限公司 中小企业电子商务之路[M] 北京:清华大学出版社 2007
    [8] 刘克强 电子商务平台建设[M] 北京:人民邮电出版社 2007
    [9] 程杰 大话设计模式[M] 北京:清华大学出版社 2010
    [10] 雷之宇 朱训雨 张麟 JAVA实用组件集[M] 北京:电子工业出版社 2008
    3 评论 103 下载 2019-05-15 16:25:48 下载需要17点积分
  • 基于C++的类UNIX文件系统

    一、题目要求使用一个普通的大文件(如 c:\myDisk.img ,称之为一级文件)模拟 UNIX V6++的一个文件卷,一个文件卷实际上就是一张逻辑磁盘,磁盘中存储的信息以块为单位。每块 512字节。


    磁盘文件结构

    定义自己的磁盘文件结构SuperBlock 结构磁盘 Inode 节点结构,包括:索引结构及逻辑块号到物理块号的映射磁盘 Inode 节点的分配与回收算法设计与实现文件数据区的分配与回收算法设计与实现
    文件目录结构

    目录文件结构目录检索算法的设计与实现
    文件打开结构:选作
    磁盘高速缓存:选作
    文件操作接口

    • void fformat(); 格式化文件卷 • void ls(); 列目录 • int fopen(char *name, int mode); 打开文件 • void fclose(int fd); 关闭文件 • int fread(int fd, char *buffer, int length); 读文件 • int fwrite(int fd, char *buffer, int length);写文件 • int flseek(int fd, int position); 定位文件读写指针 • int fcreat(char *name, int mode); 新建文件 • int fdelete(char *name); 删除文件

    主程序
    初始化文件卷,读入 SuperBlock图形界面或者命令行方式,等待用户输入根据用户不同的输入,返回结果

    二、需求分析根据对题目要求分析和用户使用分析,文件系统采用控制台命令作为输入,按照系统给定的命令即可完成相应的功能。
    控制台的命令应包括如下:
    " man : 手册 \n" " fformat : 格式化 \n" " exit : 正确退出 \n" " mkdir : 新建目录 \n" " cd : 改变目录 \n" " ls : 列出目录及文件 \n" " create : 新建文件 \n" " delete : 删除文件 \n" " open : 打开文件 \n" " close : 关闭文件 \n" " seek : 移动读写指针 \n" " write : 写入文件 \n" " read : 读取文件 \n" " at|autoTest : 自动测试 \n"
    每条命令具体分析如下:
    命令:fformat = "Command : fformat -进行文件系统格式化 \n" "Description : 将整个文件系统进行格式化,即清空所有文件及目录! \n" "Usage : fformat \n" "Parameter : 无 \n" "Usage Demo : fformat \n" ;
    命令:exit = "Command : exit -退出文件系统 \n" "Description : 若要退出程序,最好通过exit命令。此时正常退出会调用析构函数,\n" " : 若有在内存中未更新到磁盘上的缓存会及时更新,保证正确性。若点 \n" " : 击窗口关闭按钮,属于给当前程序发信号强制退出,不会调用析构函 \n" " : 数,未写回部分信息,再次启动时可能出现错误! \n" "Usage : exit \n" "Parameter : 无 \n" "Usage Demo : exit \n" ;
    命令:mkdir = "Command : mkdir -建立目录 \n" "Description : 新建一个目录。若出现错误,会有相应错误提示! \n" "Usage : mkdir <目录名> \n" "Parameter : <目录名> 可以是相对路径,也可以是绝对路径 \n" "Usage Demo : mkdir dirName \n" " mkdir ../dirName \n" " mkdir ../../dirName \n" " mkdir /dirName \n" " mkdir /dir1/dirName \n" "Error Avoided : 目录名过长,目录路径不存在,目录超出根目录等 \n" ;
    命令:ls = "Command : ls -列目录内容 \n" "Description : 列出当前目录中包含的文件名或目录名。若出现错误,会有相应错误提示!\n" "Usage : ls \n" "Parameter : 无 \n" "Usage Demo : ls \n" ;
    命令:cd = "Command : cd -改变当前目录 \n" "Description : 改变当前工作目录。若出现错误,会有相应错误提示! \n" "Usage : cd <目录名> \n" "Parameter : <目录名>默认为当前目录;\n" " <目录名> 可以是相对路径,也可以是绝对路径 \n" "Usage Demo : ls \n" " ls ../dirName \n" " ls ../../dirName \n" " ls /dirName \n" " ls /dir1/dirName \n" "Error Avoided : 目录名过长,目录路径不存在,目录超出根目录等 \n" ;
    命令:create = "Command : create -新建文件 \n" "Description : 新建一个文件。若出现错误,会有相应错误提示! \n" "Usage : create <文件名> <选项> \n" "Parameter : <文件名> 可以包含相对路径或绝对路径 \n" " <选项> -r 只读属性 \n" " <选项> -w 只写属性 \n" " <选项> -rw == -r -w 读写属性 \n" "Usage Demo : create newFileName -rw \n" " create ../newFileName -rw \n" " create ../../newFileName -rw \n" " create /newFileName -rw \n" " create /dir1/newFileName -rw \n" "Error Avoided : 文件名过长,目录路径不存在,目录超出根目录等 \n" ;
    命令:delet = "Command : delete -删除文件 \n" "Description : 删除一个文件。若出现错误,会有相应错误提示! \n" "Usage : delete <文件名> \n" "Parameter : <文件名> 可以包含相对路径或绝对路径 \n" "Usage Demo : delete fileName \n" " delete ../fileName \n" " delete ../../fileName \n" " delete /fileName \n" " delete /dir1/fileName \n" "Error Avoided : 文件名过长,目录路径不存在,目录超出根目录等 \n" ;
    命令:open = "Command : open -打开文件 \n" "Description : 类Unix|Linux函数open,打开一个文件。若要进行文件的读写必须先open。\n" " 若出现错误,会有相应错误提示! \n" "Usage : open <文件名> <选项> \n" "Parameter : <文件名> 可以包含相对路径或绝对路径 \n" " <选项> -r 只读属性 \n" " <选项> -w 只写属性 \n" " <选项> -rw == -r -w 读写属性 \n" "Usage Demo : open fileName -r \n" " open ../fileName -w \n" " open ../../fileName -rw \n" " open /fileName -r -w \n" " open /dir1/fileName -rw \n" "Error Avoided : 文件名过长,目录路径不存在,目录超出根目录等 \n" ;
    命令:close = "Command : close -关闭文件 \n" "Description : 类Unix|Linux函数close,关闭一个文件。可以对已经打开的文件进行关闭\n" " 若出现错误,会有相应错误提示! \n" "Usage : close <file descriptor> \n" "Parameter : <file descriptor> 文件描述符 \n" "Usage Demo : close 1 \n" "Error Avoided : 文件描述符不存在或超出范围 \n" ;
    命令:seek = "Command : seek -写入文件 \n" "Description : 类Unix|Linux函数fseek,写入一个已经打开的文件中。若出现错误,会有相应错误提示! \n" "Usage : seek <file descriptor> <offset> <origin> \n" "Parameter : <file descriptor> open返回的文件描述符 \n" " <offset> 指定从 <origin> 开始的偏移量 可正可负 \n" " <origin> 指定起始位置 可为0(SEEK_SET), 1(SEEK_CUR), 2(SEEK_END) \n" "Usage Demo : seek 1 500 0 \n" "Error Avoided : 文件描述符不存在或超出范围,未正确指定参数 \n" ;
    命令:write = "Command : write -写入文件 \n" "Description : 类Unix|Linux函数write,写入一个已经打开的文件中。若出现错误,会有相应错误提示! \n" "Usage : write <file descriptor> <InFileName> <size> \n" "Parameter : <file descriptor> open返回的文件描述符 \n" " <InFileName> 指定写入内容为文件InFileName中的内容 \n" " <size> 指定写入字节数,大小为 <size> \n" "Usage Demo : write 1 InFileName 123 \n" "Error Avoided : 文件描述符不存在或超出范围,未正确指定参数 \n" ;
    命令:read = "Command : read -读取文件 \n" "Description : 类Unix|Linux函数read,从一个已经打开的文件中读取。若出现错误,会有相应错误提示! \n" "Usage : read <file descriptor> [-o <OutFileName>] <size> \n" "Parameter : <file descriptor> open返回的文件描述符 \n" " [-o <OutFileName>] -o 指定输出方式为文件,文件名为 <OutFileName> 默认为shell \n" " <size> 指定读取字节数,大小为 <size> \n" "Usage Demo : read 1 -o OutFileName 123 \n" " read 1 123 \n" "Error Avoided : 文件描述符不存在或超出范围,未正确指定参数 \n" ;
    命令:autoTest = "Command : autoTest -自动测试 \n" "Description : 帮助测试,在系统启动初期帮助测试。测试不一定所有命令都是正确的,但是系统具有容错性,\n" " : 不会使系统异常。\n" "Usage : autoTest | at \n" "Parameter : 无 \n" "Usage Demo : at \n" ;
    三、概要设计3.1 模块划分经过分析,整个文件系统可以由以下几个部分组成:

    DeviceDriver:设备驱动模块,直接负责磁盘文件直接读写
    BufferManager:高速缓存管理模块,主要负责管理系统中所有的缓存块,包括申请、释放、读写、清空一块缓存的功能函数接口,以及系统退出时刷新所有缓存块
    FileSystem:系统盘块管理模块,主要负责对镜像文件的存储空间管理,包括SuperBlock 空间占用、DiskINode 空间分布、数据块区空间分布的管理。需要提供分配、回收 DiskINode 节点、数据块节点以及格式化磁盘文件的接口
    FileManager:系统文件操作功能实现模块,主要封装文件系统中对文件处理的操作过程,负责对文件系统访问的具体细节。包括打开文件、创建文件、关闭文件、Seek 文件指针、读取文件、写入文件、删除文件等系统功能实现
    OpenFileManager:打开文件管理模块,负责对打开文件的管理,为用户打开文件建立数据结构之间的勾连关系,为用户提供直接操作文件的文件描述符接口
    User:用户操作接口模块,主要将用户的界面执行命令转化为对相应函数的调用,同时对输出进行处理,也包含检查用户输入的正确性与合法性

    3.2 数据结构定义3.2.1 DeviceDriver:设备驱动模块
    3.2.2 BufferManager:高速缓存管理模块

    3.2.3 FileSystem:系统盘块管理模块
    3.2.4 FileManager:系统文件操作功能实现模块
    3.2.5 OpenFileManager:打开文件管理模块

    3.2.6 User:用户操作接口模块
    3.3 数据结构图示3.3.1 磁盘存储空间分布:
    3.3.2 文件索引结构:
    3.3.3 内存文件打开结构:
    3.3.4 高速缓存数据结构:
    3.4 总体流程程序的总体流程为:main 函数等待用户输入,用户输入后,对其命令进行简单解析,然后由命令查找 User 提供的操作接口,将参数交由 User 函数进行处理和判断合法性,若基本符合命令的参数约定,则由User调用FileManager中功能函数实现文件系统的具体功能。而 FileManger 中函数的具体功能则依赖于 FileSystem、BufferManager、OpenFileManager的相关函数接口调用。
    总体流程图如下:

    3.5 模块调用关系下图为模块间调用关系图示:

    四、详细设计4.1 外存磁盘文件管理外存索引节点分配 IAlloc 函数:外存 DiskINode 索引节点采用栈式管理 DiskINode,当需要分配 DiskINode 时,如果 s_ninode 不为 0,则将栈顶节点分配,栈指针减一;否则s_ninode 为 0,说明外存索引节点表中已不包含任何空闲节点,就重新搜索整个 DiskINode区,将找到的 DiskINode 号顺次登入 s_inode 表中,直到该表已满或者已搜索完整个DiskINode 区。

    外存索引节点分释放 IFree 函数:当释放 DiskINode 节点时,如果超级块索引节点表中空闲 DiskINode 数小于 SuperBlock::MAX_NINODE,则将该索引节点编号记入“栈顶”,若其中记录的空闲 DiskINode 已满,则将其散落在磁盘 DiskINode 区中。

    外存空闲盘块分配 Alloc 函数:外存中的空闲盘块采用分组链式索引法进行管理。超级块中的空闲块索引表用栈式管理空闲数据块,但是它最多只能直接管理 MAX_NFREE(100)个空闲块。所有空闲块按照每 MAX_NFREE(100)个进行构成一组,最后一组直接由超级块中的空闲索引表进行管理,其余各组的索引表分别存放在它们下一组第一个盘块的开头中。
    空闲盘块分组链式索引示例:

    分配空闲盘块时,总是从索引表中取其最后一项的值,即 s_free[—s_nfree],相当于出栈,当及时直接管理的最后一个空闲盘块时,就将该盘块的前 404 字节读入超级块的s_nfree 和索引表 s_free 数组中,使得用间接方式管理的下一组变为直接管理。

    4.2 目录搜索和地址变换目录搜索 NameI 函数:将路径名到索引节点转换的过程,与 Unix 执行的目录搜索函数基本类似,流程图如下:

    地址变换 Bmap 函数:将文件逻辑号变换成文件在存储设备的物理块号,与 Unix 执行的 Bmap 函数基本类似,流程图如下:

    4.3 内存高速缓存模拟实现Unix 系统采用自由队列和设备队列进行对缓存块的管理,但是因为本次课程设计项目是模拟 Unix 文件系统,并且整个模拟时串行执行,无并行操作,所以经过考虑,可以将自由队列和设备队列进行合并为一个缓存队列,具体细节如下:
    高速缓存初始化:即构造相应的双向循环链表,初始化成员变量。

    分离一个节点 DetashNode 函数:采用 LRU 算法,每次将第一个节点分离,第一个节点即为过去一段时间最久未使用的节点。

    插入一个节点 InsertTail 函数:采用 LRU 算法,每次将插入的节点放置在缓存队列的最尾部,视为最近使用的缓存节点。

    申请一块缓存 GetBlk 函数:申请一块缓存,将其从缓存队列中取出,用于读写设备块上的 blkno。执行过程为:首先从缓存队列中寻找是否有缓存块的 blkno 为目标 blkno,如有则分离该缓存节点,并返回该节点;没有找到说明缓存队列中没有相应节点为 blkno,需要分离第一个节点,将其从缓存队列中删除。若其带有延迟写标志,则立即写回,清空标志,将缓存 blkno 置为 blkno,返回该缓存块。

    五、调试分析5.1 测试为了方便自己程序调试和老师测试,添加了一个自动测试命令,用于测试二级文件系统容错性和正确性。
    自动测试命令较为完备,对各个环节均有考虑到,自动测试命令序列如下:
    "mkdir /dir1","mkdir dir2","create file1 -rw","create file2 -rw","ls","delete /file2","ls","mkdir /dir1/dir11","create /dir1/file11-rw","cd dir1","ls","cd ..","ls","open file1-rw","write 6 file1-2000.txt 800","seek 6 500 0","read 6 20","seek 6 500 0","read 6-o readOut1.txt 20","seek 6-20 1","read 6 100","close 6","cd dir1","ls","open file11-rw","write 6 file11-100000.txt 100000","seek 6 0 0","read 6 100","read 6 100","seek 6 50000 0","read 6 100"
    测试结果如下:



    5.2 调试中的问题解决问题 1:缓存刷新算法逻辑错误
    经过基本的功能测试后,添加了最后的 exit 命令,由前面介绍的高速缓存模拟知道,在退出时,可能有些缓存块上带有延迟写标记,尚未更新到磁盘文件中,那么在退出时需要调用虚构函数,将 Buffer 中带有延迟写标志的数据块写入到磁盘中,没有细想将缓存队列进行线性扫描写回,错误代码如下:

    调用 exit 命令后引发异常,进行了 NULL 指针的读写访问,经过仔细的逻辑思考,这个代码会造成死循环,并将循环队列尾节点的前后指针置为 NULL,接下来 pb 就变为了 NULL指针,自然就错了。不应进行按照循环队列的次序写回,不应该进行调用 Bwrite 写回。纠错后代码如下:

    问题 2:磁盘物理序号错写为数据分区盘块序号
    在做自动测试的时候,发现小文件测试没有问题,本来想欢欢喜喜以为基本完成了,但是当把文件大小设置大 100000 字节约等于 100KB 文件大小时,就出现了下面的错误:No Sapce left on device!。显然 100KB 大小是绝对可以存储的下的,于是新的问题产生了。

    通过提示来看,不难定位错误位置,通过搜索错误关键词,在 FileSystem.cpp 文件中找到了相应位置。如下红色标记:

    于是开始了问题分析:既然小文件没有问题,说明基本功能是没有问题的,文件大小为100KB 肯定会分配多个磁盘扇区,肯定是相应分配算法没有写对或者磁盘初始化的时候代码有问题,定位到磁盘初始化函数,经过仔细分析,发现将盘块在数据分区中序号写入 s_free表中,但是读取的时候是按照磁盘盘块的物理块号读取,结果就出现了以上问题。

    代码修改为:

    问题 3:分配空闲盘块后清空 Buffer 内容的 Bclear 函数错写
    解决上一个问题后,自以为这下总可以好好写报告了吧,天不遂人愿。测试没有问题,但是进行 exit 命令退出控制台时,控制台卡住几秒,然后磁盘镜像文件莫名变为了 GB 级大小。经过思考,我觉得文件这么大肯定是写入参数异常造成,而整个系统的读写都要通过BufferManager 的 Bread 和 Bwrite 函数进行读写,在函数中加入 debug 函数,打印 Buffer的相关标记信息,结果如下:

    最终的镜像文件变为了 GB 级就是因为这个 blkno 是 GB 大小的 blkno。blkno 发生错误,但是根本不知道是哪一个环节发生错误,那怎么找到错误原因呢?当然需要进一步分析何时这个编号为 45 的 Buffer 中的 blkno 变为了异常值,方法如下:

    我可以在 Bread 函数中进行条件判断,当 blkno 变为 812542311 时,设置断点,查看调用堆栈,调用关系如下:

    发现调用函数为 INode.cpp 中的 WriteI 函数,用同样的方法使函数停下来,然后查看相应局部变量。

    在此函数中进行单步执行,发现是在 Bmap()函数返回时错误,继续在 Bmap 函数中添加代码使之在指定条件停住。

    发现 Buffer 中数据与预期不和,而数据的改变只能是两个地方,一个是初始化写入时不正确,另一个是读入 Buffer 中不正确,仔细看了一下初始化的代码,并没有错误。然后看了 FileSystem.cpp 中 Alloc 分配空闲盘块时会进行清空,看了一下清空的函数,结果大吃一惊,明明要清空整个 Buffer 的内容,偏偏不知道怎么就多了一个 sizeof。

    问题 4:vs 下编译运行正确而 Linux 下出现编译及运行错误
    在 window 下 vs 集成环境下编译正确并且测试也正确之后,觉得交整个工程文件有点庞大,不够简洁,决定自己写一个 Makefile 编译,简洁舒服。但是写好 Makefile 后在 Linux下使用 G++编译就报了错误,错误如下:

    因为在 vs 下指针占用空间为四字节,int 也为四字节,没有问题。但是在 Linux 下的G++编译器中指针占用八字节空间,这样就会报精度损失错误。
    解决方法:将 arg 定义为 long 型数组,这样在 Linux 下大小为 8 字节,在 Window 下long 占用 4 字节。
    解决编译问题后,运行竟然报错了,错误为段错误。

    在 window 下编译运行正确,但是在 Linux 下发生错误,肯定是两者编译器或系统有细微区别,要想找出问题,必须在 Linux 下进行调试,选用工具为 GDB 调试。在编译命令选项中加入-g –rdynamic 可以进行 gdb 调试,调试过程如下:
    进入 GDB 调试,运行命令 r

    运行中会在相应地方报段错误的信号 SIGSEGV,找到是什么函数导致段错误。

    输入GDB命令bt打印当前函数调用栈,得知是在NameI函数中的memcpy调用出现问题。

    再次运行,设置断点为 FileManager.cpp:115 行处,准备进行单步调试查看变量。

    上面设置好断点以后,调试如下:

    发现 unsigned int nindex 这个变量不等于 string::npos 值,大概知道是因为类型转换的问题,于是写了一个测试程序如下:

    在 windows 下编译结果如下:

    同样的代码放在 Linux 下结果却不一样,原因就在这。

    由测试可以知道 Linux 64 位系统下 string::npos 的值为 unsigned long long 型,但是 windows 确是 unsigned int 型。程序错误就是 unsigned long long 截断为 unsigned int型再和 unsigned long long 型比较显然不会是 true,导致后续访问内存越界,程序段错误。更改代码如下,进行强制转换比较即可正确。

    结果验证:

    六、用户使用说明项目结构
    [1453381@sdn os]$ tree.|-- Buffer.cpp |-- Buffer.h |-- BufferManager.cpp |-- BufferManager.h |-- DeviceDriver.cpp |-- DeviceDriver.h |-- file11-100000.txt |-- file1-2000.txt |-- File.cpp |-- File.h |-- FileManager.cpp |-- FileManager.h |-- FileSystem.cpp |-- FileSystem.h|-- INode.cpp|-- INode.h|-- main.cpp|-- Makefile|-- OpenFileManager.cpp|-- OpenFileManager.h|-- readOut1.txt|-- User.cpp|-- User.h|-- Utility.cpp`-- Utility.h0 directories, 25 files
    编译方法
    可以将源程序放在集成环境下编译,也可利用 GNU 编译工具,通过写好的 Makefile 进行编译,make 如下:
    [1453381@sdn os]$ makeg++ -std=c++11 -w -c -o main.o main.cppg++ -std=c++11 -w -c -o Buffer.o Buffer.cppg++ -std=c++11 -w -c -o BufferManager.o BufferManager.cppg++ -std=c++11 -w -c -o DeviceDriver.o DeviceDriver.cppg++ -std=c++11 -w -c -o File.o File.cppg++ -std=c++11 -w -c -o FileManager.o FileManager.cppg++ -std=c++11 -w -c -o FileSystem.o FileSystem.cppg++ -std=c++11 -w -c -o INode.o INode.cppg++ -std=c++11 -w -c -o OpenFileManager.o OpenFileManager.cppg++ -std=c++11 -w -c -o User.o User.cppg++ -std=c++11 -w -c -o Utility.o Utility.cppg++ -o unix-fs main.o Buffer.o BufferManager.o DeviceDriver.o File.oFileManager.o FileSystem.o INode.o OpenFileManager.o User.o Utility.o
    运行说明
    在 Windows 下直接点击生成的 exe 文件执行,在 Linux 平台直接./unix-fs 即可运行。运行界面为控制台的命令行方式,命令较为简单,通俗易懂,初始界面如下:
    ++++++++++++++++++++ Unix 文件系统模拟 ++++++++++++++++++++Command : man -显示在线帮助手册Description : 帮助用户使用相应命令Usage : man [命令]Parameter : [命令] 如下: man : 手册fformat : 格式化exit : 正确退出mkdir : 新建目录cd : 改变目录ls : 列出目录及文件create : 新建文件delete : 删除文件open : 打开文件close : 关闭文件seek : 移动读写指针write : 写入文件read : 读取文件at|autoTest : 自动测试Usage Demo : man mkdir
    若对任何命令有不太清楚的地方,可直接 man [Command]查看详细说明,以 read 命令为例:
    [unix-fs / ]$ man readCommand : read -读取文件Description : 类 Unix|Linux 函数 read,从一个已经打开的文件中读取。若出现错误,会有相应错误提示!Usage : read <file descriptor> [-o <OutFileName>] <size>Parameter : <file descriptor> open 返回的文件描述符[-o <OutFileName>] -o 指 定 输 出 方 式 为 文 件 , 文 件 名 为<OutFileName> 默认为 shell<size> 指定读取字节数,大小为 <size>Usage Demo : read 1 -o OutFileName 123read 1 123Error Avoided : 文件描述符不存在或超出范围,未正确指定参数
    正确退出
    若要退出程序,最好通过 exit 命令。此时正常退出会调用析构函数。若有在内存中未更新到磁盘上的缓存会及时更新,保证正确性。若点 击窗口关闭按钮,属于给当前程序发信号强制退出,不会调用析构函 数,未写回部分信息,再次启动时可能出现错误!
    格式化
    格式化命令为 fformat,运行命令后系统会进行文件系统格式化,然后正常退出,再次进入时为初始环境。
    七、实验总结这学期课程设计很多,操作系统可能是自己花费时间精力最多的课程设计了。付出就有回报,通过本次操作系统课程设计,我觉得无论是系统分析和设计架构的能力,编程语言C++的运用和理解,还是寻找项目代码 bug 的能力,分析错误调试程序的能力都有较大的提升。
    要想使项目的整体规划和模块划分具有较好的合理性,做好需求分析是非常重要的。如果对系统功能要求不够明确,那么便不能很好的开展后续的工作。需求分析脚踏实地了,才能整个项目有一个较好的全局认识,然后在此基础上进行系统架构的设计和模块的划分。具体就是确定好模块的大致功能,模块之间的相互调用关系,每个功能模块类的定义,函数接口的定义,做好这些准备工作,才能一步一步稳扎稳打的实际编程。
    C++语言是建立在 C 语言之上的一门面向对象的语言,虽然从计算机入门到现在个人技术栈一直都是以 C/C++语言为主,语言的语法知识应该比较熟悉了,但是仍从本次课程设计学到不少知识。例如类的静态成员数据是不占用类的大小的,每一个类的占用空间大小是有规则定义,可能同样的成员,定义顺序不一样占用空间的大小是不一样的;不同编译器对C++语法编译规则是有细微差别的,不同操作系统运行一样的标准 C++语法代码也是有着一定区别。
    本次课程设计时间跨度比较大,本来准备先写好操作系统课程设计,写到一半又被其它课程设计和作业无情中断,导致前前后后费时较多。某些模块的小问题在这种来回切换的模式下被遗留忘记,导致后面整体测试时大费周章的寻找错误。不过这样也有好处,不知不觉中提高了自己调试代码的能力,进一步的提升了如何分析错误的原因,快速准确定位 bug所在。
    Unix 系统是现代各类 Unix 操作系统的源头,Unix v6 是非常优秀的系统程序,结构清晰,短小精悍,Unix v6++又用面向对象的思想对其重新进行了设计,并用 C++加以实现。本次课程设计就是仿照 Unix v6++中的文件系统进行改造而来,在这过程中,不免需要通透了解 Unix v6++的设计思想,详细阅读 Unix v6++中的源码,到现在可以说对其文件系统这一块的代码较为熟悉。但是 Unix v6++中的文件系统仅仅是其中的一个子部分,还有进程管理、内存管理、设备管理等模块,对整个 Unix 操作系统的进一步认识还有很长的路程要走。
    八、参考文献[1] 尤晋元,UNIX 操作系统教程[M],西安:电子科技大学出版社,1985 年 6 月
    [2] John Lions,莱昂氏 UNIX 源代码分析[M],机械工业出版社,2006 年 8 月
    [3] 汤小丹、梁红兵等,计算机操作系统[M], 西安:电子科技大学出版社,2013 年 11 月
    [4] Unix v6++源码
    2 评论 36 下载 2018-11-02 23:55:06 下载需要5点积分
  • 基于TCP SOCKET实现的远程聊天系统

    一、实验目的本次实验需要完成一个实时聊天系统。该系统由聊天客户端和聊天服务器组成。客户端即可以给指定客户端发送信息,也可以把消息广播给所有客户端。通过这个实验,使得学生掌握socket API编程。
    二、实验内容该章节将会详细的列出服务器和客户端的功能要求。
    2.1 服务器的功能
    服务器能够并行处理客户端发送过来的消息或者命令
    服务器把从新连接的客户端中收到的第一条消息作为该客户端的用户名称
    服务器能够处理从客户端发送过来的两种类型的信息:

    广播信息,服务器收到信息后将其广播给其他客户端点对点信息,服务器将消息转发给指定客户端
    服务器需要把某个客户端发送的广播聊天信息,广播给和该客户端在同一个频道的所有客户端(但是不包括该用户端自己)这个广播消息的格式应为[<name>]:<message>。其中<name>为发送聊天信息的客户端名称,<message>为该客户端发送的消息
    当某个客户端离线时,服务器需要广播一个离线消息给所有的客户端
    容错处理。当客户端发送的数据和规定的格式不一致时,服务器能够处理这个错误并且返回错误信息

    2.2 客户端的功能
    从服务器返回的消息需要显示在控制台下,并且需要去除末尾多余的空格
    为了区别于其他人发送的消息,客户端自己发送的消息,需要在控制台中以“[me]:”显示

    三、操作环境
    操作系统:Mac OS
    编写语言:Java
    编译软件:Eclipse

    四、问题分析网络编程中两个主要的问题一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定工nternet上的一台主机。而TCP层则提供面向应用的可靠(TCP)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。目前较为流行的网络编程模型是客户机/服务器(C/S)结构。即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。
    两类传输协议:TCP和UDP。TCP是Tranfer Control Protocol 的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket 连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
    UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
    经过慎重的选择,本程序基于TCP传输协议,本人独立完成了整体设计,并部分借鉴了部分教材上使用的架构设计,逐项完成了实验要求的功能。

    五、详细设计5.1 总体设计思路单连接、单线程如果仅仅是客户端与服务器进行通信,则设计较为简单,仅需要在服务器开辟端口建立ServerSocket即可,用死等函数.accept()等待客户端Socket连接,一旦连接成功则在服务器建立Socket对象匹配客户端。具体描述如下:

    用指定的端口实例化一个Seve rSocket对象。服务器就可以用这个端口监听从客户端发来的连接请求
    调用ServerSocket的accept()方法,以在等待连接期间造成阻塞,监听连接从端口上发来的连接请求
    利用accept方法返回的客户端的Socket对象,进行读写I0的操作
    关闭打开的流和Socket对象

    其中,I0操作可以利用Socket提供的getlnputStream和getOutputStream方法得到输入和输出流,为方便起见,可以采用 Buffered Reader/PrintStream封装。

    客户端较为简单,只需要匹配到服务器的’P地址和相应的Port 即可。具体描述如下:

    用服务器的’P地址和端口号实例化Socket对象
    调用connect方法,连接到服务器上
    获得Socket上的流,把流封装进Buffered Reader/Pri ntStrea m的实例,以进行读写
    利用Socket提供的getlnputStream和getOutputStrea m方法,通过旧流对象,向服务器发送数据流

    关闭打开的流和Socket。

    单连接、多线程上述方法一个很致命缺点,这个连接没有开辟多线程,也就是说,服务器必须等待客户端发送来消息后才可以给一个回执消息,客户端操作过程也类似,但我们希望的应该是一个全双工的通信,因此必须开辟多线程。
    开辟多线程的方法很简单,只需要继承Runnable接口即可,然后将I0操作添加至run函数中。

    多连接、多线程现在基本的通讯问题己经解决了,服务器和客户端可以像发短信一样互相全双工的发送信息了,但这还远远不够,因为我们不能是针对两个用户的应用,我们的应用应该可以在服务器转发来自不同用户的消息,并且实现私聊和群聊的区别,因此,我们需要做一个概要设计,之后会详细讲述每部分的内容。
    如图,大体的设计架构如下,总共分为三个包:


    Client包:与客户端相关的一切信息,其中Login类实现客户端到服务器的登陆,Register类实现新用户信息的注册,ChatRoom为聊天主界面,ChatFra m为私聊窗口。
    Server包:完成服务器相关功能实现,FileOpen用于识别登录用户的各项信息,由于时间紧迫,暂未连接数据库,采用的是文本文件存储用户内容,Connection类用于开辟端口等待连接,同样采用多线程技术为每个链接进来的用户开辟线程,并保存所有己连接用户的信息,并保存他们的进程,ChatCu stomer类用于保存连接用户的全部信息,并完成登陆、注册消息的处理以及聊天内容、文件等转发操作。
    Util包:为服务器客户端通用内容,Customer保留了每个登陆用户的信息,Message定义了消息的类别、内容、发送方、接收方以及其他信息,Mtype类定义各种用到的常量。

    Util包具体内容Mtype类定义各种常量,主要分两类:消息类别和IP/Port

    Message类
    如图,主要定义了消息类型、消息内容、发送方、接收方以及其他信息(主要用于文件传送),类中用set函数和get函数为消息赋值和得到消息内容。
    Customer类
    同Message类,主要为得到己连接用户的各项基本信息。
    Server包Connection类由基本的ServerSocket功能扩展而来,主要为并行处理客户端发送过来的消息或者命令,并保存各个连接的客户线程。

    Vector可以更好的处理并发功能,在客户端窗口顶端显示在线的人数。

    采用多线程,并行处理多个连接。并可以返回在线用户列表。
    ChartCustomer类该类主要是处理每个连接到服务器的客户端线程。
    根据发送来的消息,可以分为:登陆消息、离线消息、注册消息、普通聊天消息、文件传送消息,以及应对错误错误消息格式的反馈。在此,如果一个线程断开,认为该用户已离线,发出离线消息给所有用户。

    对于每个消息,服务器都会解析消息的具体内容,对于登录的用户,需要判断该账号是否己经在线、用户名密码是否正确,如果成功登陆则为该用户保留线程资源的同时发送该用户上线的消息给所有在线用户;对于注册用户,注册时需要判断用户名是否己存在,存在则返回注册失败的消息,否则保留该用户的资料;处理文件消息和聊天消息在服务器端是相同的,只需要判断是发送给所有用户的还是发送给单独用户得即可,在服务器实现转发功能。

    FileOpen类保存用户资料。

    Client类由于此部分代码多为界面设计,在此不一一罗列。
    Login类登陆界面,输入用户名密码登陆,登录成功会显示聊天主界面,登录失败会返回失败原因
    Register类用户注册界面,注册失败会予以反馈。
    ChartRoom类聊天主界面,可选择在线用户进行私聊或广播消息,同样可以给用户传送文件或给所有用户群发文件。
    在系统消息一栏,用于显示各种系统消息,如:用户上线、下线提醒,新消息通知、文件传送提醒等。
    ChatFrame类类似腾讯00的聊天界面,可以从本地同步聊天记录,并允许发送消息、接收消息。
    六、测试登录界面

    聊天室主界面

    可以实现私聊功能

    可以实现广播功能

    可以实现文件传送

    离线有提醒
    3 评论 30 下载 2018-11-05 11:58:38 下载需要7点积分
  • 基于java web的台球厅管理系统的设计与实现

    摘 要随着科学技术的不断提高,软件工程技术日渐成熟,它已进入人类社会的各个领域并发挥着越来越重要的作用。台球厅管理系统的设计与实现与台球桌计费功能给人们带来了很大的便捷,传统的台球厅管理耗费人力物力繁重,效率也不高。因此我开发了这个台球厅管理系统的设计与实现来管理台球厅中的各类事务。
    本文从信息系统分析的角度详细讲述了台球厅管理系统的设计与实现的开发过程。全文共分五章,首先介绍了系统的开发背景以及课题意义,并对系统进行了详细的可行性分析,然后,按照软件的开发步骤,从台球厅管理系统的设计与实现的需求分析到总体设计到详细设计详细阐述了系统的功能实现过程。
    关键字:台球厅;Mysql;javaweb

    ABSTRACTABSTRACT With the continuous improvement of science and technology, computer science and technology matures, its powerful features have deep understanding for the people, it entered the human society each domain and is playing an increasingly important role. Room the design and implementation of a billing system is closely related to the cultivation of the room pricing, the traditional pattern of room the design and implementation of a billing system mechanical hard, quality is not high also. So we developed the room the design and implementation of a billing system to manage documents.
    In this paper, from the Angle of information system analysis, detailed tells the room the design and implementation of a billing system development process. The full text is divided into six chapters, first introduced the system development background and topic meaning, and feasibility analysis of the system in detail including software development tools for Mysql and JAVA working principle in detail, and then, according to the software development steps, from the room the design and implementation of a billing system requirements analysis to the overall design and detailed design process of the realization of the function of the system is expounded in detail. Finally, the system has carried on the special test function, high degree of humanization, reflects the system management characteristics of efficient and maintainable.
    Key Words: billiard; Mysql; Java
    一、前言近年来随着社会的发展,生活水平的提高,越来越多的人们注重自己的精神娱乐生活,随着台球厅规模的不断扩大,台球厅收费的数量也相应的增加,面对着庞大的信息量,传统的人工方式管理会导致收费管理的混乱,人力和物力过多浪费,导致不必要的浪费。因此,必须指定一套合理,有效,规范和实用的台球厅计时收费系统,对计时收费进行集中统一的管理,因此需要有台球厅计时收费系统来帮助管理台球厅的计时收费信息,以便提高管理的工作效率。
    台球厅的管理问题是一个迫在眉睫的问题。现在的人们越来越喜欢在闲暇的时间打台球放松自己,为了实现更现代化的管理以及节约人力资本和资源,建立一套完善的台球厅管理系统是一个明智的选择。
    台球厅管理系统是典型的信息管理系统,其开发主要包括后台数据库的建立和维护以及前端网站的开发两个方面。对于前者要求建立起资料一致性和完整性强、资料安全性好的库。而对于后者则要求网站功能完备,易使用等特点。台球厅管理系统是一个台球厅信息化管理的重要组成部分,不但能实台球厅日常状况查询,同时也为台球厅管理者简便快捷的管理方式,使管理者轻松管理台球厅设备及收费项目。
    当今,越来越多的台球厅管理系统的设计与实现话题走进了我们的生活,。然而传统的台球厅管理系统的设计与实现不仅模式单一,内容也少,所以我们认为台球厅管理系统的设计与实现也可以通过网络来达到想要的效果。所以我们打算开发 “台球厅管理系统的设计与实现”。台球厅管理系统的设计与实现是集管理、经营、服务为一体的有偿服务劳动,是台球厅管理系统的设计与实现社会化、专业化、台球厅管理系统的设计与实现现代化发展的有效途径。计算机和网络方面越来越普及的时代已经到了,普通的台球厅管理系统的设计与实现管理效率低,已经出现疲态,所以利用网络来搭建一个台球厅管理系统的设计与实现既符合时代潮流又能为社会的知识企业带来很多利益,在学习java知识,正可以用到开发网站上面,从理论层次过渡到实践方面,从书本走到生活,提高自己的编程能力,所以创建一个台球厅管理系统的设计与实现对自己很有意义。
    二、概述2.1 系统说明目前,网络台球厅管理系统的设计可以分为传统的台球厅管理系统的设计与实现平台软件和网络版的台球厅管理系统的设计与实现软件两种。
    第二类是2000年以后的开发语言开发的系统,这一类的系统一般在技术方面都比较先进一些。
    从功能上讲,台球厅管理系统的设计与实现软件主要分为几个层次:
    功能全面,系统界面条例清晰明了,方便管理。
    应用B/S架构的台球厅管理系统的设计与实现管理软件,这一类产品在台球厅管理系统的设计与实现管理软件行业比较少,因为台球厅管理系统的设计与实现行业不同于别的行业,他在管理的时候数据的浏览量相当大,运算量也比较大,并且客户的需求千变万化,个性话的设置比较多,因此,B/S的网页形式的台球厅管理系统的设计与实现管理软件在应用时有一定的局限性。
    应用html语言,所开发出来的系统支持互联网直连,并且由于开发语言比较先进,所做出来的系统界面比较美观,技术实力强的公司的产品功能也比较灵活,模块也比较丰富,这一类的产品的功能也比较深入细致,更加人性化。这样的集中式应用的系统能更好的满足大中高中学校的统一管控的管理模式,因为支持互联网直连,所以不受地域的限制,并且这一类的系统一般都是整体解决方案,功能涉及到网络企业,这一类产品也是台球厅管理系统的设计与实现的发展方向。
    2.2 系统特点
    本系统完全基于Java web技术,只要有一台电脑并且能联网就可以浏览本网站
    采用html技术和MYSQL数据库开发,具有代码易懂,可扩展性高,性能高、数据安全等特点
    可以完全通过网页登录管理系统,维护方便
    各个功能模块独立性强,可以根据实际情况任意组合
    具有清新简洁方便且易懂的界面,操作简单
    支持所有的Windows系列操作系统以及移动终端网页访问

    2.3 系统功能简介完成“台球厅管理系统的设计与实现”的设计,台球厅管理系统的设计与实现是一个适应于所有具有基本台球桌计费需求的企业的管理系统,本系统初步拟定由管理员模块组成。
    管理员模块有会员管理,台球桌管理几大功能。
    本台球桌计费要实现的是对台球桌计费所需要的基本功能,采用了较为简单的spring+springmvc+mybatis框架开发技术。Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
    另外,本台球桌计费采用了免费开源的Java集成开发工具——Eclipse开发平台,免费开源的数据库——Mysql关系型数据库,免费开源的Web应用服务器——Tomcat服务器,由Eclipse、 Mysql 和Tomcat这三个软件组合并构建成一个相当优越的开发环境。
    在开发技术和开发环境的确立以后,就要对本文档系统原型进行构建和对数据库进行设计,待系统原型和数据库这两方面的工作完成后,就根据需求对系统原型和数据库加以扩充和完善,直至本文档系统可以交付使用。 顾客客户端:操作系统windows98以上,浏览器IE5.0以上。
    条件与限制:开发本系统所用到的软件有: Eclipse,Mysql。
    三、总体设计3.1 开发背景随着我国科技和市场的快速发展,人们的生活速度不断提高,管理者对台球厅管理系统的设计与实现提升的要求也越来越高,台球厅管理系统的设计与实现已成为台球厅管理系统的设计与实现管理信息管理的首选,普通的人工台球厅管理不能满足用户的需求,浪费时间和财力,管理效率也十分低下。如何利用先进的管理手段,提高台球厅管理系统的设计与实现管理水平,是如今台球厅管理系统的设计与实现改革面临的一个重要瓶颈。要想提高管理水平,必须全方位地提高使用体验。只有高标准、高质量的台球厅管理系统的设计与实现管理信息服务才能满足社会的需求。如今计算机科学技术日渐成熟,功能越来越强大,已完全能够胜任台球厅管理系统的设计与实现管理信息管理平台工作,而且更加方便、准确、快捷、高效、清晰、透明。这将给台球厅管理系统的设计与实现管理带来很大的方便,从而给台球厅管理系统的设计与实现管理信息管理工作带来更高的效率,这也是台球厅管理系统的设计与实现管理信息管理正规化、现代化的重要标志。
    台球厅管理系统的设计与实现是一个新兴行业,台球厅管理系统的设计与实现市场非常庞大,并且有着巨大的增长空间。
    现如今,台球厅管理系统的设计与实现在一些发达国家和地区早已经形成一个独立的产业,信息与科技的结合式管理是社会管理的重要管理模式,无论在国内还是国外,都已经取得了迅速全面的发展,台球厅管理系统的设计与实现管理信息管理的开发,使管理越来越智能化与人性化。
    从功能上讲,台球厅管理系统的设计与实现软件主要分为几个层次:
    功能全面,系统界面条例清晰明了,方便管理。
    应用B/S架构的台球厅管理系统的设计与实现管理软件,这一类产品在台球厅管理系统的设计与实现管理软件行业比较少,因为台球厅管理系统的设计与实现行业不同于别的行业,他在管理的时候数据的浏览量相当大,运算量也比较大,并且客户的需求千变万化,个性话的设置比较多,因此,B/S的网页形式的台球厅管理系统的设计与实现管理软件在应用时有一定的局限性。
    3.2 功能分析完成“台球厅管理系统的设计与实现”的设计,台球厅管理系统的设计与实现是一个适应于所有具有基本台球桌计费需求的企业的管理系统,本系统初步拟定由以下两个模块组成。管理员可以登录系统后对会员模块进行查询会员信息,充值,消费,会员信息修改,会员信息删除,新增会员,几个功能。管理员可以登录系统后对台球桌模块进行订台,计时,结算等操作。
    3.3 数据流图
    在本系统中,用户管理模块的功能比较简单。在系统初始化时,有一个默认的“系统管理员”用户Admin,由我手动添加到数据库中。Admin用户可以管理其他的会员信息,台球桌信息等。管理员可以对会员进行增加,删除,修改,查找,充值,扣费等操作。管理员还可以对台球桌进行操作,如观察台球桌的使用和空闲状态,订台服务,结算服务等。
    四、数据库设计4.1 数据表的介绍本系统数据库的功能主要是存储网站中所有数据,以便进行操作。
    本系统数据库采用MYSQL数据库,系统数据库名称为billiard.

    本数据库共分为三个表:

    Account表:该表存放的是会员的姓名,身份证号和账户余额的信息
    Admin表:该表存放的是管理员的账户和密码
    Billiard_table表:该表存放的是台球桌的使用状态和开始使用时间和结束使用时间

    4.2 MyBatis框架的应用MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
    MyBatis框架的特点:

    简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现
    灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求
    解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性
    提供映射标签,支持对象与数据库的orm字段关系映射
    提供对象关系映射标签,支持对象关系组建维护
    提供xml标签,支持编写动态sql

    我们把Mybatis的功能架构分为三层:

    API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
    数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作
    基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑

    五、详细设计互联网的兴起从本质上改变了整个社会的管理方式,国内从上个世纪90年代互联网兴起之时,就产生了通过网络进行台球厅管理系统的设计与实现的想法。但是由于在技术不成熟等一系列的原因,限制了台球厅管理系统的设计与实现的开发步伐。进入21世纪以后,随着整个社会的发展、进步,制约台球厅管理系统的设计与实现的各个问题逐一被解决,各企业机构也纷纷的加入到台球厅管理系统的设计与实现的洪潮之中。
    除了台球厅管理系统的设计与实现管理信息管理场所的改变以外,更重要的是大大改变了传统的台球厅管理系统的设计与实现管理信息管理行为习惯,无论是否在台球厅管理系统的设计与实现,网上查询台球厅管理系统的设计与实现管理信息管理信息的相关信息,已经成为台球厅管理系统的设计与实现环节的重要组成部分,这一环节对台球厅管理系统的设计与实现管理信息管理行为的实际发生起到了至关重要的指导作用。
    5.1 系统登陆模块下图5.1所示的界面是基于B/S模式的台球厅管理系统的设计与实现的首页。

    5.2 管理员管理会员管理界面
    该模块可对会员进行管理,包括增加会员,删除会员,进行充值,扣费,信息修改等功能
    5.3 管理员管理台球桌界面
    该模块有预定台球桌的功能,还有根据消费时间计算出消费金额的功能。
    六、总结本次毕业设计查阅了许多有关普通用户台球厅管理系统的设计与实现管理系统管理信息系统的资料,翻阅了许多书籍,结合自己的经验,详细调查了普通用户台球厅管理系统的设计与实现管理的工作内容与细节,开发设计了这个台球厅管理系统的设计与实现。
    在系统的开发过程中,运用到了B/S三层结构技术和自己在平时学习中掌握的一些技术,通过这些技术的实现,整个系统的性能得到了大大的提高。这些技术都在论文中做了比较详细的介绍。本系统还存在许多的缺陷和不足之处,比如很多细节上做的还不行,有些功能模块还应再加强。希望在以后的时间里,我可以把这些缺陷都弥补过来,进一步完善系统。
    本系统由于时间和技术条件的限制,还存在一些不足之处,有些功能还需要改进,还应该做进一步的系统调查需求分析工作,更深入的完善系统。总之,一个紧跟时代步伐的真正使用的软件必需有一个不断完善改进的过程。
    参考文献[1] 徐建波主编.《Internet与Web设计教程》 .中国矿业大学出版社 .2011
    [2] 贺振增JAVA WEB开发.清华大学出版社.2014
    [3] 武晓军、陈海滨编著.Javascript/VBScript网页编程实例解析.清华大学出版社.2011
    [4] 张海藩. 软件工程[M]. 北京: 人民邮电出版社 2012.
    [5] 龚玉清.网页设计的色彩运用. 现代台球厅管理系统的设计与实现管理信息管理技术2013, 5.
    2 评论 13 下载 2019-11-23 10:37:44 下载需要17点积分
  • 基于JAVA WEB和MYSQL数据库实现的大学图书馆管理系统APP

    一、系统开发目的几年前的web2.0时代给我们带来的冲击还在扩大。紧接着的 iPhone 和 Android 平板电脑的日益流行,使得我们可以用一种很轻松的手势,触摸,语言等方式与互联网交互。根据调查显示,移动设备的占有率会在几年后超过传统pc,Windows在2012年9月推出的最新Windows8系统也第一次把触控功能带到了Windows系统,这不可谓是一种趋势:互联网已经逐渐靠着移动终端发展。此外,HTML5的日益规范化,其在各种平台上都得到了较好的支持。这些现象,构成了本次系统的开发目的:打造一个移动客户端。
    二、设计内容设计一个模仿大学图书馆的移动客户端与一个使用MySQL数据库的服务端。
    三、设计要求要求本客户端实现的基本功能如下:

    读者的登陆,注册。
    读者的查询图书。
    读者的预约图书。
    读者的借阅图书。
    读者的还书。
    读者的借阅图书超期的罚款。
    有合理的异常处理机制将出错友善的告诉读者出错在哪。
    管理员对图书,用户的基本管理。

    四、设计平台客户端使用HTML5,JavaScript,css3加上jQuery Mobile搭建,除了可以在web浏览器上访问外,也可以转换为Android,ios,Windows phone等平台上的原生app应用。
    服务端使用Java平台开发,使用MySQL作为底层数据库。除此之外,还应用了多种技术开发,所有的技术都是目前工业界成熟的,流行的,稳定的。
    开发环境为:Windows 8、jdk1.7_10、MySQL_5.5.29、eclipse_3.7
    五、技术路线本次系统服务端所用到的技术列在下面,由于使用maven作为项目管理,故直接把项目所用到的核心依赖及其版本号以maven定义的xml列在下面:
    <java.version>1.7</java.version><spring.version>3.2.0.RELEASE</spring.version><freemarker.version>2.3.19</freemarker.version><hibernate.version>4.1.9.Final</hibernate.version><logback.version>1.0.9</logback.version><servlet-api.version>3.0.1</servlet-api.version><mysql.jdbc.version>5.1.22</mysql.jdbc.version><json.version>20090211</json.version><jetty.version>8.1.8.v20121106</jetty.version>
    其中,java使用的是jdk7的最新版本,使用spring提供的依赖注入,控制反转以及数据库的声明式事务管理给应用程序提供更好的灵活性与解耦性与安全性。此外,web层也使用了spring mvc提供的mvc机制来处理用户的请求与返回相应的视图,对于视图层,使用了freemarker的模版引擎技术来动态的生成视图文件返回到客户端,除了单一的请求,应用也提供了能够Json数据的Ajax的请求方式,使得应用程序更简单,更高效。
    另外,本次数据库课程设计的核心,数据层由于一些原因被弱化了(原因见后面),所以使用了hibernate的orm技术,对象关系映射来处理数据库的访问,在比较大的程度上简化了数据库的代码量(当然,功能是实现了的),spring的事务管理也得到非常好的应用。MySQL数据库无须多说,jdbc也是最新版本的。
    Webserver使用jetty嵌入式服务器,轻量型,但是非常强大。
    至于本次系统的客户端,使用的事最新的HTML5,css3,与JavaScript,这些也都无需赘言。
    整个项目使用非常流行和成熟的maven管理,开发,构建,测试,集成,部署一应俱全,非常的方便。
    1 需求分析本次课程设计的设计内容是设计一个关于数据库系统原理的图书馆系统。通过自己在西大图书馆的经历,模拟出其应有的功能,用rose画出的用例图如下:
    当读者想要借阅的书已经全部被借走时,用户可以预约这本书,当该书归还后,用户可以有优先权去借阅。预约有效时间为30天。过期不侯,并且当有多个读者共同预约同一本书时,依照先到先得的策略分配借阅优先权。用户有效的最大预约书本数量为10本。并且有欠款未缴付的不予预约。

    详细说明如下:

    注册:用户只有经过注册认证后才能享有图书馆提供的服务,注册必须提供正确的个人信息,否则不予通过注册
    登陆:注册认证后的用户唯有经过登陆认证后才能在网上享受服务
    修改信息:登陆后的读者可以更新自己个人信息
    注销:当用户想要安全退出时,提供这个方法保护用户的个人信息不被他人窃取
    预约图书:当读者想要借阅的书已经全部被借走时,用户可以预约这本书,当该书归还后,用户可以有优先权去借阅。预约有效时间为30天。过期不侯,并且当有多个读者共同预约同一本书时,依照先到先得的策略分配借阅优先权。用户有效的最大预约书本数量为10本。并且有欠款未缴付的不予预约
    借阅图书:认证的读者可以借阅图书。最长的借阅时间为30天,每位读者最大借阅数量为10本。超过之后予以罚款,每本书每天0.1元。借阅的规则如下:

    若读者有欠款未缴付,不予若读者达到了借书数量最大值,不予若该书被预约并且该读者未预约,不予
    归还图书:读者借阅的书籍必须按时归还,否者将会按照每本书每日0.1元处以罚款。更严重的,将加以法律追究!书本归还之后,将对该书的预约信息进行更新
    缴付图书欠款:当读者由于超出还书期限时,图书馆将冻结其一些操作。读者惟有缴付欠款才能得到相应的服务
    读者可以对图书进行查询,按关键字,复杂,或者简单,然后图书馆返回相应的结果
    查询图书:按关键字,复杂,或者简单,然后图书馆返回相应的结果

    此外,还设置了一些基本的管理员的功能,由于重点没有放在管理员处,故这里的用例较少也较为简单。管理员用例如下:

    详细说明如下:

    图书管理:简单地获取图书列表(含分页),查看图书信息,修改图书信息,以及添加图书
    类别管理:简单地获取类别列表(含分页),查看类别信息,修改类别信息,以及添加类别
    读者管理:简单地获取读者列表(含分页),查看读者信息

    2 概念结构设计2.1 实体关系图2.1.1 实体关系类图(用rose画出)
    2.1.2 数据库表结构关系图(用navicat画出)
    2.1.3 关系模型
    Category(类别):id(主键,自增),name,description,includeDate(录入日期)
    Book(图书):id(主键,自增),title,author,category_id(外键,关联Category 的id字段,多对一关系),publishHouse,publishDate,ISBN,price,borrowedTimes,bookedTimes,clickTimes,clickTimes,remain(剩余图书数量),description,lendable(是否可借,默认true),includedDate(录入日期),image,url(链接信息)
    Reader(读者):id(主键,自增),name,nick,age,sex,account,password,idCard,email,address,loginTimes(登陆次数),registerTime(注册日期),lastLoginTime(上次登录时间)
    BookingInfo(预约信息):id(主键,自增),reader_id(预约的读者,外键,关联读者的主键id),book_id(预约的图书,外键,关联图书的主键id),bookDate,cancel(是否取消), deal(预约是否成功)
    LendInfo(借书信息):id(主键,自增),reader_id(借书读者,外键,关键读者的主键id),book_id(借阅的图书,外键,关联图书的主键id),lend_date,returnDate(还书日期,默认为空),charge(是否有罚款,默认为false)
    Admin(管理员):id(主键,自增),username,password,last_login_time

    3 逻辑结构设计3.1 数据库表结构3.1.1 Category
    3.1.2 Book
    3.1.3 Reader
    主键:ppt_Id
    外键:ppt_ItemId 参照ppt_Item的ppt_ItemId;Variety_ID 参照 Variety 的 Variety_ID


    3.1.4 lend_info 预约信息
    3.1.5 booking_info 预约信息
    3.1.6 charge_info 罚款信息表
    3.1.7 admin
    4 系统实现与测试本系统使用经典的mvc(model,view,controller)思想,配以先进流行的技术来实现,以面向接口来驱动开发。测试使用了JUnit单元测试,所有的核心接口都通过了JUnit单元测试。
    4.1 类图的组织层次
    这是一个典型了maven管理的项目,简单地描述一下包图的构造:

    src/main/java java主程序放置目录

    config: 这里放置了一些配置文件的java类controller:这里放置的是控制器类,用来处理客户端的请求并返回给对应的视图entity:实体类,与数据库里的表一一对应interceptor:拦截器类,拦截没有权限的用户非法进入某些页面repository:数据访问接口类,这里定义了各个实体类相关处理数据访问的接口,子impl包有对应的实现类service:对外服务接口,这里定义了系统对于客户端提供的服务,子包impl有其实现util:工具类,提供一些工具方法,比如异常,时间处理等org.json:这个是使用json.org官方提供的处理json数据的一组类
    src/main/resources 应用程序资源文件 放置了一些配置文件,比如logback的日记记录配置文件等
    src/test/java java JUint测试类放置目录,这里对数据访问接口和对外接口进行了测试
    src/test/resources 测试时提供的资源文件放置目录src/main/webapp web应用程序文件放置目录,包括web配置文件,视图文件,spring配置文件还有html,css,JavaScript,图片资源等文件

    4.2 数据访问层接口(ROSE画出)
    4.3 对外服务接口
    4.4 以一个例子来具体描述功能的实现通过如前所述定义的数据访问层和对外服务层的接口,根据需求分析中的说明分别写好接口的实现。在对外服务层中调用数据访问层的接口,再在控制器通过调用对外服务层来对客户端的读者提供服务,返回相应的视图,这就是这个系统的设计模式。接口与实现相分离,即方便了代码的编写与测试,又增加了代码的优雅性,利于日后的维护与扩展。
    在这里我们通过一个用例来看看整个系统是如何交互的,使用rose画的图,以还书为例。
    其需求如下:读者借阅的书籍必须按时归还,否者将会按照每本书每日0.1元处以罚款。更严重的,将加以法律追究!书本归还之后,将对该书的预约信息进行更新。
    对应的活动图:

    对应的序列图如下:

    这个序列图是调用接口的,具体实现没有来得及画,可能会有点问题,但是无碍我们来看还书的过程各个对象见是如何调用的。由于序列图可以转换成交互图,所以这里就不画了。另外,通过这个用例的实现,也可以大致看出整个系统的实现概况。所以,整个系统的实现就介绍到这里,完整的uml图和源代码见附录。
    4.5 客户端试图展现客户端各个页面的实现原理很简单,就是通过移动设备采用触摸手势来与服务端进行交互。读者(管理员)通过触控来传递请求,服务端通过对外服务接口再调用数据访问接口处理请求后返回相应的视图文件,若出了错,就会跳转到错误页面,给予用户相应的提示。
    4.5.1 首页界面(登陆页面)
    4.5.2 注册页面
    4.5.3 登陆成功后的主页
    4.5.4 搜索结果页面(就在刚才那个页面,我们选择通过书名)
    4.5.5 查看修改个人信息
    4.5.6 通过类别获取相应类别的图书
    4.5.7 点击查看图书的信息
    4.5.8 预约图书
    功能及原理:当读者触摸预约按钮时,请求就会发送到服务段,控制器收到请求交给服务接口,但是实现原理里面对预约有这样的要求,如果书还有未借的,那么预约就会失败。所以将错误信息试图返回到了客户端。(类似的,错误处理在系统中大量出现,保障了系统的稳定性),碍于篇幅以及其他,其他的错误提示就不截图了。
    4.5.9 借阅图书
    功能及原理:由于我没有欠款,也没有借满10本书,之前也没有借阅过这本书,而且这本书也没有被人预约,所以我能借阅这本书。(这个是成功的试图,返回了一条成功的信息,其他的成功信息也类似,不再附图)。
    4.5.10 个人中心
    这里使用了json数据请求,是一个亮点,可以在一个试图上以异步请求的方式在同一个试图(不需要切换试图)动态加载数据,比如,读者触摸我的借阅信息时:

    点击查看更多,则会再次通过异步请求获取数据在动态的加载到当前页面,不再赘述。
    同时,我们在这里也可以看到相关的信息,比如说书未归还,有欠款,取消预约信息等,取取消预约图书为例:

    触摸取消预约按钮后,则会出现相应的成功试图,与前类似,不再赘述。
    4.6 后台管理管理员这层不是我此次的重点,原理也类似,代码也差不多,就连拦截器也是几乎一样,所以,这里就简单的展现几个试图吧。
    4.6.1 管理员管理首页
    4.6.2 增加书籍
    4.6.3 查看图书列表
    4.6.4 其他管理员的其他操作大致一样,其实现原理也如前,这里就不截图了。细节太多,事无巨细,最好的办法就是亲自去体验,截图太累,排版太麻烦。
    5 优缺点自我评价本次数据库项目其实做了两次,这是第二次了,第一次将近做好了,但是在年底被舍友给把整个硬盘删除了,可以没找回来。很郁闷,于是就有了第二次(这次吸取教训,使用git来做为版本控制工具)。第一次和第二次的差别在于第一次是使用原声的jdbc操作数据库语句,视图使用传统的web页面。第二次,也就是这一次,出于快刀斩乱麻的原因,使用了hibernate这个开源的orm框架来与数据库层打交道,减轻了一部分代买量。另外,第二次也在视图层使用了适合于移动终端的视图展现,通过触摸来实现交互,还挺漂亮的挺方便的。
    本次数据库设计,我个人淡化了数据库在整个系统中的出镜率。虽然可能有些不符合数据库课程设计这个名字。但是,个人觉得,数据库固然重要,但是它应该也无可争议作为应用程序的最底层,底层的东西,是高层东西的基石,但是底层的东西就是传统的sql语句之类,在应用程序中代码大多都类似,过度强调还不如直接在控制台写数据库语句来得直接,所以,我这篇报告写得可能有点四不像吧,既不像数据库,也不像软件工程,像个大杂烩,不过这其中体现的思想和方法确实也是我学习和实践的收获。
    本次课程设计,采用了很多当前工业界流行的,最新的技术,完全可以作为一个showcase来展现,一开始写就打算把它共享,或者说开源吧,所以风格代码写的非常规范,也有点刻意的取使用某些面向对象的设计模式,封装等思想,目的是想从这个项目中传达一种思想之类的吧。毕竟,感觉周围的人还欠火候。大量的注释带来的好处就是生产的javadoc文档,省去了很多敲击。最后,这个项目使用uml类图类建模,现学现卖,感觉帮助挺大的。
    整个项目使用到的平台技术,框架,第三方类库都是免费和开源的,没有一分钱的花费,这个比起sqlserver要好一些吧。
    至于优缺点,我觉得优点就是在于一个“新”字,这个项目可以跨平台的运行在各种移动设备上,甚至,还可以转换为相应平台(Android,ios)上的原声app。对于性能和安全都有考虑(具体见附录)不过这个是后话了。
    说一下自己感觉的缺点

    由于使用了太多的技术,编写的代码量比较多,对于这个简单的系统,甚至有些过了 ,造成了一定的复杂
    控制器没有完善,写得不是很合理,get,post方法没有连接好
    没有使用原生的jdbc和sql来操作数据库,弱化了sql ,性能上也有减弱
    题材不够新,很多人是写图书馆系统,这个就显得不够新了。但是这个是完全模仿西大图书馆的用例,作为学生,作为读者,也希望能有图书馆的移动客户端出现
    图书馆的续借功能忘记了,没有实现
    管理员模块较为简单
    没有对外提供删除的功能,虽然程序有设置。(ps:数据库一般应该是少量的删除与大量的查询,我就懒得没有提供删除的接口了)。但是从数据库设计的角度来说是不对的
    出于时间问题,代码没有经过大量的测试,某些地方人存在问题
    在写报告时,太多的截图了
    1 评论 48 下载 2018-11-23 18:00:54 下载需要11点积分
  • 基于Java和Sql Server 2000实现的学生选课管理系统

    一、课程设计任务完成学生选课管理系统的开发。
    二、需求描述本系统是一个单机版的小型的学生选课管理系统,在本系统中,开发了一个面向管理员、学生和教师这三个对象的教务平台,对学生提供的服务有登录、选课、、修改登录密码、和查询成绩这几个服务,所选课程总数不能超过3门;对教师提供的服务有登录、修改登录密码和登录成绩;对管理员提供的服务有登录开设学生和教师帐号、删除学生和教师帐号的服务。
    三、系统总体设计3.1 系统架构设计
    架构

    单机
    运行软件环境

    windows XP SP3jdk1.6
    开发环境

    硬件平台
    CPU:P41.8GHz内存:256MB以上
    软件平台:windows XP SP3 、jdk1.6
    操作系统:WindowsXP数据库:SQL Server 2000、SQLServer SP4补丁开发工具:Eclipse 3.3分辨率:1024*768


    3.2 功能模块设计
    各模块功能:

    登录界面:登录界面是有帐号,密码两个JTextField,管理员帐号一字母A开头,教师帐号一字母T开头,学生帐号以字母S开头,登录帐号或密码输入错误会弹出相应的提示对话框
    学生信息管理模块:管理员用于添加和删除学生信息的模块
    教师信息管理模块:管理员用于添加和删除教师信息的模块
    教师密码修改模块和学生密码修改模块:管理员添加的用户帐号的初始密码与用户的帐号相同,用户通过密码修改模块可以自己需改密码
    教师录入成绩模块:教师可以浏览选修自己课程的学生的信息并且录入该学生的成绩
    学生选择选修课模块:该模块通过表格的形式将所有课程列出来,学生可以根据个人兴趣选择不同的课程,每个学生选择的课程数目不能超过3门,而且不能重复选课,否则会弹出对话框,提示用户查看已经选择了的课程
    学生查询成绩模块:通过表格的形式将该学生选择了的课程列出来,如果教师有录入成绩,则可以看到自己的课程成绩

    3.3 数据库设计E-R图

    关系模式

    学生(学生学号,学生姓名,教师性别,教师生日,所在班级)
    教师(教师编号,教师姓名,教师性别,教师生日,教师职称,所在院系)
    课程(课程号,课程名,学分,选课人数)
    选课(课程号,学生学号,成绩)
    授课(课程号,教师编号,上课地点)

    数据库管理系统
    Microsoft SQL Server 2000
    数据库命名
    StudentManager
    数据库表
    Logon(登录帐号密码),主要用来保存用户登录信息。



    字段名
    数据类型
    长度
    是否为空
    是否主键




    UserID
    char
    10
    不为空
    主键


    Passwordr
    charr
    10




    StudentTable1(学生信息表),主要用来保存学生信息。



    字段名
    数据类型
    长度
    主键否
    是否为空
    描述




    StudentID
    Char
    10
    主键
    不为空
    学生学号


    StudentName
    Char
    10

    不为空
    学生姓名


    StudentSex
    Char
    2

    不为空
    学生性别


    StudentBirthday
    Datetime
    8


    学生生日


    Class
    char
    16


    所在班级



    TeacherTable1(教师信息表),用来储存教师的基本信息。



    字段名
    数据类型
    长度
    主键否
    是否为空
    描述




    TeacherID
    Char
    10
    主键
    不为空
    教师编号


    TeacherName
    Char
    10

    不为空
    教师姓名


    TeacherSex
    Char
    2

    不为空
    教师性别


    TeacherBirthday
    Datetime
    8


    教师生日


    Post
    char
    10


    教师职称


    Department
    char
    20


    所在院系



    CourseTable(课程信息表)



    字段名
    数据类型
    长度
    主键否
    是否为空
    描述




    CourseID
    Char
    16
    主键
    不为空
    课程编号


    CourseName
    Char
    16

    不为空
    课程名


    Point
    Char
    8

    不为空
    学分


    StuNumber
    Datetime
    4

    不为空
    选课人数



    ScoreTable(学生成绩表),用于存储学生成绩。



    字段名
    数据类型
    长度
    是否为空
    是否主键




    CourseID
    char
    16
    不为空
    主键


    StudentID
    char
    10
    不为空
    主键


    Score
    int
    4




    TeachTable(j教师授课表)



    字段名
    数据类型
    长度
    是否为空
    是否主键




    CourseID
    char
    16
    不为空
    主键


    TeacherID
    char
    10
    不为空
    主键


    Location
    int
    10




    数据库账户及权限 (截图)
    学生账户表

    教师账户表

    用户登录表

    数据库存储过程
    AllCourse
    create proc AllCourseasbegin select x.CourseID,x.CourseName,x.Point ,y.TeacherName,y.Post,z.Location,x.StuNumber from Course x,TeacherTable1 y,TeachTable z where x.CourseID=z.CourseID and y.TeacherID=z.TeacherIDend
    DeleteLogon
    create proc DeleteLogon(@id char(10))asbegin delete from Logon where UserID=@idend
    DeleteStudent
    create proc DeleteStudent(@id char(10))asbegin delete from StudentTable1 where StudentID=@idend
    DeleteTeacher
    create proc DeleteTeacher(@id char(10))asbegin delete from TeacherTable1 where TeacherID=@idend
    InsertLogon
    create proc InsertLogon(@id char(10))asbegin insert into Logon values(@id,@id)end
    InsertStudent
    create proc InsertStudent(@userid char(10),@username char(10),@sex char(2),@birth datetime,@class char(10))asbegin insert into StudentTable1 values(@userid ,@username,@sex,@birth,@class)endreturn
    InsertTeacher
    create proc InsertTeacher(@userid char(10),@username char(10),@sex char(2),@birth datetime,@post char(10),@department char(10))asbegin insert into TeacherTable1 values(@userid ,@username,@sex,@birth,@post,@department)endreturn
    IsExistsStu
    create proc IsExistsStu(@id char(10))asbegin select * from StudentTable1 where StudentID=@idend
    IsExistsTea
    create proc IsExistsTea(@id char(10))asbegin select * from Teachertable1 where TeacherID=@idend
    ProcAllStu
    create proc ProcAllStuasbegin select * from StudentTable1end
    ProcAllTea
    create proc ProcAllTeaasbegin select * from TeacherTable1end
    ProcLogon
    create proc ProcLogon(@userid char(16),@password char(10))asbegin select * from Logon where UserID=@userid and Password=@passwordendreturn
    ProcModify
    create proc ProcModify(@id char(10),@password char(16))asbegin update Logon set Password=@password where UserID=@idend
    ProcStudent
    create proc ProcStudent(@id char(10))asbegin select * from StudentTable1 where StudentID=@idend
    SelectCourse
    create proc SelectCourse(@id char(10),@courseid char(16))asbegin insert into ScoreTable values(@courseid,@id,null)end
    SelectedCourse
    create proc SelectedCourse(@id char(10))asbegin select * from ScoreTable where @id=StudentIDend
    SelectedCourseNum
    create proc SelectedCourseNum(@id char(10))asbegin select COUNT(*) from Scoretable where StudentID=@idend
    SelectedDetail
    create proc SelectedDetail(@id char(10))asbegin select x.CourseID,x.CourseName,x.Point ,y.TeacherName,y.Post,z.Location,s.Score from Course x,TeacherTable1 y,TeachTable z,ScoreTable s where @id=s.StudentID and x.CourseID=z.CourseID and z.TeacherID=y.TeacherID and x.CourseID=s.CourseIDend
    3.4 系统界面设计3.4.1 窗体功能描述登录界面Logon.java

    管理员以帐号Admin密码123登录成功进入管理员的信息管理界面,通过点击“学生信息管理”和“教师信息管理”进入不同的管理界面,学生信息管理界面如下:

    教师信息管理界面如下:

    以学生帐号(如:帐号:S001001,密码:S001001)登陆成功后进入如下界面,首先显示的 是学生的基本信息:

    点击“课程列表”按钮进入如下界面:

    根据自己的跟人兴趣选择课程,选择的课程数目不能超过3门否则弹出对话框如下:

    点击“确定”跳转到已选课程列表。
    在主界面点击“已选课程”按钮也可以进入下面的界面查看已经选择的课程:

    以教师帐号(如:帐号:T01001,密码:T01001)登陆成功后进入如下界面,首先显示的是教师的基本信息:

    点击“录入成绩”可以通过表格来录入学生的成绩,界面如下图所示:

    3.4.2 页面/窗体关系结构图
    四、系统实现技术小结为了方便管理,将数据库的封装分成两部分,数据库资源配置文件和封装数据库操作的类SqlManager.java。
    数据库资源配置文件sysConfig.properties
    #Sepecify the system type: window or unixsystem-type=windows#specify the database's typedatabase-type=sqlserver#specify some parametersDBhost=localhostDBport=1433DBname=StudentManagerDBuser=saDBpassword=
    封装数据库操作的类:SqlManager.java
    import java.sql.*;import java.util.*;import javax.swing.JOptionPane;public class SqlManager { private static SqlManager p=null; private PropertyResourceBundle bundle; private static String jdbcDriver=null; private static String split=null; private String DBType=null; private String DBhost="localhost"; private String DBname=""; private String DBport=""; private String DBuser=""; private String DBpassword=""; private Connection Sqlconn=null; private Statement Sqlstmt=null; private String strCon=null; private SqlManager(){ try{ bundle=new PropertyResourceBundle(SqlManager.class. getResourceAsStream("/sysConfig.properties")); this.DBhost=getString("DBhost"); this.DBname=getString("DBname"); this.DBport=getString("DBport"); this.DBuser=getString("DBuser"); this.DBpassword=getString("DBpassword"); String system_type=getString("system-type"); if(system_type!=null){ if(system_type!=null){ if(system_type.toLowerCase().equals("widows")) split=";"; else if(system_type.toLowerCase().equals("unix")) split=":"; } String database_type=getString("database-type"); this.DBType=database_type; if(database_type!=null){ if(database_type.toLowerCase().equals("mysql")){ jdbcDriver="com.mysql.jdbc.Driver"; strCon="jdbc:mysql://"+DBhost+":"+DBport+"/"+DBname; } else if(database_type.toLowerCase().equals("oracle")){ jdbcDriver="oracle.jdbc.driver.OracleDriver"; strCon="jdbc:oracle:thin:@"+DBhost+":"+DBport+":"+DBname; } else if(database_type.toLowerCase().equals("sqlserver")){ jdbcDriver="com.microsoft.jdbc.sqlserver.SQLServerDriver"; strCon="jdbc:microsoft:sqlserver://"+DBhost+":"+DBport+";DatabaseName="+DBname; } } } }catch(Exception e){ e.printStackTrace(); } } public static SqlManager createInstance(){ if(p==null) { p=new SqlManager(); p.initDB(); } return p; } private String getString(String s) { return this.bundle.getString(s); } public void initDB(){ System.out.println(strCon); System.out.println(jdbcDriver); try{ Class.forName(jdbcDriver); }catch(Exception ex){ System.err.println("Can't Find Database Driver."); } } public void connectDB(){ try{ System.out.println("SqlManager:Connecting to database..."); Sqlconn=DriverManager.getConnection(strCon,DBuser,DBpassword); Sqlstmt=Sqlconn.createStatement(); }catch(SQLException ex){ System.err.println("connectDB"+ex.getMessage()); } System.out.println("SqlManager:Connect to database successful."); } public void closeDB(){ try{ System.out.println("SqlManager:Close connection to database..."); Sqlstmt.close(); Sqlconn.close(); }catch(SQLException ex){ System.err.println("closeDB:"+ex.getMessage()); } System.out.println("Sqlmanager:Close connection successful."); } public int executeUpdate(String sql){ int ret=0; try{ ret=Sqlstmt.executeUpdate(sql); }catch(SQLException ex) { System.out.println("executeUpdate:"+ex.getMessage()); } return ret; } public ResultSet executeQuery(String sql){ ResultSet rs=null; try{ rs=Sqlstmt.executeQuery(sql); }catch(SQLException ex){ System.err.println("executeQuery:"+ex.getMessage()); } return rs; } public static void main(String args[]){ SqlManager.createInstance().connectDB(); SqlManager.createInstance().closeDB(); }}
    五、课程设计体会该系统主要实现了学生选课的功能,这个系统是我独立完成,从需求分析,界面的搭建,到数据库的连接,表格,存储过程和存储过程等的建立,在这段时间的摸索中,我确实学到了很多东西,特别是对以前不太了解的Java Swing组件有了更深刻的了解。比如JTable,对于它的用法我在网上找了很多资料,JTable的建立有各种不同的方法,可以使用DefaultTableModel类来实现,如DefaultTableModel dtm=new DefaultTableModel(new Object [] {“”,”课程编号”,”课程名称”,”学分”,”任课教师”,”教师职称”,”上课地点”,”以选人数”},0));然后再table.setModel(dtm); 或者继承AbstractTableModel类,还有对于如何在JTable中添加Swing组件,原本我是直接新建一个JcheckBox对象直接添加到表格的单元格里,结果发现只能显示出一串字符串,上网查找后才知道,要用DefaultCellEditor来添加Swing组件,再设置setCellRenderer(new MyTableRenderer()) 这是一个实现了TableCellRenderer接口的JCheckBox。TableCellRenderer可以看做是Swing组件的呈现器,这样Table就会把内容显示绘制交给JCheckBox了。
    对于数据库,我尽量将对数据库的操作放在存储过程中,这样的抽象和封装使得源程序代码更加容易理解,而且在web应用系统中也可以避免发生不安全的状况,我想这是一个号的程序员应当要养成的习惯,在这次的课程设计中,层次化,模块化,抽象化也是我学到的一个重要的经验,参考一些资料后发现模块化能使程序设计更加简单,设计代码时目标更加明确,效率更高,以前虽然也知道这些道理,但自己真正实施起来却感到无从下手,比如前面的数据库操作和数据库资源配置文件,就是我从书中看来的,这样做的好处是,在程序中操作数据库的时候避免了使用很多try和catch语句,是代码更加简洁,更容易理解,此外需要连接不同的数据库时只要修改数据库的资源配置文件sysConfig.properties就可以了。原本我是想用jsp 做一个web应用程序的,因为对于学生选课系统做成单版的确实没什么实用性,但是我对jsp还不太熟悉,所以这次先做个单机版的,以后我会尝试用jsp来做这个系统。
    1 评论 83 下载 2019-04-29 20:06:31 下载需要12点积分
  • 基于Android的天气预报APP

    摘 要随着移动通信技术的发展和无线数据业务的进步,手机已被赋予了除通话以外的其它许多功能。全新的手机软件领域已逐渐聚焦了众多软件开发商的目光,软件开发者和软件用户将共同面临这个振奋人心的新境界。
    本设计使用Android设计技术开发了一种运用在Android系统上的手机天气预报软件系统,本系统通过选择城市来获得天气,风向,风向,温度等信息。基于手机的天气预报系统软件可以使用户对于各地的天气情况的实时掌握,极大的方便了用户的出行和行程安排,避免了不必要的麻烦,具有很强的实用性。
    关键词:Android;手机天气预报软件。
    AbstractWith the development of science and technology, the mobile terminal gradually into the people’s attention, related to more widely, and play an increasingly important role in people’s daily lives. Therefore, the development of critical applications has become an important factor in the popularity of the mobile terminal, the design and development of practical, convenient application is of great significance and good market prospects. Android as the most popular operating platform, naturally, there are a lot of demand for application services.
    The study of this topic is the weather software, based on the Android platform is designed to help the user to query weather information and weather changes anytime, anywhere, to make life more comfortable and convenient. This paper describes the software interface design of the Android platform under the weather and exception handling part, including the contents of the interface implementation, the use of controls, the layout of the interface, and exception handling, combined with weather data of the China Meteorological Association, will be accurate weather conditions presented to the user-friendly way, allows the user to experience more enjoyable the service of this software.
    KEY WORDS:Android,interface,control,weather software
    1 绪论Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2012年11月数据显示,Android占据全球智能手机操作系统市场76%的份额,中国市场占有率为90%。2013年09月24日谷歌开发的操作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。
    1.1 课题研究内容本课题研究的是基于Android平台下的天气软件,目的是使用户能随时随地的查询天气信息及天气变化情况,让生活更加舒适方便。本文讲述Android平台下天气软件的界面设计以及数据的获取和解析,主要包括界面的实现,控件的使用,界面的布局和数据处理等内容,结合中国气象网的天气数据,将准确的天气情况以友好的方式呈现给用户,使用户更加赏心悦目的体验本软件的服务。通过对界面的布局及控件的应用等相关内容的学习,使我们对Android平台下界面开发工作有一个初步的了解,并且经过这次开发过程,能够基本掌握这些内容。
    1.2 课题研究需求分析课题研究需要达到的基本要求:

    能够查询城市的天气情况
    系统能通过手机查看并显示天气数据
    系统必须具有安全性,可靠性,独立性

    1.3 研究目的和意义天气软件是一种非常实用的信息服务,随着智能手机的不断普及,各种智能手机平台下都有各种各样的天气软件。Android作为现在主流的智能手机之一,自然也需要这方面的软件。天气关系到人们的日常生活,如告知温暖,方便出行等。一款简单实用的天气软件会很吸引用户。
    基于Android平台的天气软件已经有很多,经过分析,用户第一眼往往是一个软件的外观,一个好看的界面才能让用户以一种爱美之心去尝试,才能进一步了解一个软件的好坏,所以吸引眼球的界面是争取用户的第一步。因此,界面设计工作对应用程序来说非常重要,在界面上吸引了用户,才能进一步让用户体验应用程序中的功能,使用这个软件。
    1.4 研究前景Android最吸引人的特点是开源特性,因其开源,允许所有人对其代码进行开发和修改,同时又由于其代码的简单易学性,Android在全世界拥有众多的粉丝。Android在中国的前景十分广阔,首先是有成熟的消费者,在国内,Android社区十分红火,这些社区为Android在中国的普及做了很好的推广作用。国内厂商和运营商也纷纷加入了Android阵营,包括中国移动,中国联通,中兴通讯,华为通讯,联想等大企业,同时不仅仅局限于手机,国内厂家也陆续推出了采用Android系统的产品,我们可以预见Android将会被广泛应用在国产智能上网设备上,将进一步扩大Android系统的应用范围。
    Android采用了软件层(Software stack)的构架,主要分为三个部分。底层以Linux为内核作为基础,由C语言开发,只提供基础功能,中间层次包话函数库和虚拟机,由C++开发。最上层是各种应用软件,包话通话程序,短信程序。应用软件可以由各公司或个人自行开发,以JAVA编写。
    2 Android开发环境及平台搭建2.1 Android开发环境介绍Android平台使用Java编程语言来开发应用程序,而Android提供了对Java的核心支持。考虑到Java虚拟机的执行效率和占用资源情况,Google重新设计了Java的编译器,命名为Dalvik。Dalvik是经过优化的Java编译器,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux进程执行,独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
    项目的开发在Eclipse环境中进行,由于进行的是Android应用程序的开发,需要在Eclipse安装ADT插件,即Android开发工具,这样Eclipse就可以和Android SDK建立连接,在Eclipse中启动Android模拟器、调试程序等工作。
    由以上分析可知,Android平台的搭建需要Android SDK、Java SDK、Eclipse和ADT四个软件。
    2.2 Android开发平台搭建在进行Android应用程序的开发前,要先搭建Android平台,然后才能在开发环境中进行编程。根据官方指导,对Android平台的搭建过程介绍如下:
    STEP1:在官方网址上下载JDK6.0并安装,网址是:
    http://www.oracle.com/technetwork/java/javase/downloads/index.html安装后设置系统环境变量JAVA_HOME、CLASS_PATH、PATH的值;
    STEP2:在官方网址上下载更新的SDK进行安装,官方网址为:
    http://development.android.com/sdk/index.html下载完后解压到指定文件夹,启动SDK Manager进行安装,选择需要的Android版本,然后更新,这次更新需要的时间比较慢,所以更新前要做好准备。安装完成后,将ADB命令所在的目录platform-tools的完整路径添加到系统的环境变量PATH中,就能够在命令中使用ADB命令了;
    STEP3:接下来要安装的是ADT插件,即Android开发工具。因为ADT在线安装容易遇到问题,增加一些不必要的麻烦所以需要下载后在本地安装。指定网址为:
    http://development.android.com/sdk/index.htmlSTEP4:下载Eclipse,建议选择Eclipse3.4以上版本,网址为:
    http://www.eclipse.org/downloads/解压到指定位置后运行,选择Eclipse菜单中的Help>Install New Software选项卡上的Available Software,点击右侧的Add,然后在Name框中填写Android,在Location框中选择上步下载的ADT文件,然后点击OK>Finish>Install All,这时关闭Eclipse再重新启动。重启后选择Eclipse菜单中的Window>Preferences,在左侧的Android项目中SDK Location中填入Android SDK解压后的目录,然后点击Apply。
    至此,整个平台的搭建工作就完成了,可以进行相应的安卓应用开发。
    3 项目分析3.1 用户界面分析根据应用程序的功能需要,对用户界面做如下分析:
    实时天气界面:显示城市当前的实时天气状况,包括城市名称、城市名片、天气情况、温度高低、星期等信息。界面左边有一列城市列表,显示中国各个城市名称,当用户想知道哪个城市的天气情况时,点击这个城市名就可以获取天气状况,考虑到使软件占用尽量小的内存,软件去掉了不必要的花哨,显示城市名称,城市名片,温度和天气情况,同时对未来6天的天气情况简要描述,简要显示星期、天气描述、温度高低等数据,使用户一目了然,使人们及时了解天气变化,对日常生活出行、穿衣做好准备。
    3.2 相关技术介绍3.2.1 Activity在Android应用程序中,一个活动Activity通常就是一个单独的界面。每一个界面都被实现为一个独立的类,并且从Activity基类中继承而来,Activity将会显示由空间组成的用户接口,并对事件做出响应。大多数的应用都是由多个Activity显示组成。
    简单的说,Activity代表一个用户所能看到的界面,主要用于处理应用程序的整体性工作,例如,监听系统事件如按键事件、触摸屏事件等,为用户显示指定的View,启动其他Activity等。所有应用的Activity都继承于android.app.Activity类,该类是Android提供的基层类,其他的Activity继承该父类后,通过父类的方法实现各种功能,这种设计在其他领域也较为常见。
    3.2.2 IntentAndroid基本的设计理念是鼓励减少组件间的耦合,因此Android提供了Intent,Intent提供了一种通用的消息系统,它允许在你的应用程序与其他的应用程序间传递Intent来执行动作和产生时间。使用Intent可以激活Android应用的三个核心组件:活动、服务和广播接收器。
    Intent可以划分为显示意图和隐式意图。显示意图调用Intent,SetClass方法明确制定了组件名的Intent为显示意图,显示意图明确制定了Intent应该传递给那个组件,在同一个应用内部使用的。隐式意图没有明确指定组件名的Intent为隐式意图,Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。
    Intent负责对应用中一次操作的动作、动作涉及数据和附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的结构。
    3.2.3 Service如果把Activity比喻为前台程序,那么Service就是后台程序,Service的整个生命周期都只会在后台执行。Service跟 Activity一样也由Intent调用,由于Service在后台运行,所以没有界面,用来处理耗时比较长,而且Service不是一个单独的进程,也不是一个单独的线程。Service有两种类型:

    本地服务(Local Service):用于应用程序内部
    远程服务(Remote Sercie):用于android系统内部的应用程序之间

    前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。后者可被其他应用程序复用,例如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
    Service的生命周期,Service有startService和bindService两种启动Service方法,每种方法Service的生命周期是不一样的。
    通过startService()——Service会经历 onCreate —> onStartCommand(),stopService的时候直接onDestroy,如果是调用者直接退出而没有调用stopService的话,Service会一直在后台运行,下次调用者再起来仍然可以stopService;
    通过bindService()——Service只会运行onCreate()—>onBind() 这个时候调用者和Service绑定在一起 unbindService的时候onUnbind() —> onDestroyed(),调用者退出了,Srevice就会调用onUnbind() —> onDestroyed()。在这里需要注意的是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。
    3.3.4 Layout布局布局方式有很多种,比如线性布局(Linear Layout)、相对布局(Relative Layout)、表格布局(Table Layout)、网格视图(Grid View)、标签布局(Tab Layout)、列表视图(List View)和绝对布局(Absolute Layout)。本文设计主要采用相对布局(Relative Layout)、线性布局(Linear Layout),所以就相对布局和线性布局我们来做简单地介绍。
    相对布局 Relative:里面可以放多个控件,允许子元素指定它们相对于父元素或其他元素的位置(通过ID指定)。因此你可以按正确的顺序对齐两个元素,或者让一个视图在另外一个下面,居于屏幕中间,左边的中间,等等。元素通过给定顺序来绘制,因此如果第一个元素在屏幕中间,其他以它对齐的元素都会对齐到屏幕中间。同样,因为这个顺序,如果使用XML来指定这个布局,你将引用的元素(为了定位其它视图对象)必须被列在XML文件中,在你通过引用ID从其他视图中引用它之前。其中一些特性直接由元素支持,另外一些由它的LayoutParams成员变量支持(为所有这个屏幕中的元素子类化RelativeLayout,因为所有元素都是RelativeLayout父对象的子元素)。已定义的相对布局RelativeLayout参数是:width,height,below,alignTop,toLeft以及padding[Bottom|Left|Right|Top]和margin[Bottom|Left|Right|Top]。注意其中一些参数明确是相对于其他元素的布局位置,所以它们的数值必须是你的相对位置元素的ID。
    线性布局 LinearLayout:线性布局是所用布局中最常用的方式之一,RadioGroup, TabWidget,TableLayout,TableRow,ZoomControls类的父类。LinearLayout可以让它的子元素垂直或水平的方式排成一行(不设置方向的时候默认按照垂直方向排列)。LinearLayout以你为它设置的垂直或水平的属性值,来排列所有的子元素。所有的子元素都被堆放在其它元素之后,因此一个垂直列表的每一行只会有一个元素,而不管他们有多宽,而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高度)。LinearLayout保持子元素之间的间隔以及互相对齐(相对一个元素的右对齐、中间对齐或者左对齐)。
    LinearLayout还支持为单独的子元素指定weight 。好处就是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个weight 值,剩余的空间就会按这些子元素指定的weight比例分配给这些子元素。默认的weight值为0。例如,如果有三个文本框,其中两个指定了weight值为1,那么,这两个文本框将等比例地放大,并填满剩余的空间,而第三个文本框不会放大。
    3.3.5 控件介绍TextView——文本控件,可以用它来显示文字,就像一个标签一样,对TextView是怎么设置显示的文本,怎样设置字体的大小,字体的颜色,字体的样式。TextView包含以下子类:Button, CheckedTextView,Chronometer,DigitalClock,EditText。

    android:id —— 控件的标识符
    android:layout_width —— 设置控件的宽度
    android:layout_height —— 设置控件的高度
    android:layout_marginTop —— 设置文本的上外边距
    android:textSize —— 设置文本文字的的大小
    android:paddingLeft —— 设置元素左内边距

    Button——按钮控件,在button内部可以放置内容,比如文本或图像。<button>与</button>标签之间的所有内容都是按钮的内容,其中包括任何可接受的正文内容,比如文本或或多媒体。例如,我们可以在按钮中包括了一个图像和相关的文本,用它们在按钮中创建一个吸引人的标记图像。不过button禁止使用的元素是图像映射,因为它对鼠标和键盘敏感的动作会干扰表单按钮的行为。下面是Button的部分属性:

    android:id —— 控件的标识符
    android:layout_width —— 设置按钮的宽度
    android:layout_height —— 设置按钮的高度
    android:textSize —— 设置按钮里文字的大小
    android:layout_marginTop —— 设置按钮的上外边距
    android:text —— 设置按钮中的文字
    android:visibility —— 设置按钮里的元素是否可见

    EditText——文本编辑框,TextView的直接子类,所以EditText会继成父类TextView的一些方法。在布局中配置EditText也需同时配置一个Button,这样可以在代码中监听Button的事件,以便获取当前在EditView中输入的内容并且显示出来。在EditView可以限制输入的字符串类型。下面是EditText的部分属性:

    android:id —— 控件的标识符
    android:layout_width —— 设置输入框的宽度
    android:layout_height —— 设置输入框的高度
    android:layout_weight —— 设置输入框占父控件的比例
    android:inputType —— 设置输入框内的字符串类型
    android:hint —— 设置在输入框输入内容前默认的文字

    ImageView——标签可以显示任意图像,例如图标,图片等。ImageView类可以加载各种来源的图片,需要计算图像的尺寸,以便它可以在其他布局中使用,并提供例如缩放和着色等各种显示选项,在本文用来显示城市图片。下面是ImageView的部分属性:

    android:id —— 设置图片的标识符
    android:layout_width —— 设置图片的宽度
    android:layout_height —— 设置图片的高度
    android:visibility —— 设置图片是否可见性

    4 天气预报软件界面设计与实现4.1 Android平台用户界面的实现Android 提供的可变化的用户界面(UI)开发模块是基于XML 文件的。这些XML 文件放在工程/res/layout 下面。这个目录可包含所有应用程序所需的代码部分,比如图片、字符串、xml 文件。当要使用到这些资源时,在代码目录中打开R.java文件即可。在XML 文件里编辑界面的代码,实现起来不仅方便,使用时也会更加灵活。
    在Android 程序设计中要用到一些基本的Android UI 元素,通过使用Views、View Groups 和layouts 可为Activity 创建功能性的、富有直观力的UI.通常是使用Android SDK 中提供的一些控件,进行布局、扩展和定制这些控件,并使用ViewGroups 去组合Views,创建由相互作用的子控件组成的原子的、重复利用的UI 元素。也可以创建自己的Views,来实现显示数据和与用户交互的新途径;或使用一些继承自View Group 的Layout 管理器来组织Android UI中的单个元素到屏幕上。
    在一个Android 应用中,用户界面由View 和View Group对象构建。View 与View Group 有很多种类,而它们都是View类的子类。View 对象是Android 平台中用户界面的基本单元。View 类是widgets(工具)类的父类,它们提供了诸如文本输入框和按钮之类的UI 对象的完整实现。View Group 类是Layouts(布局)类的父类,它们提供了诸如流式布局、表格布局以及相对布局之类的布局架构。
    View 对象是一个数据体,它的属性存储了用于屏幕上一块矩形区域的布局参数及内容。并负责它所辖的这个矩形区域之中所有测量、布局、焦点转换、卷动以及按键/触摸手势的处理。作为一个用户界面对象,View 同时也担任着用户交互关键点以及交互事件接受者的角色。天气实时预报系统程序功能比较单一,其UI 也相对比较简单,只要有一个显示所有中国城市信息的列表,一个显示城市图片的Imageview即可。为了建立Android 平台的用户界面,首先要在Package Explorer 窗口中展开Layout 后新建xml 文件,用来对窗口界面进行布局,主要有系统运行的主配置文件activity_main.xml ,listview.xml和weatherfragment.xml。
    Layout 是一类特殊的ViewGroup 控件,它们本身没有任何可显示内容,存在的惟一原因就是其中的内部结构,能够更好地摆放它的子控件。比如Linearlayout,可将子控件按水平或垂直方向按顺序排列下去;Tablelayout,可以将子控件按照表格的形式,一枚枚放置好;Relativelayout 更灵活,可以设定各个控件之间的对齐和排列关系,适合定制复杂的界面。有了Layout 的存在,控件和控件之间不再是割裂地存在,而是更有机地结合在一起,设定起来也更为方便。在activity_main.xml 文件中主要是添加一些界面的布局设置。
    4.1.1 主要的项目工程文件为了给用户清晰,直观的体验,界面设计要做到简明,友好,因为考虑到各个城市的不同特点,所以给每个城市添加一张城市名片的图片,能使用户感觉更加友好,界面左边是城市列表,用户可以选择具体城市查看天气信息。考虑到软件的简洁明确性,只设定一个界面用来显示城市和天气信息,weather工程目录结构及其源代码文件如图1所示:

    4.1.2 创建中国城市列表根据天气预报系统功能需求分析,系统启动后,应在主界面上呈现出中国国内所有城市的列表数据,因此需要创建中国城市列表数据,包括获取、解析城市列表数据,并在用户界面上呈现出来。同时为了给用户更好的交互,每个城市对应显示城市名片,通过代码实现,具体代码如下:
    @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLayoutInflater = LayoutInflater.from(this); cityList = (ListView) findViewById(R.id.citylist); cityImage = (ImageView) findViewById(R.id.cityImage); cityName = (TextView) findViewById(R.id.cityName); cityWeather = (TextView) findViewById(R.id.cityWeather); cityTemp = (TextView) findViewById(R.id.cityTemp); viewpager = (ViewPager)findViewById(R.id.viewpager); citys.add(new City(R.drawable.city1, "桂林", "101300501")); citys.add(new City(R.drawable.city2, "北京", "101010100")); citys.add(new City(R.drawable.city3, "哈尔滨", "101050101")); citys.add(new City(R.drawable.city4, "大连", "101070201")); citys.add(new City(R.drawable.city5, "南京", "101190101")); citys.add(new City(R.drawable.city6, "成都", "101270101")); citys.add(new City(R.drawable.city7, "广州", "101280101")); citys.add(new City(R.drawable.city8, "乌鲁木齐", "101130101")); citys.add(new City(R.drawable.city9, "香港", "101320101")); citys.add(new City(R.drawable.city10, "台北", "101340101")); citys.add(new City(R.drawable.city11, "沈阳", "101070101")); citys.add(new City(R.drawable.city12, "呼和浩特", "101080101")); citys.add(new City(R.drawable.city13, "济南", "101120101")); citys.add(new City(R.drawable.city14, "西安", "101110101")); citys.add(new City(R.drawable.city15, "兰州", "101160101")); citys.add(new City(R.drawable.city16, "武汉", "101200101")); cityadapter = new CityAdapter(); weatheradapter = new WeatherAdapter(getSupportFragmentManager()); cityList.setAdapter(cityadapter); viewpager.setAdapter(weatheradapter); cityList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { // TODO Auto-generated method stub selectid = position; cityadapter.notifyDataSetChanged(); cityImage.setImageResource(citys.get(position).image); callHTTP(citys.get(position).code); } }); cityImage.setImageResource(citys.get(selectid).image); callHTTP(citys.get(selectid).code);}
    这段代码的作用是在创建城市列表的同时,将城市名称,城市名片和城市接口结合在一起,使得显示的时候同步,具体效果如图2所示:

    4.2 天气信息的获取基于Android 操作系统的天气实况预报系统设计的核心是通过调用通信协议SOAP(Simple Object AccessProtocol)的接口,从Web Service 提供商中提取天气预报的数据信息,为客户端服务。其基本功能是当用户运行天气预报系统程序时,在手机屏幕上显示出中国的城市名称,用户单击任意一个城市名,可获得该城市的天气实时预报信息。为此,需要解决的问题是手机终端从Web 服务器获取了所有类型的数据之后,将这些数据进一步交给Android 手机终端View 组件,在手机界面上显示给用户。
    4.2.1 天气信息数据的获取在开发中我们经常提到”接口”这个词,什么是接口呢?简单的说,接口其实就是一个http地址。一个标准的网络应用肯定需要两个部分,一部分是咱们正在学习的android开发,还有另一部分是服务器开发。
    大多数android程序都是基于网络的,比如基本上大家都在使用的QQ手机客户端。那么假设我们现在要开发一个类似QQ的通信客户端。第一步,需要开发一个登录界面来验证用户登录。很显然的,为了验证登录,我们需要和服务器进行通信,把用户输入的用户名和密码传递给服务器,然后服务器来判断这组用户名密码数据是否正确,并返回给客户端,告诉我们用户登录是否成功。一般接口由三部分组成:接口地址+接口名称+接口参数。比如下面这个是中国气象网提供的天气信息查询接口:http://www.weather.com.cn/data/cityinfo/101300501.html ,该接口提供的数据是实时天气情况,通过这个接口我们可以得到以下信息,如图3所示:

    代码实现接口获取数据如下:
    // 请求接口private void callHTTP(final String cityCode) { // 创建一个runnable Runnable runnable = new Runnable() { @Override public void run() { // step1 :创建HttpGet, 就是创建我们要访问的接口地址 HttpGet getMethod = new HttpGet("http://m.weather.com.cn/data/"+cityCode+".html"); // step2 :HttpClient, 我们要通过它来将step1创建出来的地址发送给服务器 HttpClient httpClient = new DefaultHttpClient(); try { // step3: 通过httpClient.execute()方法,我们把url发送给了服务器, // 而服务器返回的信息就会被保存在HttpResponse中了 HttpResponse response = httpClient.execute(getMethod); // 发起GET请求 // 用EntityUtils.toString把HttpResponse转换成string String result = EntityUtils.toString(response.getEntity(), "utf-8"); // 将返回的json字符串解析并显示出来 try { paresJson(result); } catch (JSONException e) { e.printStackTrace(); Log.v("TAG", "解析失败 "); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; // 开启线程执行runnable new Thread(runnable).start();}
    4.2.2 解析数据从图3可以看出,我们获得了桂林的天气信息,但是这些数据看着很乱,为了使用户清晰的获得信息,我们可以采用json协议解析数据:
    // 将返回的json字符串解析并显示出来private void paresJson(String jsonString) throws JSONException { // 首先,把这个字符串转换成jsonobject JSONObject jsonObject = new JSONObject(jsonString); // { // "weatherinfo": { // "city": "桂林", // "cityid": "101300501", // "temp1": "28℃", // "temp2": "19℃", // "weather": "多云", // "img1": "d1.gif", // "img2": "n1.gif", // "ptime": "11:00" // } // } // 理解json格式我们可以把它当成window里的文件系统, 大括号表示文件夹 // 假设上面是字符串的内容, // 那么最外面的"文件夹"里包含着一个叫"weatherinfo"的子文件夹. // 然后weatherinfo文件夹里包含着许多文件, 有的叫city ,有的叫 temp1, // city 后面的 "桂林" 表示的是city这个文件的实际内容是"桂林" //
    4.3 在UI上显示天气信息当获得天气数据之后,就可以把它绑定到activity_main.xml 定义的ListView 组件上,在WeatherFragment.java 中的代码段为:
    public class WeatherFragment extends Fragment { Weather weather; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); weather = (Weather)getArguments().getSerializable("weather"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater.inflate(R.layout.weatherfragment, null); TextView dayTextView = (TextView) view .findViewById(R.id.time); TextView tempTextView = (TextView) view .findViewById(R.id.yubaoTemp); TextView weatherTextView = (TextView) view .findViewById(R.id.yubaoWeather); dayTextView.setText(weather.day); tempTextView.setText(weather.temp); weatherTextView.setText(weather.weather); return view; }}
    5 软件测试5.1 天气预报软件在电脑模拟环境下测试软件编写完成,对其进行测试,首先将手机天气预报系统在电脑模拟环境下测试的方案,以下是对系统进行测试,在Eclipse 的Package Explorer 窗口中用鼠标右键选择weather工程名,在弹出的窗口中选择”Run As”→”Android Application”安装该应用程序到Android 模拟器并启动它,如图4所示:

    等待模拟器启动完成软件的安装,然后单击所要查询的城市名称列表项,稍等片刻便会显示出该城市的天气实况信息。电脑模拟测试结果如图5所示:


    通过网站查询桂林的天气情况如图6所示:

    通过对图5和图6的数据比较,可以知道软件获得的数据是正确的,说明软件的可行性基本满足要求。
    5.2 天气预报软件在Android手机下测试在工程名weather上点右键,然后选择“Run As”,然后选择“Android Application”。进入界面后,选择测试手机,如图7所示:

    等待程序安装完成,保证手机连接互联网的情况下,启动后可以得到各个城市的天气信息,如图8所示:




    该测试说明开发的天气预报软件可以独立在Android设备运行,满足设计要求的独立性,通过与网络的数据比较,可以发现,天气预报软件获取的数据与实际的天气情况非常接近,说明数据的准确性,实时性;从图9可以看出,当选择不同的城市时,软件可以通过网络获取不同城市的天气信息,说明该天气预报软件可以获取不同城市的气象信息,满足设计要求。
    6 总结在本次Android天气预报软件开发过程中,我通过学校的图书馆资料和网上查询,了解了Android的搭建、Intent、Activity、Service等知识。Android环境搭建的基本工作完成后,本文对界面的控件、布局和美观方面进行设计,对数据获取和解析做了分析,通过模拟器显示城市名片,实时天气情况和未来5天天气情况,这个软件还可以进一步发展,比如“短信预报”、“新闻模块”等功能,如果这些功能都能实现将会对用户有更多的帮助,使他们的生活更加愉悦和方便。Android 智能手机应用程序的开发涉及了它的整个体系结构,是一项非常复杂的工程。
    6 评论 119 下载 2019-05-18 15:31:02 下载需要15点积分
  • 基于JAVA实现的塔防游戏

    1 项目概述塔防游戏主要代表一类通过在游戏地图上装置炮塔,阻止敌人进攻的策略型游戏。本游戏是在地图上的特定地点装置多种能力不同的炮台以抵御多种怪兽的入侵。同时玩家每场战斗将拥有多种道具让玩家防守更加轻松。游戏原型是【保卫萝卜】和【皇城守卫】,总体设计风格和游戏背景音乐音效向【皇城守卫】靠拢,而游戏机制是参照了【保卫萝卜】。
    1.1 项目目标该项目是要创造出一个界面设计良好,运行流畅,游戏体验较好的一款单机塔防类游戏。游戏风格偏向卡通,游戏难度较为困难,需要玩家合理使用道具和防御塔。
    1.2 项目任务
    游戏中的炮塔创建,怪兽移动,炮塔攻击特色,玩家的特殊道具等功能的实现
    背景音乐的开启和关闭,关卡和地图选择,用户帮助文档,重新开始等功能的存在
    不同界面之间的切换良好,用户不会感到阻塞

    2 需求分析本游戏能够实现正常塔防游戏的基础功能,并且我们在游戏机制上是综合了保卫萝卜和皇城守卫两款游戏。本款游戏将实现如下功能:

    防御塔的创建、售卖、攻击
    怪兽的攻击、移动
    合理的金币获得设计、获取量设计
    道具的设计
    BGM的关闭,游戏音效的实现

    详细将由下图给出:

    3 系统设计本游戏因为组员资源收集能力有限并未找到相应源码进行参考,所以游戏的核心代码全是组员之间相互讨论得出。
    3.1 开发环境及技术手段
    jre1.8.162
    Java语言

    3.2 系统技术架构本程序主要采用多线程处理问题,包含线程的有游戏界面类,防御塔类,怪兽类。在新建一座防御塔时就会让防御塔启动线程,而所有线程结束的判断条件都是玩家的血量是否为零。线程所做的事情是将自我特定属性进行改变,让主线程的paint调用每个类的paint方法,然后主线程不停的重绘,这样就能达到动画效果。
    3.3 系统流程设计在等待界面,关卡选择界面,游戏界面都是实现了简单的mouse listener事件,而在进入游戏界面时会启动游戏界面的线程,只要玩家血量不为零并且怪兽没有被全部消灭线程就不会终结。但是在游戏界面有事件可以暂停游戏,返回开始界面。本游戏并没有设计退出按钮,玩家想结束游戏是可以在任何界面关闭窗体达到退出游戏效果。
    3.3.1 游戏流程图本游戏通过鼠标事件在不同的就jpanel之间进行切换,其中有游戏界面,关卡选择界面,帮助界面,开始界面。判断条件就是玩家选择哪个界面。

    3.3.2 开始界面开始界面中含有转换到帮助界面,关卡选择界面的鼠标事件,同时鼠标事件还能实现提示效果。即鼠标触碰到固定区域或者按钮时会有提示音效和图片改变效果。

    3.3.3 帮助界面帮助界面将有不同的图片指引玩家更好的进行该游戏,帮助界面只能返回开始界面,且只能在开始界面访问帮助界面。

    3.3.4 关卡选择界面关卡选择界面与开始界面设计大致相同,不同旗子的click事件将会让玩家进入到新的游戏界面。

    3.3.5 游戏界面当进入到游戏界面时游戏界面线程就开始启动并进入循环。只有玩家胜利、失败或者返回开始界面时,游戏线程才会结束。同时只要玩家处在这个界面就能够响应其鼠标事件

    3.3.6 游戏界面鼠标监听游戏界面的鼠标监听主要分为两个部分,游戏结束时监听、游戏运行时监听。游戏时监听分为防御塔空地监听,系统按钮监听。游戏结束监听即是执行游戏结束函数,因为在游戏结束函数中加入了判定游戏是否结束,所以只要将该函数放在首位即可。

    3.3.7 游戏界面线程游戏界面线程主要工作就是在游戏没有结束时不停的刷新页面。在游戏结束时调用结束函数去结束防御塔和怪兽的线程。因为结束函数的关系,玩家可以选择不反悔开始页面重新进行本关卡。当让如果想返回开始界面可以在点击游戏界面后点击返回按钮返回开始界面。

    3.3.8 游戏结束函数游戏结束函数只要作用是让玩家胜利或者失败是停止游戏并播放相应的BGM,在界面中画出相应的失败胜利标志。同时在鼠标事件中提示玩家重新开始。玩家如果不想继续游戏可以在游戏界面点解返回按钮返回开始界面

    3.4 接口和包的设计
    3.5 类图设计
    3.6 类表
    4 系统简介游戏能够正常的进行防御塔建立,怪兽死亡,胜利,失败,道具使用。项目目标中的功能基本全部实现。
    开始界面

    关卡选择界面

    游戏界面一

    游戏界面二

    胜利画面

    失败画面

    道具释放画面一

    道具释放画面二

    5 总结本次实践项目完成度良好。同学们在本次实践项目中掌握了不仅熟练掌握了Java语言的基础语法,对于特定的属性方法也有所掌握,如Jpanel的布局方式,线程的实际应用等。除开语言本身的熟练,队员们对于面向对象的思想,以及如何完整,有组织,有纪律的完成一个项目的方法也有了一定的接触。这也显示着我们正在逐步变成一个有着良好习惯的程序员。虽然本次游戏基本实现了项目目标,但是在实践过程中还是出现了很多的失误。

    因为时间和外部环境的制约,本次实践没有使用GitHub等实用的代码管理工具,代码之间的整合基本靠U盘和网络发送
    虽然初期准备了很多,整个项目的大致方向基本确立,但是缺少核心代码的讨论,一致于组员在初期的第一次整合代码阶段出现了严重的失误,导致组员又要聚集在一起重新讨论游戏的核心实现代码,时间也浪费的较多
    任务时间分工执行并不彻底,因为组员代码编写能力有限,常常会出想某个同学等另一个同学的情况,但是等待的同学并没有做他自己剩余的其他任务,这样就导致了没有充分利用工作时间的问题
    在游戏完成之后,再次查看自己编写的代码发现其中存在很多重复,没有用到的代码,这种问题的存在说明初期对象设计的失误,在初期自己设计整个代码是没有考虑到后期的延展性

    除开上述我们组员出现的失误,组员也展示了自己的专业素养:

    基本实现面向对象思想,在初期分类的时候大家都集体整合了接口相关的问题,而后期实现时基本不会存在类中有类的现象,并且出现bug时能够快速的知道是哪个类出现了问题
    游戏基础功能运行良好,初期设立的项目目标基本实现。UI界面设计良好,游戏动画效果基本无卡顿现象
    在代码编写阶段时组员都编写了良好可用的注释,让其他组员可以独立自主的查看代码
    大家都很积极的参与到项目的完成工作之中,在代码编写阶段,出现了小bug时都能在极短的时间内找到相应代码编写者进行调试解决,从而保证了代码良好的运行,提高了工作效率
    5 评论 247 下载 2018-11-14 16:38:54 下载需要20点积分
  • 利用哈希表实现电话号码查询系统

    第一章 需求分析1.1 问题描述设计一个电话号码查询系统,为来访的客⼈提供各种信息查询服务。
    1.2 基本要求
    设计每个记录有下列数据项:电话号码、用户名、地址
    从键盘输入个记录,分别以电话号码和用户名为关键字建立不同散列表存储
    采用一定的方法解决冲突
    查找并显示给定电话号码的记录
    查找并显示给定用户名的记录

    1.3 实现提示
    设计不同的散列函数,尝试不同类型冲突解决方案,考察平均查找长度的变化
    记录与散列表分开,达到不同关键字散列表可共享记录

    1.4 补充内容
    自动读入硬盘中的记录,并可以选择存储更新后的记录
    提供信息检测机制,以学号作为唯一关键字,对重复学号的记录不允许插入
    提供删除功能
    提供空⽩检测机制,输入信息任意一项为空则不允许插入
    提供格式检测机制,输入信息的格式不正确则不允许插入(如年龄不允许输入字符或字符串)
    采用不同的hash函数构建方法和不同的冲突处理方式
    实现用户界面

    第二章 系统描述2.1 开发语言及主要功能实现方法本程序基于java语言写成,配置java所需环境变量。 本程序中链表和hash函数均未使用java库中已有函数,链表和hash函数都 是使用java语言自⼰编写实现。 Java 语言实现链表和 C 语言类似,但由于 java 没有指针功能,因此可以将 节点作为单独的类,用引用的方法实现链式链接。 Hash函数分别采用除留取余法和伪随机数法,其中伪随机数用于字符串构造 hash函数,可根据不同的字符串生成不同的随机数。 冲突处理分别采用线性探测法、再哈希法和链地址法。
    2.2 单条记录所含内容结合学生电子号码本的需求情况,选出本部周围的8项内容,作为一条记录:



    学号
    姓名
    性别
    年龄
    电话号码
    住址
    学院
    专业




    123456789
    张三

    19
    1357924680
    学3-236
    计算机学院
    计算机科学与技术



    (其余记录与此格式相同,不做重复)
    2.3 Hash 函数及处理冲突方法本系统分别对学号、姓名、电话号码三项构建 hash 函数,并采用不同的冲突处理方法,具体如下:

    学号散列表:采用除留取余法构建hash函数,采用线性探测法处理冲突
    姓名散列表:采用伪随机数法构建hash函数,采用链地址法处理冲突
    电话号码散列表:采用除留取余法构建hash函数,采用再哈希法处理冲突

    除留余数法
    m是散列表表长。
    f(key) = key mod p (p<=m)
    随机数法
    注意random的随机种子需要是固定的,以便查询的时候能够根据key重新找到,适用于关键字长度不等的情况。
    f(key) = random(key)
    再哈希法
    遇到冲突就重新采用一个散列函数计算新的存储位置,可以使关键字不产生聚集。
    f i (key)=RH i (key) (i=1,2,...k)
    链地址法(拉链)
    将所有关键字的同义词记录在一个单链表中,在散列表中只存储所有同义词表的头指针。
    第三章 功能模块结构3.1 信息插入模块
    功能:插入单条记录,依次输入单条记录中的信息
    输入要求:学号不允许重复、每项信息不能有空值、性别只允许男/女,年龄只允许输入数字等等
    输出结果:将该记录保存在链表中备份,依次采用三种不同的 hash 函数构建散列表索引项,并处理冲突,实现记录与散列表分开,达到不同关键字散列表可共享记录

    3.2 信息修改模块
    功能:按照输入学号修改相应记录,在屏幕上显示对应记录的所有信息并允许修改
    输入要求:学号不允许重复、每项信息不能有空值、性别只允许男/女,年龄只允许输入数字等等
    输出结果:将原记录在链表中的内容更新备份,同时更新三种不同的 hash 函数构建的散列表索引项

    3.3 信息删除模块
    功能:删除单条记录,同时删除链表中的记录和各散列表中的索引
    输入要求:相应记录的学号必须存在
    输出结果:同时删除链表中的记录和各散列表中的索引

    3.4 信息查询模块——按照学号查找
    功能:根据学号的散列值查找单条记录,实际上为查找学号散列表中的索引并获取对应的完整记录
    输入要求:相应记录的学号必须存在
    输出结果:在屏幕上显示相关记录

    3.5 信息查询模块——按照电话查找
    功能:根据电话号码的散列值查找单条记录,实际上为查找电话号码散列表中的索引并获取对应的完整记录
    输入要求:相应记录的电话号码必须存在
    输出结果:在屏幕上显示相关记录

    3.6 信息查询模块——按照姓名查找
    功能:根据姓名的散列值查找单条记录,实际上为查找姓名散列表中的索引并获取对应的完整记录
    输入要求:相应记录的姓名必须存在
    输出结果:在屏幕上显示相关记录(由于姓名可能重复,所以可能会显示多条记录)

    3.7 信息保存
    功能:将已有记录保存在本地
    输入要求:无
    输出结果:在本地保存所有信息


    第四章 主要模块算法说明4.1 学号散列表设计
    hash函数构建方法:通过除留取余法构建散列表
    处理冲突方法:采用线性探测法,一次一步

    4.2 电话号码散列表设计
    hash函数构建方法:通过伪随机数法构建散列表处理冲突方法:采用再哈希法
    4.3 姓名散列表设计
    hash函数构建方法:通过伪随机数法构建散列表
    处理冲突方法:采用链地址法(插入、删除、更新、查询全部包含在内)

    4.4 记录插入模块设计从界面上⽂本框中读取字符串,并进⾏判断:

    首先各项都必须按 照要求,⽐如年龄不能为字符,学号不能为字符等等
    然后判断是否有某项为空,有空则不允许插入
    最后检测学号是否重复, 重复则不允许插入。 然后在链表中添加完整记录,同时建⽴学号、电话号码、姓名的索引

    4.5 记录修改模块设计首先根据给定的学号选择相应记录,显示在屏幕上,允许用户自⾏修改。从界面上⽂本框中读取字符串,并进⾏判断:

    首先各项都必须按 照要求,⽐如年龄不能为字符,学号不能为字符等等
    然后判断是否有某项为空,有空则不允许插入
    最后检测学号是否重复, 重复则不允许插入。 然后在链表中更新完整记录,同时更新学号、电话号码、姓名的索引

    4.6 记录删除模块设计删除输入学号对应的记录,同时删除链表中的节点和各索引表中的索引。
    第五章 运行结果主界面

    添加纪录

    通过学号查找记录并修改

    查询界面

    查询信息如下所示:

    保存信息到本地

    第六章 课程设计总结
    ⼈机交互的问题,用户界面如何设计得美观且易于使用,在此使用java UI设计,设计友好美观的界面,方便用户使用
    怎样能利用合理的哈希函数构建算法和冲突处理算法
    如何实现记录与散列表分开,达到不同关键字散列表可共享记录
    2 评论 100 下载 2018-11-05 12:19:45 下载需要6点积分
显示 75 到 90 ,共 15 条
eject