有话要说:

这次准备讲述后台服务器的搭建以及前台访问到数据的过程。

成果:

准备:

  1. 安装了eclipse
  2. 安装了Tomcat7
  3. 安装了数据库管理工具:Navicat

搭建服务器:

用eclipse直接创建一个web工程,并将运行环境设置为Tomcat7

接着定义了四个类来实现了一个简单的接口(通过servlet的方式),下面来看看这四个类

NewsBean.java

 package com.lanxingren.bean;

 import java.util.List;

 public class NewsBean {

     //段子标识
private int id; //段子文本
private String title; //段子包含的图片链接
private List<String> urls; //段子点赞数
private int like; //段子点踩数
private int unlike; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public List<String> getUrls() {
return urls;
} public void setUrls(List<String> urls) {
this.urls = urls;
} public int getLike() {
return like;
} public void setLike(int like) {
this.like = like;
} public int getUnlike() {
return unlike;
} public void setUnlike(int unlike) {
this.unlike = unlike;
} @Override
public String toString() {
return "NewsBean [id=" + id + ", title=" + title + ", urls=" + urls + ", like=" + like + ", unlike=" + unlike
+ "]";
} }

该类是段子类的一个bean类,各个属性代表的意思在代码里已经说清楚了。

DatabaseUtil.java

 package com.lanxingren.util;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet; public class DatabaseUtil { private static String url = "jdbc:mysql://localhost:3306/imitating9gag?serverTimezone=GMT%2B8&useSSL=false";
private static String user = "root";
private static String password = "root"; private static Connection conn; //获取数据库连接
public static Connection getConnection() { try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
} return conn;
} //关闭数据库连接
public static void close (Connection conn, PreparedStatement ps) {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} //关闭数据库连接
public static void close (Connection conn, PreparedStatement ps, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} }

该类是一个工具类,主要用来创建数据库连接以及关闭数据库连接。

其中,由于MySQL更新到了最新的版本,所以设置了useSSL为false,否则连接会出问题。

而且,最新的MySQL其实并不需要通过Class.forName来加载驱动了。

NewsDAO.java

 package com.lanxingren.dao;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import com.lanxingren.bean.NewsBean;
import com.lanxingren.util.DatabaseUtil; public class NewsDAO { //page是页数,pageSize是每页条数
public List<NewsBean> queryNewsByPage (int page, int pageSize) {
List<NewsBean> newsList = new ArrayList<NewsBean>(); Connection conn = DatabaseUtil.getConnection(); String sql = "select * from news order by id desc limit " + (page - 1)*pageSize + ", " + pageSize;
PreparedStatement pstmt = null; try {
pstmt = (PreparedStatement)conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
NewsBean nb = new NewsBean();
nb.setId(rs.getInt("id"));
nb.setTitle(rs.getString("title"));
nb.setLike(rs.getInt("like"));
nb.setUnlike(rs.getInt("unlike"));
newsList.add(nb);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
DatabaseUtil.close(conn, pstmt);
} return newsList;
} // 根据段子id获取段子所包含的图片
public List<String> queryUrlsByNewsId (int newsId) {
List<String> urls = new ArrayList<String>(); Connection conn = DatabaseUtil.getConnection(); String sql = "select url from news_pics where newsid = " + newsId;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
urls.add(rs.getString("url"));
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
DatabaseUtil.close(conn, pstmt);
} return urls;
} }

该类定义了两个方法,分别为获取段子信息的方法和获取图片的方法。

其中sql用了倒序是为了让段子按照时间流的顺序在前台展示。

QueryNewsServlet.java

package com.lanxingren.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson;
import com.lanxingren.bean.NewsBean;
import com.lanxingren.dao.NewsDAO; @WebServlet("/QueryNewsServlet")
public class QueryNewsServlet extends HttpServlet {
private static final long serialVersionUID = 1L; int pageSize = 5; public QueryNewsServlet() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/json; charset=utf-8");
PrintWriter out = response.getWriter(); String page = request.getParameter("page");
List<NewsBean> newsList = new ArrayList<NewsBean>();
List<NewsBean> realList = new ArrayList<NewsBean>();
NewsDAO dao = new NewsDAO(); String news = ""; if (page != null) {
newsList = dao.queryNewsByPage(Integer.parseInt(page), pageSize);
} if (newsList != null && newsList.size() > 0) {
for (NewsBean nb : newsList) {
List<String> urls = dao.queryUrlsByNewsId(nb.getId());
if (urls != null && urls.size() > 0) {
nb.setUrls(urls);
realList.add(nb);
}
}
} Gson gson = new Gson();
news = gson.toJson(realList); out.print(news);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
} }

