仿9GAG制作過程(三)
阿新 • • 發佈:2018-06-08
url thread for and 實現 pri baseurl set ted
有話要說:
這次準備講述後臺服務器的搭建以及前臺訪問到數據的過程。
成果:
準備:
- 安裝了eclipse
- 安裝了Tomcat7
- 安裝了數據庫管理工具:Navicat
搭建服務器:
用eclipse直接創建一個web工程,並將運行環境設置為Tomcat7
接著定義了四個類來實現了一個簡單的接口(通過servlet的方式),下面來看看這四個類
NewsBean.java
1 package com.lanxingren.bean; 2 3 import java.util.List; 4 5 public class NewsBean { 6 7 //段子標識8 private int id; 9 10 //段子文本 11 private String title; 12 13 //段子包含的圖片鏈接 14 private List<String> urls; 15 16 //段子點贊數 17 private int like; 18 19 //段子點踩數 20 private int unlike; 21 22 public int getId() { 23 return id; 24 } 25 26 publicvoid setId(int id) { 27 this.id = id; 28 } 29 30 public String getTitle() { 31 return title; 32 } 33 34 public void setTitle(String title) { 35 this.title = title; 36 } 37 38 public List<String> getUrls() { 39 return urls; 40 } 41 42public void setUrls(List<String> urls) { 43 this.urls = urls; 44 } 45 46 public int getLike() { 47 return like; 48 } 49 50 public void setLike(int like) { 51 this.like = like; 52 } 53 54 public int getUnlike() { 55 return unlike; 56 } 57 58 public void setUnlike(int unlike) { 59 this.unlike = unlike; 60 } 61 62 @Override 63 public String toString() { 64 return "NewsBean [id=" + id + ", title=" + title + ", urls=" + urls + ", like=" + like + ", unlike=" + unlike 65 + "]"; 66 } 67 68 }
該類是段子類的一個bean類,各個屬性代表的意思在代碼裏已經說清楚了。
DatabaseUtil.java
1 package com.lanxingren.util; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 8 public class DatabaseUtil { 9 10 private static String url = "jdbc:mysql://localhost:3306/imitating9gag?serverTimezone=GMT%2B8&useSSL=false"; 11 private static String user = "root"; 12 private static String password = "root"; 13 14 private static Connection conn; 15 16 //獲取數據庫連接 17 public static Connection getConnection() { 18 19 try { 20 Class.forName("com.mysql.cj.jdbc.Driver"); 21 conn = DriverManager.getConnection(url, user, password); 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 26 return conn; 27 } 28 29 //關閉數據庫連接 30 public static void close (Connection conn, PreparedStatement ps) { 31 try { 32 if (ps != null) { 33 ps.close(); 34 } 35 if (conn != null) { 36 conn.close(); 37 } 38 } catch (Exception e) { 39 e.printStackTrace(); 40 } 41 } 42 43 //關閉數據庫連接 44 public static void close (Connection conn, PreparedStatement ps, ResultSet rs) { 45 try { 46 if (rs != null) { 47 rs.close(); 48 } 49 if (ps != null) { 50 ps.close(); 51 } 52 if (conn != null) { 53 conn.close(); 54 } 55 } catch (Exception e) { 56 e.printStackTrace(); 57 } 58 } 59 60 }
該類是一個工具類,主要用來創建數據庫連接以及關閉數據庫連接。
其中,由於MySQL更新到了最新的版本,所以設置了useSSL為false,否則連接會出問題。
而且,最新的MySQL其實並不需要通過Class.forName來加載驅動了。
NewsDAO.java
1 package com.lanxingren.dao; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 import com.lanxingren.bean.NewsBean; 11 import com.lanxingren.util.DatabaseUtil; 12 13 public class NewsDAO { 14 15 //page是頁數,pageSize是每頁條數 16 public List<NewsBean> queryNewsByPage (int page, int pageSize) { 17 List<NewsBean> newsList = new ArrayList<NewsBean>(); 18 19 Connection conn = DatabaseUtil.getConnection(); 20 21 String sql = "select * from news order by id desc limit " + (page - 1)*pageSize + ", " + pageSize; 22 PreparedStatement pstmt = null; 23 24 try { 25 pstmt = (PreparedStatement)conn.prepareStatement(sql); 26 ResultSet rs = pstmt.executeQuery(); 27 while (rs.next()) { 28 NewsBean nb = new NewsBean(); 29 nb.setId(rs.getInt("id")); 30 nb.setTitle(rs.getString("title")); 31 nb.setLike(rs.getInt("like")); 32 nb.setUnlike(rs.getInt("unlike")); 33 newsList.add(nb); 34 } 35 } catch (SQLException e) { 36 e.printStackTrace(); 37 } 38 finally { 39 DatabaseUtil.close(conn, pstmt); 40 } 41 42 return newsList; 43 } 44 45 // 根據段子id獲取段子所包含的圖片 46 public List<String> queryUrlsByNewsId (int newsId) { 47 List<String> urls = new ArrayList<String>(); 48 49 Connection conn = DatabaseUtil.getConnection(); 50 51 String sql = "select url from news_pics where newsid = " + newsId; 52 PreparedStatement pstmt = null; 53 try { 54 pstmt = conn.prepareStatement(sql); 55 ResultSet rs = pstmt.executeQuery(); 56 while (rs.next()) { 57 urls.add(rs.getString("url")); 58 } 59 } catch (Exception e) { 60 e.printStackTrace(); 61 } 62 finally { 63 DatabaseUtil.close(conn, pstmt); 64 } 65 66 return urls; 67 } 68 69 }
該類定義了兩個方法,分別為獲取段子信息的方法和獲取圖片的方法。
其中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獲取的數據見下圖:
前臺獲取數據並展示:
1 public List<NewsBean> newsBeans = new ArrayList<NewsBean>();// 段子集合 2 private String baseUrl = "http://192.168.10.14:8080/Imitating9GAG/QueryNewsServlet?page=";
1 new Thread(new Runnable() { 2 @Override 3 public void run() { 4 String url = baseUrl + (currentPage); 5 OkHttpClient client = new OkHttpClient(); 6 Request request = new Request.Builder() 7 .url(url) 8 .build(); 9 try { 10 Response response = client.newCall(request).execute(); 11 String json = response.body().string(); 12 if (json != null) { 13 Gson gson = new Gson(); 14 newsBeans.addAll(0, (List<NewsBean>)gson.fromJson(json, new TypeToken<List<NewsBean>>(){}.getType())); 15 } 16 Message message = new Message(); 17 message.what = QUERY_NEWS; 18 handler.sendMessage(message); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 } 23 }).start();
由於請求網絡是一個耗時操作,因此放進了子線程中。在子線程中請求網絡並將返回的數據放入段子集合中。
Handler如下:
1 // 請求網絡結束後的更新View 2 private Handler handler = new Handler() { 3 @Override 4 public void handleMessage(Message msg) { 5 switch (msg.what) { 6 case QUERY_NEWS: 7 recyclerView.getAdapter().notifyDataSetChanged(); 8 break; 9 case UPDATE_NEWS: 10 recyclerView.getAdapter().notifyDataSetChanged(); 11 swipeRefreshLayout.setRefreshing(false); 12 break; 13 case LOAD_MORE: 14 ((NewsAdapter)recyclerView.getAdapter()).changeStatus(NewsAdapter.UNLOADING); 15 currentState = NewsAdapter.UNLOADING; 16 break; 17 } 18 } 19 };
結束語:
這樣,獲取數據+後臺服務器搭建+前臺頁面展示的過程整個就已經完整了。
下一篇準備講述官方自帶的SwipeRefreshLayout刷新控件。
由於該控件沒有上拉加載功能,於是就在RecyclerView中實現了上拉加載功能。
大家如果有什麽疑問或者建議可以通過評論或者郵件的方式聯系我,歡迎大家的評論~
仿9GAG制作過程(三)