有话要说:

在做完了数据展示功能之后,就想着完善整个APP。发现现在后台非常的混乱,有好多点都不具备,比方说:图片应该有略缩图和原图,段子、评论、点赞应该联动起来,段子应该有创建时间等。

于是就重新设计了数据库,重新爬取了数据,重新设计了后台接口。

这次主要讲这次重构的主要内容。

数据库设计:

一共设计了六张表,分别为

  1. 段子表,主要存放每一个段子的图片等信息
  2. 评论表,主要存放评论信息,评论可以上传图片
  3. 用户表
  4. 标签表,每条段子发表之前会自定义标签,该表存放的就是这些标签
  5. 点赞记录表,因为用户点赞与段子之间是多对多的关系,因此要加一张表用来存放点赞记录
  6. 段子标签关联表,因为段子和标签是多对多的,因此需要多一张表存放关联关系

接口设计:

橙色的为表,咖啡色为接口。

目前设计了十四个接口,上图写明了各接口和相关的表之间的关系。

后台结构:

bean包下为基本实体类;

implement包下为消息实体类的子类;

dao包为涉及到数据库的具体实现类;

servlet为接口类;

util为过程中用到的工具类。

具体例子:

下面以查询段子接口为例,介绍具体的结构。

bean类:

消息实体类:

 public class MessageEntity {

     // 返回信息描述
private String reason;
// 返回码
private int errorCode; public String getReason() {
return reason;
} public void setReason(String reason) {
this.reason = reason;
} public int getErrorCode() {
return errorCode;
} public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
} }

段子消息实体类:

 public class TopicMessageEntity extends MessageEntity {

     // 获取段子的结果
private List<TopicEntity> result; public List<TopicEntity> getResult() {
return result;
} public void setResult(List<TopicEntity> result) {
this.result = result;
} }