通过注解的方式来设置servlet的地址,并将数据转化成json输出。

通过以上的方式,就完成了后台查询段子接口的开发,并且可通过page参数来获取第page页的信息,接口URL为:http://localhost:8080/Imitating9GAG/QueryNewsServlet?page=2

接着,将项目在Tomcat下启动后台服务器就正式搭建完成了,通过该URL获取的数据见下图:

前台获取数据并展示:

 public List<NewsBean> newsBeans = new ArrayList<NewsBean>();// 段子集合
private String baseUrl = "http://192.168.10.14:8080/Imitating9GAG/QueryNewsServlet?page=";
 new Thread(new Runnable() {
@Override
public void run() {
String url = baseUrl + (currentPage);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
String json = response.body().string();
if (json != null) {
Gson gson = new Gson();
newsBeans.addAll(0, (List<NewsBean>)gson.fromJson(json, new TypeToken<List<NewsBean>>(){}.getType()));
}
Message message = new Message();
message.what = QUERY_NEWS;
handler.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();

由于请求网络是一个耗时操作,因此放进了子线程中。在子线程中请求网络并将返回的数据放入段子集合中。

Handler如下:

  // 请求网络结束后的更新View
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case QUERY_NEWS:
recyclerView.getAdapter().notifyDataSetChanged();
break;
case UPDATE_NEWS:
recyclerView.getAdapter().notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
break;
case LOAD_MORE:
((NewsAdapter)recyclerView.getAdapter()).changeStatus(NewsAdapter.UNLOADING);
currentState = NewsAdapter.UNLOADING;
break;
}
}
};

结束语:

这样,获取数据+后台服务器搭建+前台页面展示的过程整个就已经完整了。

下一篇准备讲述官方自带的SwipeRefreshLayout刷新控件。

由于该控件没有上拉加载功能,于是就在RecyclerView中实现了上拉加载功能。

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

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

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

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

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

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

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

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

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

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

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

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

  6. BabyLinux制作过程详解

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

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

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

  8. 用AE如何制作如下三个loading动效,

    在本期象牙绘UED团队分享当中,我们将详细演示用AE如何制作如下三个loading动效, 其中涉及到AE表达式的应用.值曲线调整.速度曲线编辑等知识. 对于初学者来说可能信息量略大,希望通过是视频教程 ...

  9. Android 仿PhotoShop调色板应用(三) 主体界面绘制

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 仿PhotoShop调色板应用(三) 主体界面绘制    关于PhotoShop调色板应用的实现我总结了两个最核心的部分:   1 ...

随机推荐

  1. &和&&的共同点和区别、Java字符含义和Java创建对象的几种方式

    一.&和&&的共同点和区别 1.&和&&的联系(共同点): &和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定. 操 ...

  2. Redis安装及使用详解

    推荐在Linux系统上安装,这里我采用CentOS6: Redis采用3.0.0版本,官网下载即可 由于Redis是C语言编写,需要安装gcc(部分Linux自带gcc) yum install gc ...

  3. [Swift]LeetCode26. 删除排序数组中的重复项 | Remove Duplicates from Sorted Array

    Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...

  4. [Swift]LeetCode153. 寻找旋转排序数组中的最小值 | Find Minimum in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  5. [Swift]LeetCode333. 最大的二分搜索子树 $ Largest BST Subtree

    Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest mea ...

  6. [Swift]LeetCode684. 冗余连接 | Redundant Connection

    In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...

  7. zookeeper使用详解(命令、客户端、源码)

    1. zookeeper使用详解(命令.客户端.源码) 1.1. 前言   zookeeper我们常用来做分布式协调中间件,很多时候我们都接触不到它的原理和用法,我对他的了解也仅限于知道它可以做分布式 ...

  8. 利用Zabbix来监控Windows Performance Counter

    Windows的性能计数器提供了很多系统的性能指标度量,通过Windows的性能计数器,我们可以对Windows的服务器的当前运行状态有个即时的情况了解. Zabbix Agent支持(Win) pe ...

  9. 解决同一页面中两个iframe互相调用jquery,js函数

    这一个月又没更新博客,唉,懒癌又犯了,今天解决了一个问题,关于两个iframe互相调用jquery函数方法 a.html中有两个iframe,如下: <iframe width="10 ...

  10. 好用的函数,assert,random.sample,seaborn tsplot, tensorflow.python.platform flags 等,持续更新

    python 中好用的函数,random.sample等,持续更新 random.sample random.sample的函数原型为:random.sample(sequence, k),从指定序列 ...