基于Java的MVC框架的图书推荐系统展示平台设计
目 录
摘 要 1
Abstract 2
引 言 1
1 文献综述 2
1.1 课题背景 2
1.1.1 图书推荐系统发展背景 2
1.1.2 主要技术发展背景 3
1.2 开展研究的意义 4
1.3 论文研究内容 4
1.4 论文的组织结构 5
2 框架与工具介绍 6
2.1 Maven介绍 6
2.1.1 Maven概述 6
2.1.2 Maven概念 6
2.2 Git介绍 8
2.2.1 Git概述 8
2.2.2 Git特性 9
2.3 MVC模式与Spring Framework框架 11
2.3.1 MVC模式 11
2.3.2 Spring MVC框架 12
2.4 MyBatis介绍 15
2.5 Bootstrap介绍 16
2.5.1 Bootstrap概述 16
2.5.2 结构和功能 16
2.6 jQuery介绍 17
2.7 小结 18
3 基于Web的图书推荐系统展示平台设计 20
3.1 系统总体设计 20
3.1.1 总体功能描述 20
3.1.2 系统模块组成 20
3.2 模块详细设计 23
3.2.1 数据库设计 23
3.2.2 页面原型设计 27
3.3 小结 29
4 基于Web的图书推荐系统展示平台实现 30
4.1 环境的搭建 30
4.1.1 数据库的建立与数据的导入 30
4.1.2 工程建立 30
4.1.3 版本控制 32
4.1.4 MyBatis配置 32
4.2 数据的清洗 34
4.3 系统开发 36
4.3.1 控制器类 36
4.3.2 模块类 38
4.3.3 视图类 39
4.4 分析及调优 40
4.5 性能测试 42
4.6 小结 43
结 论 44
参 考 文 献 45
附 录 46
附录A 外文参考文献原文 46
附录B 外文参考文献译文 55
在 学 取 得 成 果 63
致 谢 64
3 基于Web的图书推荐系统展示平台设计
3.1 系统总体设计
3.1.1 总体功能描述
本课题是要开发一套轻量级、功能完善的基于Web的图书推荐系统展示平台。利用此平台,对图书信息进行展示与推荐,对用户提供注册与登录功能。由于原始数据为从豆瓣依照网站网页结构抓取得来,并不适用于系统直接读取,于是需要将原始数据表格进行重新设计,遍历分离所需数据存入新设计的表中,使其可以更便捷的查询与处理。开发过程需要考虑Spring MVC框架,将功能按照模块、视图、控制器三部分分离,模块与视图适度的模块化使其可以较好的重用。beans使用注解来注入,这样可以提高小的个人项目的开发效率。在开发开始,配置Maven来解决需要的依赖包,创建Git仓库,来控制版本。
3.1.2 系统模块组成
首先将系统在Spring MVC的基础上分为了三层,分别为:Web层,服务及模块层,数据层,而Web层中,分为Controller与View模块,View为Controller服务,按照预定义的格式来展示Controller的数据。Controller将数据访问与一些公共的逻辑算法交给Model来处理,Model将处理结果交还给Controller。而Model类就像前面Controller给他的任务,负责与界面无关的逻辑计算与数据库的访问、以及其它格式数据的获取。结构如图3.1所示。
图3.1 系统结构设计
Web层负责处理用户的请求,其中Controller会接收DispatcherServlet分发过来的请求,Controller调用服务与模块层中的模块,进过逻辑计算,生成最终的数据,将数据通过键值对的方式,将视图通过字符串方式传递给DispatcherServlet,DispatcherServlet再读取对应的View,使用View作为模板,生成最终的页面,返回给用户。
服务与模块层负责逻辑计算与数据获取。其中MyBatis Mapping模块为通过MyBatis Generator自动生成的DAO类,以及自定义的DAO类,用于连接MySQL数据库并且执行增删改查操作。而逻辑计算与数据获取模块包含了公共方法类,某些特殊的算法计算,以及对配置文件的查询取值。
最底下的数据层,包括数据库系统与文件系统,是用来存储数据与配置的层。其中数据库采用MySQL数据库,配置文件使用Java自带的.properties文件。
三层之间是互相独立的,只有最近的两层之间可以访问:服务与模块层只可以访问数据层,而Web层只可以调用服务与模块层。其中,服务与模块层中的逻辑计算与数据获取模块,每个模块之间是相互独立的,模块与模块之间不可以互相访问,这样用来降低耦合性,每个模块完成一个完整的任务。由于Web请求的模式决定Web应用只能是被动接收请求,并且Web应用没有涉及费时的网络获取,在代码中没有回调函数,所以层与层之间的调用为单向的,即模块层只可调用数据层,让数据层来执行操作,然后返回数据给模块,Web层调用模块层,将一些逻辑计算与数据获取的过程交给模块来完成,结果返回给Web层,而不可能模块层主动的调用Web层,来对其中的值进行更改,而后返回给用户一个新的页面。在Web层中,View模块只负责对数据进行格式化,生成最终用户页面,因此,它只接收Controller模块的值,而与程序的其它层次模块之间不可以通信。这样,在编写Controller模块时,并不需要了解数据库的组织结构以及配置文件的具体文件名等,只需要知道调用哪个模块,将需要的参数传入模块,模块返回的值就是所需要的数据。而在编写View模块时,也不需要了解其它各个层次都有什么作用,只需要分析页面哪个部分的数据是动态获取的,本文转载自http://www.biyezuopin.vip/onews.asp?id=13875然后将此部分数据安排给Controller,让Controller传过来就可以了,这样将不同模块之间的耦合性降到了最低。而Controller就像一个乐队的指挥,按照需求调用各个模块,让系统的各个部分井然有序的工作。
package cn.edu.ustb.controller;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import javax.annotation.Resource;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import cn.edu.ustb.dm.dao.BookInfoMapper;
import cn.edu.ustb.dm.dao.BookPublishingInfoMapper;
import cn.edu.ustb.dm.dao.BookTagRelationMapper;
import cn.edu.ustb.dm.dao.TagInfoMapper;
import cn.edu.ustb.dm.model.BookInfo;
import cn.edu.ustb.dm.model.BookInfoExample;
import cn.edu.ustb.dm.model.BookPublishingInfoExample;
import cn.edu.ustb.dm.model.BookPublishingInfoWithBLOBs;
import cn.edu.ustb.dm.model.BookTagRelation;
import cn.edu.ustb.dm.model.BookTagRelationExample;
import cn.edu.ustb.dm.model.TagInfo;
import cn.edu.ustb.dm.model.TagInfoExample;
import cn.edu.ustb.model.BookListItemModel;
import cn.edu.ustb.model.BookClassifyItemModel;
@Controller
public class IndexController {
@Resource
private SqlSessionFactory sqlSessionFactory;
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
private Properties properties;
private SqlSession session;
private BookInfoMapper bookInfoMapper;
private BookPublishingInfoMapper bookPublishingMapper;
private TagInfoMapper tagInfoMapper;
private BookTagRelationMapper bookTagRelationMapper;
private List<BookListItemModel> bookRecommendList;
private List<BookClassifyItemModel> bookRecommendClassifyList;
private List<BookListItemModel> bookRankList;
private Properties getProperties() {
if(properties == null) {
properties = new Properties();
try {
InputStream in = getClass().getResourceAsStream("/Web.properties");
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
return properties;
}
private BookInfoMapper getBookInfoMapper() {
if(bookInfoMapper == null) {
bookInfoMapper = session.getMapper(BookInfoMapper.class);
}
return bookInfoMapper;
}
private BookPublishingInfoMapper getBookPublishingMapper() {
if(bookPublishingMapper == null) {
bookPublishingMapper = session.getMapper(BookPublishingInfoMapper.class);
}
return bookPublishingMapper;
}
private TagInfoMapper getTagInfoMapper() {
if(tagInfoMapper == null) {
tagInfoMapper = session.getMapper(TagInfoMapper.class);
}
return tagInfoMapper;
}
private BookTagRelationMapper getBookTagRelationMapper() {
if(bookTagRelationMapper == null) {
bookTagRelationMapper = session.getMapper(BookTagRelationMapper.class);
}
return bookTagRelationMapper;
}
private List<BookListItemModel> getBookRecommendList() {
if(bookRecommendList == null) {
bookRecommendList = new ArrayList<BookListItemModel>(6);
BookInfoExample infoExample = new BookInfoExample();
infoExample.setOrderByClause("NUMBER_TOREAD DESC limit 30");
infoExample.or().andTITLE_PAGE_IMAGESIsNotNull();
List<BookInfo> bookInfoList = getBookInfoMapper().selectByExample(infoExample);
int i=0;
for(BookInfo bookInfo : bookInfoList) {
logger.info("bookInfo i = " + i);
if(bookInfo.getTITLE_PAGE_IMAGES().trim().length() != 0) {
if(i<6)
i++;
else
break;
logger.info("bookInfo with image i = " + i);
BookListItemModel item = new BookListItemModel();
item.setId(bookInfo.getBOOK_ID());
item.setImageSrc(getProperties().getProperty("book_mpic") + bookInfo.getTITLE_PAGE_IMAGES());
item.setTitle(bookInfo.getTITLE());
BookPublishingInfoExample publishingExample = new BookPublishingInfoExample();
publishingExample.or().andBook_idEqualTo(bookInfo.getBOOK_ID());
List<BookPublishingInfoWithBLOBs> bookPublishingList =
getBookPublishingMapper().selectByExampleWithBLOBs(publishingExample);
item.setAuthor(bookPublishingList.get(0).getAuther_name());
item.setStar(bookInfo.getNUMBER_STAR1(), bookInfo.getNUMBER_STAR2(),
bookInfo.getNUMBER_STAR3(), bookInfo.getNUMBER_STAR4(),
bookInfo.getNUMBER_STAR5());
bookRecommendList.add(item);
}
}
}
return bookRecommendList;
}
private List<BookClassifyItemModel> getBookRecommendClassifyList() {
if(bookRecommendClassifyList == null) {
bookRecommendClassifyList = new ArrayList<BookClassifyItemModel>(12);
TagInfoExample tagExample = new TagInfoExample();
tagExample.setOrderByClause("COUNT DESC limit 12");
List<TagInfo> tagInfoList = this.getTagInfoMapper().selectByExample(tagExample);
for(int i=0; i<12&&i<tagInfoList.size(); i++) {
TagInfo tagInfo = tagInfoList.get(i);
BookClassifyItemModel item = new BookClassifyItemModel();
item.setTagName(tagInfo.getNAME());
BookTagRelationExample relationExample = new BookTagRelationExample();
relationExample.or().andTAG_IDEqualTo(tagInfo.getTAG_ID());
List<BookTagRelation> relationList =
getBookTagRelationMapper().selectByExample(relationExample);
List<BookClassifyItemModel.TitleList> titleList = new ArrayList<BookClassifyItemModel.TitleList>(2);
int j = 0;
for(BookTagRelation relation : relationList) {
BookInfoExample bookExample = new BookInfoExample();
bookExample.or().andBOOK_IDEqualTo(relation.getBOOK_ID());
List<BookInfo> bookList = getBookInfoMapper().selectByExample(bookExample);
if(bookList.size() > 0) {
BookInfo bookInfo = bookList.get(0);
if(bookInfo.getTITLE_PAGE_IMAGES() != null &&
bookInfo.getTITLE_PAGE_IMAGES().trim().length() != 0) {
if(j<2)
j++;
else
break;
if(j == 1)
item.setImageSrc(getProperties().getProperty("book_mpic")
+ bookInfo.getTITLE_PAGE_IMAGES());
BookClassifyItemModel.TitleList title = item.createTitleList();
title.setId(bookInfo.getBOOK_ID());
title.setTitle(bookInfo.getTITLE());
titleList.add(title);
}
}
}
item.setTitleList(titleList);
bookRecommendClassifyList.add(item);
}
}
return bookRecommendClassifyList;
}
private List<BookListItemModel> getBookRankList() {
if(bookRankList == null) {
bookRankList = new ArrayList<BookListItemModel>(16);
BookInfoExample example = new BookInfoExample();
example.setOrderByClause("NUMBER_REVIEW DESC limit 40");
example.or().andTITLE_PAGE_IMAGESIsNotNull();
List<BookInfo> bookList = getBookInfoMapper().selectByExample(example);
int i = 0;
for(BookInfo bookInfo : bookList) {
if(bookInfo.getTITLE_PAGE_IMAGES().trim().length() != 0) {
if(i<16)
i++;
else
break;
BookListItemModel item = new BookListItemModel();
item.setId(bookInfo.getBOOK_ID());
item.setImageSrc(getProperties().getProperty("book_mpic")
+ bookInfo.getTITLE_PAGE_IMAGES());
item.setTitle(bookInfo.getTITLE());
bookRankList.add(item);
}
}
}
return bookRankList;
}
@RequestMapping(value="/", method = RequestMethod.GET)
public String index(Locale locale, Model model){
session = sqlSessionFactory.openSession();
try {
model.addAttribute("bookRecommendList", getBookRecommendList());
model.addAttribute("bookRecommendClassifyList", getBookRecommendClassifyList());
model.addAttribute("bookRankList", getBookRankList());
session.commit();
} finally {
session.close();
}
return "index";
}
}
还没有评论,来说两句吧...