段子实体类:

 public class TopicEntity {

     // 段子标识
private int id;
// 段子作者
private String author = "";
// 段子标题
private String title = "";
// 段子点赞数
private int upvote;
// 段子评论数
private int commentCount;
// 段子略缩图地址
private String thumbNail = "";
// 段子原图地址
private String orgPicture = "";
// 段子发表时间
private String postTime = ""; // 点的是赞还是踩,0代表没点,1代表赞,-1代表踩
private int like = 0; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getAuthor() {
return author;
} public void setAuthor(String author) {
this.author = author;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public int getUpvote() {
return upvote;
} public void setUpvote(int upvote) {
this.upvote = upvote;
} public int getCommentCount() {
return commentCount;
} public void setCommentCount(int commentCount) {
this.commentCount = commentCount;
} public String getThumbNail() {
return thumbNail;
} public void setThumbNail(String thumbNail) {
this.thumbNail = thumbNail;
} public String getOrgPicture() {
return orgPicture;
} public void setOrgPicture(String orgPicture) {
this.orgPicture = orgPicture;
} public String getPostTime() {
return postTime;
} public void setPostTime(String postTime) {
this.postTime = postTime;
} public int getLike() {
return like;
} public void setLike(int like) {
this.like = like;
} }

这里和数据库表略有不同,主要是like字段。

like字段代表的是当前获取数据的人对该段子是否点了赞。

dao层:

查询段子方法:

 public List<TopicEntity> query(int topicId, int count, boolean after) {
List<TopicEntity> topicList = new ArrayList<TopicEntity>(); if (topicId <= 0) {
topicId = 0;
} if (count <= 0) {
count = 10;
} if (after) {
queryAfter(topicId, count, topicList);
} else {
queryBefore(topicId, count, topicList);
} return topicList;
}
 private void queryAfter(int topicId, int count, List<TopicEntity> topicList) {
String queryAfter = "SELECT * FROM 9gag_topics WHERE id > ? LIMIT ?"; Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null; try {
pstmt = conn.prepareStatement(queryAfter);
pstmt.setInt(1, topicId);
pstmt.setInt(2, count);
rs = pstmt.executeQuery(); while (rs.next()) {
TopicEntity topicEntity = new TopicEntity();
topicEntity.setId(rs.getInt("id"));
topicEntity.setAuthor(rs.getString("author"));
topicEntity.setTitle(rs.getString("title"));
topicEntity.setUpvote(rs.getInt("upvote"));
topicEntity.setCommentCount(rs.getInt("commentcount"));
topicEntity.setThumbNail(rs.getString("thumbnail"));
topicEntity.setOrgPicture(rs.getString("orgpicture"));
topicEntity.setPostTime(rs.getString("posttime"));
topicList.add(topicEntity);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DatabaseUtil.close(conn, pstmt, rs);
}
}
 private void queryBefore(int topicId, int count, List<TopicEntity> topicList) {
String queryBefore = "SELECT * FROM 9gag_topics WHERE id < ? ORDER BY id DESC LIMIT ?"; Connection conn = DatabaseUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null; try {
pstmt = conn.prepareStatement(queryBefore);
pstmt.setInt(1, topicId);
pstmt.setInt(2, count);
rs = pstmt.executeQuery(); while (rs.next()) {
TopicEntity topicEntity = new TopicEntity();
topicEntity.setId(rs.getInt("id"));
topicEntity.setAuthor(rs.getString("author"));
topicEntity.setTitle(rs.getString("title"));
topicEntity.setUpvote(rs.getInt("upvote"));
topicEntity.setCommentCount(rs.getInt("commentcount"));
topicEntity.setThumbNail(rs.getString("thumbnail"));
topicEntity.setOrgPicture(rs.getString("orgpicture"));
topicEntity.setPostTime(rs.getString("posttime"));
topicList.add(topicEntity);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DatabaseUtil.close(conn, pstmt, rs);
} // 获取完数据之后逆序,因为查找的时候是逆序
Collections.reverse(topicList);
}

这三个方法实现了查询指定段子前(或者后)count条记录。

servlet层:

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/json; charset=utf-8");
PrintWriter out = response.getWriter(); TopicMessageEntity message = new TopicMessageEntity();
TopicDAO topicDao = new TopicDAO();
UpvoteDAO upvoteDao = new UpvoteDAO();
Gson gson = GsonUtil.getGson(); request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8"); int topicId = Integer.parseInt(request.getParameter("topicId"));
int count = Integer.parseInt(request.getParameter("count"));
boolean after = Boolean.parseBoolean(request.getParameter("after"));
String author = request.getParameter("author"); if (count <= 0) {
message.setErrorCode(-1);
message.setReason("count值不能为负数!");
out.print(gson.toJson(message));
return;
} try {
List<TopicEntity> topics = topicDao.query(topicId, count, after); // 判断作者是否点过赞
if (author != null) {
List<UpvoteEntity> upvoteList = upvoteDao.findUpvoteByAuthor(author, true);
if (upvoteList != null) {
for (TopicEntity topic : topics) {
for (UpvoteEntity upvote : upvoteList) {
if (upvote.getLikedId() == topic.getId()) {
int like = upvote.isLiked() ? 1 : -1;
topic.setLike(like);
}
}
}
}
} Collections.reverse(topics);
message.setErrorCode(0);
message.setReason("success");
message.setResult(topics);
} catch (Exception e) {
message.setErrorCode(-1);
message.setReason(e.getMessage());
} finally {
out.print(gson.toJson(message));
} }

主要逻辑:查找到需要的段子→遍历段子→如果段子被点过赞或者踩,就把段子相应字段更改为赞或者踩→由于查出来的数据时顺序的,要改为逆序展示。

反思:

这次主要重构了后台的设计逻辑,其实还有好多不完备的地方。

通过这次重构,明白了一个要点。要做一件事情首先要规划好,首先是设计,把一切的流程,框架设计好之后按部就班的做。这样做出来的东西才会比较好。

否则在过程中会很混乱,严重影响效率。

预告:

下一章准备讲述点赞的逻辑,因为点赞的逻辑比较复杂。

大家如果有什么疑问或者建议可以通过评论或者邮件的方式联系我,欢迎大家的评论~

仿9GAG制作过程(五)的更多相关文章

  1. 仿9GAG制作过程(一)

    有话要说: 准备开始学习Android应用程序的一个完整的设计过程.准备做一个仿9GAG的APP,前端界面设计+后台数据爬虫+后台接口设计,整个流程体验一遍.今天准备先把前端界面的框架给完成了. 成果 ...

  2. 仿9GAG制作过程(四)

    有话要说: 这次主要讲述主页面下拉刷新和上拉加载功能的实现. 主要是使用了SwipeRefreshLayout的布局方式,并在此基础上通过RecyclerView的特性增加了上拉加载的功能. 成果: ...

  3. 仿9GAG制作过程(三)

    有话要说: 这次准备讲述后台服务器的搭建以及前台访问到数据的过程. 成果: 准备: 安装了eclipse 安装了Tomcat7 安装了数据库管理工具:Navicat 搭建服务器: 用eclipse直接 ...

  4. 仿9GAG制作过程(二)

    有话要说: 这次准备讲述用python爬虫以及将爬来的数据存到MySQL数据库的过程,爬的是煎蛋网的无聊图. 成果: 准备: 下载了python3.7并配置好了环境变量 下载了PyCharm作为开发p ...

  5. BabyLinux制作过程详解

    转:http://www.360doc.com/content/05/0915/14/1429_12641.shtml BabyLinux制作过程详解 作者:GuCuiwen email:win2li ...

  6. [PCB制作] 1、记录一个简单的电路板的制作过程——四线二项步进电机驱动模块(L6219)

    前言 现在,很多人手上都有一两个电子设备,但是却很少有人清楚其中比较关键的部分(PCB电路板)是如何制作出来的.我虽然懂点硬件,但是之前设计的简单系统都是自己在万能板上用导线自己焊接的(如下图左),复 ...

  7. rpt水晶报表制作过程

    原文:rpt水晶报表制作过程 最近公司安排一个以前的项目,里面需要用到水晶报表,由于原来做这个项目的同事离职,所在公司的同事报表做成了rdlc类型的,而这类报表在加载的时候很难动态的从数据库加载数据, ...

  8. Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程

    Android实训案例(九)--答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程 项目也是偷师的,决心研究一下数据库.所以写的还是很详细的,各位看官,耐着性子看完,实现结果不重要 ...

  9. [转帖]超能课堂 CPU制作过程

    http://www.expreview.com/50814.html 一般来说,我们对IC芯片的了解仅限于它概念,但是对于已经应用到各式各样的数码产品中IC芯片是怎么来的?大家可能只知道制作IC芯片 ...

随机推荐

  1. 从SQL注入到内网漫游

    前言 在一次渗透实战中,发现了一个注入点,最后成功的漫游了内网. 正文 在渗透中遇到一个站点,顺手测试了一下,在搜索框随便输入了一个字符加个单引号直接报错了,差不多可以确认这里存在注入了.一般这种站安 ...

  2. 交叉编译 tcpdump

    目录 1. 下载 tcpdump 2. 交叉编译 3. 相关说明 1. 下载 tcpdump 官网:http://www.tcpdump.org/ 2. 交叉编译 交叉编译libpcap: $ wge ...

  3. 受到 1 万点暴击,二狗子被 DDoS 攻击的惨痛经历

    二狗子的遭遇 “好消息,好消息,免费 DDoS 攻击软件上线了,性感黑客在线攻击,帮您攻克所有商业难题.”二狗子不知道在看着什么网站,新买的 Mac 中发出热闹的声音. 二狗子想知道“DDoS 是什么 ...

  4. Python爬虫入门教程 25-100 知乎文章图片爬取器之一

    1. 知乎文章图片写在前面 今天开始尝试爬取一下知乎,看一下这个网站都有什么好玩的内容可以爬取到,可能断断续续会写几篇文章,今天首先爬取最简单的,单一文章的所有回答,爬取这个没有什么难度. 找到我们要 ...

  5. 封装cookie设置和获取的简易方法

    (function() { var tool = { expires: "expires", // 过期时间expires path: "path", // 路 ...

  6. 我对C#的认知。

    关于开发者的技术水平到底该如何定义,到底一个人的技术水平应该定位在高.中.低的标准是什么呢?很多人觉得这是一个仁者见仁的问题,有人觉得根据公司的那个员工等级判断.答案是肯定不是,从纯开发技术的角度来分 ...

  7. MaxCompute/DataWorks权限问题排查建议

    MaxCompute/DataWorks权限问题排查建议 __前提:__MaxCompute与DataWorks为两个产品,在权限体系上既有交集又要一定的差别.在权限问题之前需了解两个产品独特的权限体 ...

  8. Java提高班(五)深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

  9. Java并发专题(一)认识线程

    1.1 认识线程 线程是轻量级进程,也是程序执行的一个路径,每一个线程都有自己的局部变量表.程序计数器(指向正在执行的指令指针)以及各自的生命周期,现代操作系统中一般不止一个线程在运行.比如说,当我们 ...

  10. 找到bug的根源,问五次为什么

    在学习<问题分析与解决>时学到了一种找到问题根源的方法——问五次为什么.具体内容是:当遇到一个问题,不要只看当前答案,要继续往下问,为什么,连问五次,就能够找到更深层次的问题.最近在复盘b ...