基于SSM和Boostrap实现的电影豆瓣网站
一、项目简介
1.1 研究目的
电影是一种表演艺术、视觉艺术及听觉艺术,利用胶卷、录像带或数字媒体将影像和声音捕捉起来,再加上后期的编辑工作而成。电影的奥秘它能够借由其影像表现出现实世界之丰富,而其本身任然停留在影像。电影是现在人们休闲的重要方式之一。电影里面往往都是:爱情、友情、生活、生命、现在、未来,不管是真实的、还是虚幻的,几乎每一部电影都能把一些种子植入你的大脑中,指不定哪天就发芽了。真的把一部部电影看进去了,它解决的绝对不是你的孤独、无聊。它会让你对生活有了新的看法,甚至会改变你人生的轨迹。
在科技高速发展的今天,人们的日常生活、工作、学习等活动,越来越依赖于网络。在物质生活过剩的今天,追求精神生活,就是很大一部分人对生活的定义。而从最早的黑白无声电影开始,通过一代又一代的影视大师的演绎,电影也成为了人们生活中必不可少的精神食粮。喜欢看电影的人很依赖电影网站,电影网站能提供热映电影、历史电影、电影分类、电影推荐、电影评论等内容。
1.2 发展概况
随着时代的发展,如雨后春笋般的出现了很多的电影网站,可是质量却是参差不齐。很多的电影类型的网站,在商业环境的影响下,通过在各大门户网站挂外链,采取非常规手段刷关键字等各种各样的方式,在网站推出的短时间内达到一个惊人的“浏览量”,而很多并不知情的网友们,恰恰就是通过判断这种“浏览量”来决定自己平时观看电影的时候所使用的网站。这就使得现如今能够适应国内平民家庭的电影评论网站或多或少都存在这样那样的安全问题,所以一个拥有简洁的界面,并且初期投入不多,拥有井井有条的内容,以及新鲜网站主题的电影类网站的出现就会大大的抓取广大电影爱好者的眼球。
1.3 开发工具的选择
1.3.1 IDE
IntelliJ IDEA是一种商业化销售的Java集成开发环境(Integrated Development Environment,IDE)工具软件,由捷克软件公司 JetBrains 在2001年1月时推出最初版。IntelliJ IDEA被认为是当前Java开发效率最快的IDE工具。它整合了开发过程中实用的众多功能,几乎可以不用鼠标可以方便的完成你要做的任何事情,最大程度的加快开发的速度。简单而又功能强大。与其他的一些繁冗而复杂的IDE工具有鲜明的对比。本网站开发IDE选择IDEA。
1.3.2 操作系统选择
代码部署在Linux机器上。
免费的操作系统
Linux是开源免费的操作系统,任何机构和个人都能自由的查看Linux的底层源码,并自由的修改和再发布。免费意味着零成本,无需购买任何licence,开发和部署都不需要花一分钱。
软件优势
Linux内置GCC、VI、Mysql等强大的编程软件和工具以及强大的命令行支持,你仅需几行命令就能完成一系列的工作。同时市面上的编程软件和工具几乎都对Linux支持最好,而在其它平台如windows可能支持不太好,甚至完全没法使用。
社区支持
开源的解决方案几乎都是最先基于Linux的,Linux有最强大的社区支持,几乎你遇到的任何问题都能在社区上找到答案,你所需要做的事情就是放心折腾,出现麻烦Google一下,或者去社区发帖求助,问题就能迎刃而解。
虽然Java是跨平台的语言,但Linux对Java提供了最好的支持。以最少的资源消耗,最方便的操作,优雅的完成你所需要的做事情。
1.3.3 Web容器选择
Web容器采用Nginx和Tomcat
Jsp容器采用Tomcat
Apache Tomcat是Apache基金会来发和维护的椅子Servlet容器,支持Servlet和Jsp,是世界上使用最广泛的Web容器。Tomcat的主要目的是实现Java Servlet API和执行Java Servlet构建动态网站。还可以使用Tomcat作为一个常规的HTTP服务器,静态页面,但这不是它的主要目的。Tomcat的Servlet引擎通常与Apache或者其他Web服务器一起工作。除了用于开发过程中的调试以及那些对速度和事务处理只有很小要求的用户,很少会将Tomcat单独作为Web服务器。但随着版本的更新,正有越来越多的用户将其单独作为Web服务器用以那些对速度和可靠性有较高要求的环境中。
静态资源、反向代理服务器采用Nignx
Nginx是HTTP反向代理服务器,邮件代理服务器,和通用的TCP代理服务器,相较于Apache、lighttpd等传统的HTTP Server具有占有内存少,稳定性高等优势。很多繁忙的网站都运行在Nginx上。与传统的服务器相比,Nginx并不依赖线程来处理请求。相反,它使用一个更加可伸缩的事件驱动架构(异步)。此体系结构占用的资源少但是负载巨大。即 使你不希望处理成千上万的同步请求,你仍然可以受益于Nginx的高性能和小内存占用。
自2004年发布以来,Nginx一直专注于高性能、高并发性和低内存的使用。拥有大量的Web服务器功能,如负载平衡、缓存、访问和带宽控制等,并且能够有效地集成各种应用程序。目前Nginx是互联网上第二流行的开源Web服务器。
1.3.4 数据库
数据库采用Mysql。
MySql是世界上最流行的开源数据库,Mysql完美支持高性能和可伸缩的网络和嵌入式数据库应用程序。由于Mysql可靠性好、性能高、成本低,吸引了很多开发者。大部分网站都使用Mysql,比如Google、Facebook等世界顶级的网站。
1.3.5 编程语言
编程语言采用Java Java是一种计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。Java是最流行的语言之一,国内外大型互联网公司大多使用Java。
1.3.6 编程框架
Bean管理使用Spring Framework
Spring Framework是一个开源的Java开发框架,它提供了一个全面的现代Java企业应用程序编程和配置模型——在任何类型的部署平台。使用Spring Framework,你可以专注于应用程序的业务逻辑,没必要关心特定的部署环境,也省去了大量复杂的帮助类和配置文件。基于控制反转(IOC)的配置管理让应用程序的组建开发变得更为简洁方便。Spring核心支持依赖注入、事务管理、Web应用程序、数据访问、消息传递等。Spring Framework能与市面上绝大部分的主流Java框架进行无缝集成和兼容。
MVC框架使用SpringMVC
Spring框架是一个流行的开源应用程序框架,它可以使Java EE开发变得更容易。它由一个容器,一个框架来管理组件,包含一组Web用户界面管理,事务和持久性。Spring Web MVC是Spring框架是的一部分,是一个用来创建Web应用程序的可扩展的MVC框架。
Spring Web MVC框架提供了模型-视图-控制器体系结构和组件,可以用来开发灵活、松散耦合的Web应用程序。MVC模式可以分离应用程序的不同方面(输入逻辑、业务逻辑和UI逻辑),同时提供这些元素之间的松散耦合。
层使用Hibernate
Hibernate是一个开源的Java持久性框架项目。执行强大的对象关系映射,使用HQL和SQL进行数据库查询。Hibernate是一个伟大的Java ORM映射工具。它可以减少大量的SQL操作带来的复杂性,并且对于SQL知识有限的开发者来说,带来了巨大的方便。
Hibernate是一个纯Java对象关系映射和持久性框架,允许你使用XML配置文件或者注解将普通旧式Java对象映射到关系数据库表。使用Hibernate项目可以节省大量的开发时间,因为整个JDBC层都是由框架在管理。这意味着您的应用程序的数据访问层将依赖于Hibernate,完全是从底层数据模型中抽象出来。
Hibernate有许多超过其他类似的对象-关系映射方法优点,Hibernate开放源码,免费使用,正在很多成熟的商业项目中广泛使用,并且有一个非常活跃的社区论坛。
二 系统分析
2.1 主要功能
-
一共有两个角色:评论人和管理员
-
评论人可以在网站中进行账号注册
-
评论人可以对电影进行简短评论、打分
-
管理员上传电影的画报、各类简介信息
-
网站根据某种规则自动统计、计算每部电影的分数情况
-
网站自动生成电影的排行榜
-
网站可以根据电影的年份或分数情况对电影进行自动排序
2.2 方案论证
2.2.1 设计原理
-
网站界面 :在界面上不追求奢华或者繁杂的功能,只追求两个字:“简洁”,通过干净的首页、功能、观看页面,让观看者体会到舒适的观看环境
-
功能实现 :通过判断登陆权限,以不同的身份登陆到网站,分为网站管理员以及会员。管理员拥有对节目单表的增删改查等操作,并且对网站内电影有简单的处理功能,意在对网站进行管理与维护;会员则区别于游客,登陆会员之后,可以对电影进行影评或与管理员交流等操作
-
内容多样 :通过管理员对信息的掌握程度以及采集速度的保证,每天进行更新内容的操作,并且通过挑选分类,精心的编排到各个模块。最好是用爬虫自动采集信息
2.2.2 方案选择
-
资源来源 :电影的信息一定要有稳定的来源,需要考察豆瓣电影API
-
爬取策略 :由于电影资源需要定期更新,需要设定爬虫的爬取策略
-
自动化处理 :对爬虫爬来的数据要进行自动化分类、处理,方便展示在页面上
-
评分规则制定 :因为电影需要根据评分排序,需要制定一个评分规则
-
角色界定 :系统需要根据用户不同的角色(访客、普通用户、管理员)来展示不同的界面
-
电影分类 :需要根据电影年份、类别等分类
2.3 基本思路
2.3.1 网站UI的思路
UI,对于设计者来说,可以算是最简单的地方;但对于用户一个良好的用户界面非常重要,普通用户根本不会关心你的界面时怎么实现的,他所关心的是UI是否美丽、大方、好看。如果一个网站的UI不好看,可能用户根本没有用下去的心思了。本网站使用Bootstrap作为UI框架,简单优美。
2.3.2 获取资源的思路
通过豆瓣电影API https://developers.douban.com/wiki/?title=movie_v2 ,制定合适的抓取策略,获得所需要的资源。
2.3.3 权限控制思路
网站分为管理员和前台用户,必须得根据权限来展示不同的界面和功能。可以利用Java注解来实现。注解可以看成是一个接口,注解实例就是一个实现了该接口的动态代理类。注解大多是用做对某个类、方法、字段进行说明,标识的。以便在程序运行期间我们通 过反射获得该字段或方法的注解的实例,来决定该做些什么处理或不该进行什么处理。
2.4 主要问题
设计网站时,主要有以下几个方面的问题要解决:如何设计网站的界面;如何提高丰富的内容;如果较为方便的筛选内容;如何提供下载地址。
2.5 网站要求
本网站要求能适配绝大部分浏览器,并且有较快的响应速度。
三、系统设计
3.1 概要设计
3.1.1 系统结构图
针对上面的需求分析,我们把整个系统分成三个模块:1、Model:实现数据抓取,数据处理等功能。2、View:实现网站的界面布局和接收用户响应。3、Controller用来接收view层的响应,转发给model层。
以下就是 系统结构图 :
3.1.2 系统组件图
构件是系统中遵从一组接口且提供其实现的物理的、可替换的部分。构建图显示构建与构建之间的相互关系。构件图是对系统物理方面建模的两个图之一。
系统的构件图
3.1.3 系统界面设计
系统界面主要有正在热映、分类、注册、登陆。
3.2 详细设计
3.2.1 版面设计
系统的界面是由由 html+css 来完成的,一个软件的成功与否,不仅在于软件本身的效率、稳定性、用户界面(UI)也是一项非常重要的因素。
HMTL是用来表述网页的一种语言。HTML文档=网页
HTML 标记标签通常被称为 HTML 标签 (HTML tag)。Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容。
-
与 之间的文本描述网页
-
与 之间的文本是可见的页面内容
-
与
之间的文本被显示为标题 -
与
之间的文本被显示为段落
3.2.2 功能设计
主要有正在热映、分类、排行、注册、登陆。
-
首页 :首先进入的是首页,首页展示正在热映的电影的海报和概要信息,点击可以进入具体电影的详情页
-
注册、登录 :网站发布评论需要先注册和登录,注册时候需要限制用户用户名格式
-
分类 :需要根据条件去筛选电影和排序,并根据关键字搜索
四、系统实现
4.1 创建系统外观界面
根据网站的需要设计网页,主要分为首页、注册、登陆、分类等界面,有公共的头部和尾部。用Html+Css+Bootstrap实现。
4.2 获取图片功能的实现
为了增加响应速度,图片从豆瓣上抓取下来,上传到七牛云。
java
public static void uploadToQiniu(String from, String subjectId) {
String to = BUCKET_NAME.concat(":").concat(subjectId);
String encodeFrom = EncodeUtils.urlsafeEncode(from);
String encodeTo = EncodeUtils.urlsafeEncode(to);
String url = "http://iovip.qbox.me/fetch/" + encodeFrom + "/to/" + encodeTo;
Mac mac = new com.qiniu.api.auth.digest.Mac(QiniuUtils.ACCESS_KEY, QiniuUtils.SECRET_KEY);
Client client = new DigestAuthClient(mac);
CallRet ret = client.call(url);
}
4.3 根据条件排序和筛选功能的实现
可以根据电影年份、地区、类型、关键字进行筛选,按照热门、评分、上映日期进行排序:
java
public List<Subject> listBySearch(int start, int end, String year, String place, String type, String sort, String key) {
Criteria criteria = getCurrentSession().createCriteria(Subject.class);
if (!year.contains("不限")) {
criteria.add(Restrictions.eq("year", new Short(year)));
}
if (!place.contains("不限")) {
criteria.add(Restrictions.like("countries", "%".concat(place).concat("%")));
}
if (!type.contains("不限")) {
criteria.add(Restrictions.like("genres", "%".concat(type).concat("%")));
}
if (sort.equals("rating")) {
criteria.addOrder(OrderBySqlFormulaUtils.sqlFormula("totalRating / ratingCount desc"));
} else if (sort.equals("date")) {
criteria.addOrder(Order.desc("pubDate"));
} else if (sort.equals("hot")) {
criteria.addOrder(Order.desc("commentCount"));
}
if (StringUtils.isNotEmpty(key)) {
criteria.add(Restrictions.disjunction()
.add(Restrictions.like("title", "%".concat(key).concat("%")))
.add(Restrictions.like("originalTitle", "%".concat(key).concat("%")))
.add(Restrictions.like("casts", "%".concat(key).concat("%")))
.add(Restrictions.like("directors", "%".concat(key).concat("%")))
.add(Restrictions.like("writers", "%".concat(key).concat("%")))
);
}
criteria.setFirstResult(start);
criteria.setMaxResults(end);
return criteria.list();
}
4.4 基于注解的权限认证
网站需要区分管理员和普通用户,判断是否登陆等,来展示不同界面和功能:
-
可以继承springmvc的HandlerInterceptorAdapter,然后拦截每个请求,判断是否有@LoginRequired或者@AdminRequired的注解,如果有,记录下当前uri(base64 URLEncoder之后),然后401到登陆界面,登陆成功后再跳回来
-
可以在一个需要验证的Controller class上写上@LoginRequired,然后整个Controller的所有method都会去做权限验证
-
可以用@FreeAccess 去排除不需要的的method
代码如下:
java
public class AuthenticationFilter extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod method = (HandlerMethod) handler;
FreeAccess freeAccess = method.getMethodAnnotation(FreeAccess.class);
if (freeAccess != null) {
return true;
}
boolean adminRequired = AnnotationUtils.findAnnotation(method.getBean().getClass(), AdminRequired.class) != null
|| method.getMethodAnnotation(AdminRequired.class) != null;
boolean loginRequired = AnnotationUtils.findAnnotation(method.getBean().getClass(), LoginRequired.class) != null
|| method.getMethodAnnotation(LoginRequired.class) != null || adminRequired;
if (loginRequired && !checkLogin(request)) {
String url = request.getRequestURI();
String queryString = request.getQueryString();
if (StringUtils.isNotEmpty(queryString)) {
url = url + "?" + queryString;
}
url = new String(Base64.encodeBase64(url.getBytes()));
url = URLEncoder.encode(url);
//如果是ajax请求响应头会有,x-requested-with
if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
response.setHeader("sessionStatus", "timeout");//在响应头设置session状态
return false;
}
response.setStatus(401);
String redirectUrl = "/login?redirect=" + url;
response.sendRedirect(redirectUrl);
return false;
}
if (adminRequired && !checkAdmin(request)) {
response.setStatus(403);
response.sendRedirect("/403");
return false;
}
return true;
}
public boolean checkLogin(HttpServletRequest request) {
return ContextUtils.getSessionUtils(request).getUser() != null;
}
public boolean checkAdmin(HttpServletRequest request) {
User user = ContextUtils.getSessionUtils(request).getUser();
if (user == null) {
return false;
} else {
return user.isAdmin();
}
}
}
4.5 根据权限来展示界面
用户的评论有删除功能,只有用户本人和管理员才能删除评论。扩展Jsp的tag来实现这个功能。
java
public class SecurityTagHandler extends SimpleTagSupport {
@Setter
private String userId;
@Override
public void doTag() throws JspException, IOException {
SessionUtils sessionUtils = getSessionUtils();
if (null == sessionUtils) {
return;
}
User currentUser = sessionUtils.getUser();
if (null == currentUser) {
return;
}
if (currentUser.isAdmin() || currentUser.getId().equals(userId)) {
getJspBody().invoke(null);
}
return;
}
/**
* 获取当前的SessionUtils
*/
private SessionUtils getSessionUtils() {
JspContext jc = getJspContext();
Object sessionUtils = jc.getAttribute(ContextUtils.SESSIONUTILS, PageContext.SESSION_SCOPE);
if (sessionUtils != null && sessionUtils instanceof SessionUtils) {
return (SessionUtils) sessionUtils;
}
return null;
}
}
在页面下添加删除按钮:
html
<mv:securityTag userId="${comment.userId}">
<button type="button" class="edd_f7aa_aa9775e close btn-danger delete_comment"
data-dismiss="alert" value="${comment.id}">×
</button>
</mv:securityTag>
只要满足对应权限的用户才能删除评论。
4.6 定时更新正在热映电影
每天零点定时更新正在热映电影列表,用Spring注解来实现定时任务。
java
@Scheduled(cron = "0 0 0 * * ?") //每天零点执行一次
public void renewPlaying() {
String id;
List<Playing> playingList;
String responseBody = HttpClientUtils.get(DoubanServiceImpl.DOUBAN_PLAYING_URL);
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray jsonArray = jsonObject.getJSONArray("entries");
int length = jsonArray.length();
logger.debug("{} movies are playing", length);
playingList = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
id = jsonArray.getJSONObject(i).getString("id");
doubanService.find(id);
playingList.add(new Playing(id));
}
playingDao.renew(playingList);
}
4.7 前后端认证
对用户输入的数据要进行前后端验证,防止用户在数据库中插入非法数据。
前端用Js+正则表达式来验证
java
function checkLoginName() {
var jqCtrl = $("#txt_loginname");
var loginName = $.trim(jqCtrl.val());
if (!loginName) {
jqCtrl.focus();
return false;
}
var ret = clientValid.validate("LoginName", jqCtrl.val());
if (!ret.success) {
jqCtrl.focus();
tool.tooltip(jqCtrl, ret.comment, null, true);
return false;
}
//server validation
$.getJSON("checkUserName", {userName: loginName}, function (data) {
if (!data.success) {
jqCtrl.focus();
tool.tooltip(jqCtrl, data.comment, null, true);
return;
}
});
return true;
}
后端用hibernate-validator来实现
java
/**
* Validation constraints for loginName
* 限制登录名不能为手机号或者邮箱地址
*
* @author veryyoung
*/
@Pattern(regexp = "^(?!(([1][3|5|8][0-9]{9})|([\\\\w-]+(\\\\.[\\\\w-]+)*@[\\\\w-]+(\\\\.[\\\\w-]+)+)))([0-9a-zA-Z_\u4E00-\u9FBF]+)", message = "用户名为数字字母或汉字,不能为手机号或邮箱")
@NotNull(message = "用户名不能为空")
@Size(min = 2, max = 30, message = "用户名长度需为2-30位")
@Constraint(validatedBy = {})
@Target({ElementType.METHOD,
ElementType.FIELD,
ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserName {
String message() default "{common.loginName}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
用这个注解来修饰UserName,然后验证的时候只需要:
java
try {
getValidatorWrapper().tryValidate(user);
userService.create(user);
} catch (InvalidException ex) {
logger.error("Invalid User Object: {}", user.toString(), ex);
modelAndView.addObject("error", ex.getMessage());
return modelAndView;
}
五、系统运行
5.1 首页
进入首页显示的是正在热映的电影的海报和简要信息,点击能进入对应电影的详情页。
5.2 详情页
详情页能看到该电影的详细信息,并且提供了豆瓣链接和下载链接,同时下面有五条短评,可以在该节目发布评论,也可以点击链接查看所有评论。如果是管理员或评论作者,可以删除该评论。
5.3 评论页
评论页提供了所有评论(翻页实现)
5.4 发布评论
在电影详情页和评论页都可以对电影进行评论。
5.5 分类页
分类页可对电影进行搜索、分类、排序,方便更快的找到需要的信息。
5.6 注册&登录页
发布评论需要注册&登录。
5.7个人中心页
个人中心页可以查看用户发布的所有评论,如若有权限可以删除评论
总结
从最开始确定要写个电影网站,到这个网站的整体完成。我从中学到了不少知识与编程技巧。这为我将来的工作积累了一笔财富。虽然这个系统还不是很成熟,还比较简陋,但我可以很自豪的说,我是很认真的在写每一行代码,这个系统里的每一个细节我都了如指掌,收获很多,感触很多。
系统不足 :现在网站资源还很少,大部分电影都没有,很多资源都要实时从豆瓣获取,这无疑会拖慢网站的速度,可以制定抓取策略把豆瓣大部分电影都抓取过来,然后做更优雅的展示。
参考文献
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 齐齐哈尔合众商务科技有限公司门户网站设计(吉林大学·孟云飞)
- 基于关键词提取技术的协同过滤算法研究与应用(南京邮电大学·李吉祺)
- 具有反爬虫机制的影评系统的设计与实现(北京交通大学·高萍)
- Research and Development of Movie Recommendation System Based on Hybrid Recommendation Algorithm(首都经济贸易大学·石科)
- 基于协同过滤的视频推荐系统(山东大学·王雯思)
- 电影网站数据挖掘可视化系统设计与实现(华中科技大学·王志)
- 基于.net的动漫门户网站的设计与实现(吉林大学·王彦苹)
- 某高校电影交流论坛系统的设计与实现(北京邮电大学·张新宇)
- 电影网站数据挖掘可视化系统设计与实现(华中科技大学·王志)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 黑龙江高等职业教育状态数据采集平台网站内容生成系统的设计与实现(吉林大学·刘莹)
- 多功能影院网站的设计与开发(北京工业大学·郭光明)
- 思科亿网网上交易实现与安全研究(吉林大学·周威)
- 基于NTM神经网络的电影推荐系统的设计与实现(宁夏大学·朱楠)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕设港湾 ,原文地址:https://bishedaima.com/yuanma/35498.html