欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

仿9GAG制作过程(五)

程序员文章站 2022-03-21 19:42:43
有话要说: 在做完了数据展示功能之后,就想着完善整个APP。发现现在后台非常的混乱,有好多点都不具备,比方说:图片应该有略缩图和原图,段子、评论、点赞应该联动起来,段子应该有创建时间等。 于是就重新设计了数据库,重新爬取了数据,重新设计了后台接口。 这次主要讲这次重构的主要内容。 数据库设计: 一共 ......

有话要说:

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

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

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

数据库设计:

 仿9GAG制作过程(五)

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

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

接口设计:

仿9GAG制作过程(五)

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

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

后台结构:

仿9GAG制作过程(五)

bean包下为基本实体类;

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

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

servlet为接口类;

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

具体例子:

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

bean类:

消息实体类:

 1 public class MessageEntity {
 2 
 3     // 返回信息描述
 4     private String reason;
 5     // 返回码
 6     private int errorCode;
 7 
 8     public String getReason() {
 9         return reason;
10     }
11 
12     public void setReason(String reason) {
13         this.reason = reason;
14     }
15 
16     public int getErrorCode() {
17         return errorCode;
18     }
19 
20     public void setErrorCode(int errorCode) {
21         this.errorCode = errorCode;
22     }
23 
24 }

 

段子消息实体类:

 1 public class TopicMessageEntity extends MessageEntity {
 2 
 3     // 获取段子的结果
 4     private List<TopicEntity> result;
 5 
 6     public List<TopicEntity> getResult() {
 7         return result;
 8     }
 9 
10     public void setResult(List<TopicEntity> result) {
11         this.result = result;
12     }
13 
14 }

 

 段子实体类:

 1 public class TopicEntity {
 2 
 3     // 段子标识
 4     private int id;
 5     // 段子作者
 6     private String author = "";
 7     // 段子标题
 8     private String title = "";
 9     // 段子点赞数
10     private int upvote;
11     // 段子评论数
12     private int commentCount;
13     // 段子略缩图地址
14     private String thumbNail = "";
15     // 段子原图地址
16     private String orgPicture = "";
17     // 段子发表时间
18     private String postTime = "";
19     
20     // 点的是赞还是踩,0代表没点,1代表赞,-1代表踩
21     private int like = 0;
22 
23     public int getId() {
24         return id;
25     }
26 
27     public void setId(int id) {
28         this.id = id;
29     }
30 
31     public String getAuthor() {
32         return author;
33     }
34 
35     public void setAuthor(String author) {
36         this.author = author;
37     }
38 
39     public String getTitle() {
40         return title;
41     }
42 
43     public void setTitle(String title) {
44         this.title = title;
45     }
46 
47     public int getUpvote() {
48         return upvote;
49     }
50 
51     public void setUpvote(int upvote) {
52         this.upvote = upvote;
53     }
54 
55     public int getCommentCount() {
56         return commentCount;
57     }
58 
59     public void setCommentCount(int commentCount) {
60         this.commentCount = commentCount;
61     }
62 
63     public String getThumbNail() {
64         return thumbNail;
65     }
66 
67     public void setThumbNail(String thumbNail) {
68         this.thumbNail = thumbNail;
69     }
70 
71     public String getOrgPicture() {
72         return orgPicture;
73     }
74 
75     public void setOrgPicture(String orgPicture) {
76         this.orgPicture = orgPicture;
77     }
78 
79     public String getPostTime() {
80         return postTime;
81     }
82 
83     public void setPostTime(String postTime) {
84         this.postTime = postTime;
85     }
86 
87     public int getLike() {
88         return like;
89     }
90 
91     public void setLike(int like) {
92         this.like = like;
93     }
94 
95 }

 

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

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

dao层:

