Tommorow
师生交流系统的设计与开发
复习、巩固JavaWeb的基础知识,进一步加深对JavaWeb技术的理解和掌握;课程设计为学生提供了一个既动手又动脑,独立实践的机会,将课本上的理论知识和实际有机的结合起来,锻炼学生的分析解决实际问题的能力。
培养学生在项目开发中团队合作精神、创新意识及能力
操作系统:Windows
开发工具:MyEclipse
Java中间件服务器:Tomcat
数据库: MySQL
MyEclipse 是一个十分优秀的用于开发Java, J2EE的 Eclipse 插件集合,MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持十分不错。MyEclipse可以支持Java Servlet,AJAX,JSP,JSF,Struts,Spring,Hibernate,EJB3,JDBC数据库链接工具等多项功能。可以说MyEclipse是几乎囊括了目前所有主流开源产品的专属eclipse开发工具。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
师生交流系统是一个教学系统,主要是帮助学生和教师更好进行交流,更好地将若干课程更加紧密地结合起来,更好地达到学以致用;达到教、学结合的目的;让学生能够更加完整而系统地掌握相关知识和技能。
根据师生交流系统的基本需求,本系统需要完成以下任务:
学生用户功能:学生登录之后可以对教学资料查询(可分页),教学视频播放和下载、试题下载
教师用户功能:教师登录本系统可以上传教学资料、视频以及试题,另外可以对这些资料进行增删改查
师生交流功能:学生可以向教师提问,教师可以对学生的提问进行答复
管理用户功能:管理员登录系统之后可以分配学生和教师,对学生和教师进行管理
从代码实现角度分析,该系统共包括以下几个部分:用户登录、信息的列表、信息的查询、信息的添加、信息的修改、信息的删除和退出登录。
用户分为学生用户、教师用户和管理员用户。
学生登录之后可以对教学资料、教学视频、试题进行查询和下载,还可以对教学视频进行播放;教师用户登录后可以上传教学资料、教学视频和试题,还可以对这些资料进行增删改查;管理员用户登录后可以分配学生和教师,对学生和教师信息进行增删改查。在论坛功能中,所有用户都可以发表帖子和回复,只有管理员可以对帖子信息进行删改。
功能描述:根据用户输入的用户名和密码,并选择用户角色(学生、教师或管理员)进行登录验证,输入正确则提示“成功”并进入系统主界面。输入错误则提示“失败”,并返回登录界面。
功能约束:用户登录必须输入用户名、密码,并选择用户角色。登录成功后会根据用户权限的不同,显示具有不同功能的系统主界面。
功能描述:在资料列表、视频列表、试题列表、学生管理、教师管理、论坛列表中,需要列出数据库中的数据。
功能约束:需要按实际情况准确显示数据库表中的数据。
功能描述:在列表的上方,通常要有输入框用于查询某一条或某几条特定信息,比如根据标题查找资料,根据用户名查找学生等。
功能约束:查询时不需要输入全部信息,只需输入部分信息。
功能描述:资料上传、视频上传、试题上传、用户添加、发表帖子、帖子回复等功能需要用到信息添加模块,添加时需按要求填写或选择信息,添加成功后会跳转到相应的列表界面。
功能约束:添加信息时会自动获取当前时间并录入到数据表中,需要用到文件的上传。
功能描述:管理员可以学生和教师进行编辑,还可以对帖子进行编辑,编辑成功会更新数据表中相应的信息,跳转到对应的列表。
功能约束:修改时也会自动修改数据表中的时间为当前时间。
功能描述:管理员和教师可以对资料、视频、试题进行删除,管理员可以对学生、教师的用户信息和帖子进行删除,删除成功会删除数据表中相应的信息并跳转到对应的列表。
功能约束:删除数据会根据数据表的“id”进行删除。
功能描述:当用户点击“退出”按钮时,会清空登录时保存的信息,并跳转到用户登录界面。
在前端的开发设计上,使用了bootstrap和jquary进行辅助开发,提高了开发的效率。
Bootstrap,来自 Twitter,是目前很受欢迎的前端框架。Bootstrap是基于 HTML、CSS、JavaScript的,它简洁灵活,使得Web开发更加快捷。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
本系统采用了SpringMVC框架进行后台的开发,大大加快了开发速度,使后台代码更加简洁与清晰,利于后期拓展与维护。
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
Spring MVC框架提供了一个DispatcherServlet作用前端控制器来分派请求,同时提供灵活的配置处理程序映射、视图解析、语言环境和主题解析,并支持文件上传。Spring MVC还包含了多种视图技术,例如JSP、Velocity、Tiles、iText和POI等。Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
通过对用户需求和系统设计思想的分析,并根据界面展示需要,可以得出该系统可以分为六大模块:用户登录模块、教学资料模块、教学视频模块、试题资料模块、用户管理模块、论坛系统模块。
经过分析,该系统要实现的是帮助学生和教师更好进行交流,达到辅助教学的目的。主要设计以下功能模块:
用户登录模块
用户在使用系统之前必须登录系统,登录时需要输入用户名、密码、验证码,选择用户角色进行登录。
教学资料模块
教学资料模块包括资料列表和资料上传两个部分,学生可以查看和下载资料,教师和管理员可以进行资料的增删改查。
教学视频模块
教学视频模块包括视频列表和视频上传两个部分,学生可以查看和下载视频,在线观看视频,教师和管理员可以进行视频的增删改查。
试题资料模块
试题资料模块包括试题列表和试题上传两个部分,学生可以查看和下载试题,教师和管理员可以进行试题的增删改查。
用户管理模块
管理员用户需要对学生用户和教师用户进行管理,包括学生列表、教师列表和用户添加三部分。用户添加功能需要首先选择角色,然后填写信息并提交。
论坛系统模块
论坛系统模块包括帖子列表和帖子发布两部分,所有用户都可以进行查看帖子列表和发表帖子,在帖子列表界面,点击帖子标题可以进入帖子详情,在帖子详情中用户可以查看回复内容及添加回复。
用户登录模块功能结构图,如图4.1所示:
管理员用户功能结构图。如图4.2所示:
学生用户功能结构图,如图4.3所示:
教师用户功能结构图,如图4.4所示:
系统主页面分为三部分,分别是头部,左侧菜单栏和右侧主内容区,在之前的设计中大多使用iframe标签进行布局,但我从网上了解到这个设计有很大的弊端,比如:
页面样式调试麻烦,出现多个滚动条
浏览器的后退按钮失效
过多会增加服务器的HTTP请求
小型的移动设备无法完全显示框架
产生多个页面,不易管理
不容易打印
代码复杂,无法被一些搜索引擎解读
经过查阅资料,我了解到目前主流的应用都使用了ajax代替了iframe。把你本来想创建的iframe换成DIV。然后点击菜单的时候,调用ajax或者.load,调用后台,返回数据之后,直接填充到DIV里即可。
部分实现代码如下:
//左侧菜单代码
<ul class="list-group" id="nav">
<li class="list-group-item li1" ><b>教学资料</b></li>
<li class="list-group-item li" ><a target="data/list">资料列表</a></li>
<li class="list-group-item li" ><a target="././data_upload">资料上传</a></li>
</ul>
//AJAX部分代码
$("#nav .li").click(function(){
var current = $(this);
target = current.find('a').attr('target'); //找到a的链接
$(".li").removeClass("active1");
current.addClass("active1");
$.get(target,function(data){
$("#navContent").html(data);
});
});
系统主界面如图4.5所示:
用户登录模块
功能描述:用户只有通过登录成功后才能进入系统,进行相应的操作。
用户登录功能流程图,如图4.6所示
//登录判断代码
@RequestMapping(value="/login")
public void login(String role,String username,String password,String rem,HttpServletRequest request,HttpServletResponse response) throws IOException{
User auser=null;
auser=new User();
auser.setPassword(password);
auser.setUsername(username);
auser.setRole(role);
boolean flag=userService.login(auser);
PrintWriter out = response.getWriter();
if(flag){//记住我
if("true".equals(rem)){
System.out.println(URLEncoder.encode(username,"utf-8"));
System.out.println(URLEncoder.encode(role,"utf-8"));
Cookie cook =new
Cookie("username",URLEncoder.encode(username,"utf-8"));
cook.setMaxAge(14*24*60*60); //两个星期
response.addCookie(cook);
Cookie cook1 =new
Cookie("role",URLEncoder.encode(role,"utf-8"));
cook1.setMaxAge(14*24*60*60); //两个星期
response.addCookie(cook1);
}
HttpSession session=request.getSession();
session.setAttribute("username", username);
session.setAttribute("role", role);
out.print("1");//返回登录信息
}else{
out.print("0");
}
out.flush();
out.close();
}
用户登录界面如图4.7所示:
教学资料模块
教学资料模块包括资料列表和资料上传两个部分。
//资料列表功能代码
@RequestMapping(value="/list")
public ModelAndView list(Integer currPage,String soukey){
ModelAndView mv=new ModelAndView();
String key="%%";
if(soukey!=null){
key="%"+soukey+"%";
}
int pageSize=5;
if(currPage==null||currPage==0){
currPage=1;
}
int index=(currPage-1)*pageSize;
int totalCount=Integer.parseInt(dataService.findCount(key)
.get(0).get("count(id)").toString());
Page page=new Page();
page.setPageSize(pageSize);
page.setTotalCount(totalCount);
page.setCurrPage(currPage);
mv.addObject("page", page);
List<Map<String,Object>> list=dataService.findAll(index,pageSize,key);
mv.addObject("list", list);
mv.addObject("key",soukey);
mv.setViewName("list");
return mv;
}
资料列表界面如图4.8所示:
资料上传界面如图4.9所示:
教学视频模块
教学视频模块分为视频列表和视频上传两部分。
//视频上传功能代码
@RequestMapping(value="/upload")
public ModelAndView upload(HttpServletRequest request,HttpServletResponse response) throws IOException{
multipartRequest=(MultipartHttpServletRequest)request;
String title="";
String path="";
String author="";
String fname="";
response.setContentType("text/html;charset=utf-8");
try {
//1.创建DiskFileItemFactory工厂对象
DiskFileItemFactory factory=new DiskFileItemFactory();
File f=new File("E:\\temp");
if(!f.exists())
{
f.mkdirs();
}
//2.创建ServletFileUpload对象
ServletFileUpload fileupload=new ServletFileUpload(factory);
fileupload.setHeaderEncoding("utf-8");
//3.解析request,得到上传文件的FileItem对象
List<FileItem> fileitems=fileupload.parseRequest(request);
//获取字符流
PrintWriter writer=response.getWriter();
//遍历集合
for(FileItem fileitem:fileitems){
//判断是否为普通字段
if(fileitem.isFormField()){
//获得字段名和字段值
String name=fileitem.getFieldName();
if(name.equals("name"))
{
//如果name不为空,将其保存在value中
if(!fileitem.getString().equals(""))
{
String value=fileitem.getString("utf-8");
writer.print("上传者:"+value+"<br/>");
author=value;
}
}
}else{
//获取上传文件名
String filename=fileitem.getName();
//数据表标题
title=filename;
//处理上传文件
if(filename!=null&&!filename.equals("")){
writer.print("上传的文件名称是:"+filename+"<br/>");
//截取出文件名
filename=filename.substring(filename.lastIndexOf("\\")+1);
//文件名需要唯一
filename=UUID.randomUUID().toString()+"_"+filename;
fname=filename;
//在服务器上创建同名文件
String webPath="/upload/";
//组合成完整的服务器路径
String filepath=request.getServletContext()
.getRealPath(webPath+filename);
path=filepath;
//创建文件
File file=new File(filepath);
file.getParentFile().mkdirs();
file.createNewFile();
//获得上传文件流
InputStream in=fileitem.getInputStream();
//使用FileOutputStream打开服务器端的上传文件
FileOutputStream out=new FileOutputStream(file);
//流的对拷
byte[] buffer=new byte[1024];//每次读取一个字节
int len;
//上传文件的字节输出到服务器的上传文件输出流中
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
//关闭流
in.close();
out.close();
//删除临时文件
fileitem.delete();
writer.print("上传成功!<br/>");
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
Video video=new Video();
video.setTitle(title);
video.setAuthor(author);
video.setPath("upload\\"+fname);
System.out.println(fname);
video.setTime(new Date());
videoService.add(video);
return list(1,null);
}
视频列表界面如图4.10所示:
视频上传界面如图4.11所示:
视频在线播放界面如图4.12所示:
试题资料模块
试题资料模块包括试题列表和试题上传两部分。
//试题下载功能代码
@RequestMapping(value=("/download"))
public void download(HttpServletRequest request,HttpServletResponse response) throws IOException{
/*
* 获取下载地址,下载
*/
//获取相对路径
String filename = request.getParameter("path");
//获取要下载的文件的物理路径
String filepath = request.getServletContext().getRealPath("/")+filename;
int index = filename.lastIndexOf("/");
if(index!=-1)
filename = filename.substring(index+1);//获取文件名
// 为了使下载框中显示中文文件名称不出乱码!
String framename = filenameEncoding(filename, request);
String contentType = request.getServletContext()
.getMimeType(filename);//通过文件名称获取MIME类型
String contentDisposition = "attachment;filename=" + framename;
//为了显示下载框
// 输入流
FileInputStream input = new FileInputStream(filepath); //设置头
response.setHeader("Content-Type", contentType);
response.setHeader("Content-Disposition", contentDisposition);
// 获取绑定了响应端的流(输出流)
ServletOutputStream output = response.getOutputStream();
IOUtils.copy(input, output);//把输入流中的数据写入到输出流中。
input.close();
}
试题列表界面,如图4.13所示:
试题上传界面,如图4.14所示:
用户管理模块
学生和教师用户的账号需要由管理员用户来添加和分配,用户管理模块主要包括学生管理、教师管理和用户添加三部分。
//用户信息添加和编辑代码
@RequestMapping(value="/edit")
public ModelAndView edit(String id,String role,String username,String password,String sex,String email,String phone,String birthday) throws ParseException{
ModelAndView mv=new ModelAndView();
User auser=new User();
auser.setRole(role);
auser.setUsername(username);
auser.setPassword(password);
auser.setSex(sex);
auser.setEmail(email);
auser.setPhone(phone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date date = formatter.parse(birthday);
auser.setBirthady(date);
if(id==null||"".equals(id)){
userService.addUser(auser);
}else{
auser.setId(Integer.parseInt(id));
userService.editUser(auser);
}
return list(role,1,null);
}
学生用户管理界面,如图4.15所示:
教师用户管理界面,如图4.16所示:
用户添加界面,如图4.17所示:
论坛系统模块
论坛系统包括论坛列表和发表帖子两部分。
//帖子回复功能代码
@RequestMapping(value="/replyAdd")
public ModelAndView replyAdd(String forumid,String author,String lou,String content){
//敏感词过滤
content=KeyWordFilter.keyWordFilter(content);
Reply areply=new Reply();
areply.setForumid(Integer.parseInt(forumid));
areply.setAuthor(author);
areply.setContent(content);
areply.setTime(new Date());
areply.setLou(Integer.parseInt(lou));
forumService.replyAdd(areply);
return show(forumid,1);
}
论坛列表界面,如图4.18所示:
论坛发帖界面,如图4.19所示:
帖子详情界面,如图4.20所示:
保存登录功能
//保存用户信息到cookie中
if("true".equals(rem)){
Cookie cook =new Cookie("username",URLEncoder.encode(username,"utf-8"));
cook.setMaxAge(14*24*60*60); //两个星期
response.addCookie(cook);
Cookie cook1 =new Cookie("role",URLEncoder.encode(role,"utf-8"));
cook1.setMaxAge(14*24*60*60); //两个星期
response.addCookie(cook1);
}
//从cookie中读取用户信息
Cookie cookies[] =request.getCookies();
if(cookies!=null){
for(int i=0;i<cookies.length;i++){
if(cookies[i].getName().equals("username")){
String username=cookies[i].getValue();
session.setAttribute("username", URLDecoder.decode(username, "utf-8"));
}
if(cookies[i].getName().equals("role")){
String role=cookies[i].getValue();
session.setAttribute("role", URLDecoder.decode(role, "utf-8"));
}
}
}
用户登录界面如下:
AJAX动态验证功能
//用户登录功能AJAX代码
$.ajax({
url:"user/login",
data:{role:$("#role").val(),username:$("#username").val(),password:$("#password").val(),rem:$("#rem").is(':checked')},
dataType: 'text',
type: 'post',
scriptCharset: 'utf-8',
success:function(result){
if(eval("("+result+")")=="0"){
$("#unerr").removeClass("text-success");
$("#unerr").addClass("text-danger");
$("#unerr").text("用户名或密码错误");
$("#username").focus();
}else if(eval("("+result+")")=="1"){
window.location.href = "user/success";
}
}
});
用户名密码验证和验证码验证界面如图4.22所示:
登录时输入错误,并不会提示登录失败,而是网页直接报错
提交表单时出现乱码
rs.next()不能正确获取数据库中的数据
不知道什么时候使用post提交,什么时候使用get提交。
登录判断页面(login_do.jsp)中,登录信息session的保存没有放在判断是否为空的判断语句(if(list!=null))中,导致登录失败也会保存session,这时就无法正确获取登录信息,导致网页报错。将session放在判断语句中就可以解决
表单提交时以get的请求发送到tomcat服务器后又会以默认的(ISO8859-1)解码,这时会出现中文乱码,改为post提交方式就解决了
ResultSet是一个结果集,即ResultSet存有一个表(通过执行查询数据库的语句生成),该表的当前行可以访问(当前行的初始位置是null),可以使用rs.next()方法移动到下一行(即表的第一行),如果新的当前行有效(即有值)就返回true,然后就可以使用get方法获取该行各列的值了,如果不存在下一行,则返回 false;因为这个方法会抛出一个SQLException,故要捕捉(try-catch)。直接使用rs.next()不能获取,前面要加上判断语句(if(rs.next)或while(rs.next))
get方法传输数据会在地址栏显示,并且数据不能过长,但会优先读取本地缓存,很多时候会加速用户访问。一般获取数据用get,进行数据更改用post。
以下测试均以管理员身份进行登录,测试师生交流系统的各项功能。
用户登录输入管理员用户密码,选择管理员角色,如图6.1所示:
点击登录按钮,跳转进入系统主界面,如图6.2所示:
由上图可知,用户登录功能运行成功。
对教学资料、教学视频、试题资料、用户资料、论坛帖子的增删改查和资料下载功能较为类似,这里以教学资料为例进行测试。
资料列表功能测试
点击左侧菜单“教学资料”,再点击“资料列表”,进入资料列表界面。资料列表界面如图6.3所示:
点击右侧“下载”,可以进行资料的下载,如图6.4所示。
资料上传功能测试
点击左侧菜单中的“资料上传”,进入资料上传界面,输入作者信息,选择资料文件,如图6.5所示:
点击“提交”按钮,提示“成功”,跳转进入资料列表界面,可以看到刚添加的信息,如图6.6所示:
查询资料功能测试
进入资料列表,在上方的查询框中输入标题的关键字,如图6.7所示:
点击“搜索”按钮,后台查询并显示要查询的信息,如图6.8所示:
教学资料的删除功能测试
这里进行批量删除功能的测试,进入资料列表,选中需要删除的资料,如下图所示:
点击“批量删除”按钮,成功删除指定信息,并自动刷新界面,如图6.10所示:
教学视频播放测试
点击左侧“视频列表”菜单,点击标题或右侧的“播放”,即可进入播放界面,如图6.11所示:
论坛系统测试
点击右侧“论坛系统”菜单,再点击“论坛”,进入论坛列表界面,如图6.12所示:
点击标题,进入帖子详情界面,如图6.13所示:
在下方的回复栏中可以进行帖子回复,如图6.14所示:
帖子发表功能测试
点击右侧“发表帖子”菜单,进入发表帖子页面,填写信息,如图6.14所示:
点击“提交”按钮,帖子成功发表,并转到论坛列表界面,如图6.15所示:
经过这段时间的课设学习,我收获了很多。在自己的努力和老师的耐心指导下,终于完成了这次课设的内容。这其中的酸甜苦辣只有经历过才体会得到,曾无数次找错误找到崩溃,无数次想代码想到忘记吃饭,这一刻才体会到收获的喜悦,这是发自内心的。
同时在这次课设中,我培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。我学会了很多学习的方法。而这是日后最实用的。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我的将来也有很大的帮助。以后,不管有多苦,我想我都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。以后遇到困难的问题,我除了苦恼,更多的是欣喜,因为解决了它我就能成长。
我明白了自己知识还比较欠缺,只是学习书本知识还是远远不够的,自己不会的东西还有太多,学习需要自己长期的积累,在以后的学习、工作中都应该不断的学习,将课本的理论知识与生活中的实践知识相结合,不断提高自己文化知识和实践能力。
[1] 张娜. JavaWeb开发技术教程(第二版).清华大学出版社,2018.1
[2] 王珊,萨师煊.数据库系统概论(第5版).高等教育出版社,2017.3
[3] Cay S. Horstmann / Gary Cornell. JAVA核心技术(卷1) 机械工业出版社,2008
[4] [美] Bruce Eckel. Java编程思想 [第4版] 机械工业出版社,2007
keyboard_arrow_left上一篇 : 基于QT和UDP Socket实现的即时通信软件 基于C#实现的电影院售票管理系统 : 下一篇keyboard_arrow_right