查询段子方法:

 1 public List<TopicEntity> query(int topicId, int count, boolean after) {
 2         List<TopicEntity> topicList = new ArrayList<TopicEntity>();
 3 
 4         if (topicId <= 0) {
 5             topicId = 0;
 6         }
 7 
 8         if (count <= 0) {
 9             count = 10;
10         }
11 
12         if (after) {
13             queryAfter(topicId, count, topicList);
14         } else {
15             queryBefore(topicId, count, topicList);
16         }
17 
18         return topicList;
19     }
 1 private void queryAfter(int topicId, int count, List<TopicEntity> topicList) {
 2         String queryAfter = "SELECT * FROM 9gag_topics WHERE id > ? LIMIT ?";
 3 
 4         Connection conn = DatabaseUtil.getConnection();
 5         PreparedStatement pstmt = null;
 6         ResultSet rs = null;
 7 
 8         try {
 9             pstmt = conn.prepareStatement(queryAfter);
10             pstmt.setInt(1, topicId);
11             pstmt.setInt(2, count);
12             rs = pstmt.executeQuery();
13 
14             while (rs.next()) {
15                 TopicEntity topicEntity = new TopicEntity();
16                 topicEntity.setId(rs.getInt("id"));
17                 topicEntity.setAuthor(rs.getString("author"));
18                 topicEntity.setTitle(rs.getString("title"));
19                 topicEntity.setUpvote(rs.getInt("upvote"));
20                 topicEntity.setCommentCount(rs.getInt("commentcount"));
21                 topicEntity.setThumbNail(rs.getString("thumbnail"));
22                 topicEntity.setOrgPicture(rs.getString("orgpicture"));
23                 topicEntity.setPostTime(rs.getString("posttime"));
24                 topicList.add(topicEntity);
25             }
26         } catch (SQLException e) {
27             e.printStackTrace();
28         } finally {
29             DatabaseUtil.close(conn, pstmt, rs);
30         }
31     }
 1 private void queryBefore(int topicId, int count, List<TopicEntity> topicList) {
 2         String queryBefore = "SELECT * FROM 9gag_topics WHERE id < ? ORDER BY id DESC LIMIT ?";
 3 
 4         Connection conn = DatabaseUtil.getConnection();
 5         PreparedStatement pstmt = null;
 6         ResultSet rs = null;
 7 
 8         try {
 9             pstmt = conn.prepareStatement(queryBefore);
10             pstmt.setInt(1, topicId);
11             pstmt.setInt(2, count);
12             rs = pstmt.executeQuery();
13 
14             while (rs.next()) {
15                 TopicEntity topicEntity = new TopicEntity();
16                 topicEntity.setId(rs.getInt("id"));
17                 topicEntity.setAuthor(rs.getString("author"));
18                 topicEntity.setTitle(rs.getString("title"));
19                 topicEntity.setUpvote(rs.getInt("upvote"));
20                 topicEntity.setCommentCount(rs.getInt("commentcount"));
21                 topicEntity.setThumbNail(rs.getString("thumbnail"));
22                 topicEntity.setOrgPicture(rs.getString("orgpicture"));
23                 topicEntity.setPostTime(rs.getString("posttime"));
24                 topicList.add(topicEntity);
25             }
26         } catch (SQLException e) {
27             e.printStackTrace();
28         } finally {
29             DatabaseUtil.close(conn, pstmt, rs);
30         }
31 
32         // 获取完数据之后逆序,因为查找的时候是逆序
33         Collections.reverse(topicList);
34     }

 

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

 servlet层:

 1 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         response.setContentType("text/json; charset=utf-8");
 4         PrintWriter out = response.getWriter();
 5 
 6         TopicMessageEntity message = new TopicMessageEntity();
 7         TopicDAO topicDao = new TopicDAO();
 8         UpvoteDAO upvoteDao = new UpvoteDAO();
 9         Gson gson = GsonUtil.getGson();
10 
11         request.setCharacterEncoding("utf-8");
12         response.setCharacterEncoding("utf-8");
13 
14         int topicId = Integer.parseInt(request.getParameter("topicId"));
15         int count = Integer.parseInt(request.getParameter("count"));
16         boolean after = Boolean.parseBoolean(request.getParameter("after"));
17         String author = request.getParameter("author");
18 
19         if (count <= 0) {
20             message.setErrorCode(-1);
21             message.setReason("count值不能为负数!");
22             out.print(gson.toJson(message));
23             return;
24         }
25 
26         try {
27             List<TopicEntity> topics = topicDao.query(topicId, count, after);
28             
29             // 判断作者是否点过赞
30             if (author != null) {
31                 List<UpvoteEntity> upvoteList = upvoteDao.findUpvoteByAuthor(author, true);
32                 if (upvoteList != null) {
33                     for (TopicEntity topic : topics) {
34                         for (UpvoteEntity upvote : upvoteList) {
35                             if (upvote.getLikedId() == topic.getId()) {
36                                 int like = upvote.isLiked() ? 1 : -1;
37                                 topic.setLike(like);
38                             }
39                         }
40                     }                    
41                 }
42             }
43             
44             Collections.reverse(topics);
45             message.setErrorCode(0);
46             message.setReason("success");
47             message.setResult(topics);
48         } catch (Exception e) {
49             message.setErrorCode(-1);
50             message.setReason(e.getMessage());
51         } finally {
52             out.print(gson.toJson(message));
53         }
54 
55     }

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

结束语:

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

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

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

预告:

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

 

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