摘要:市長信箱郵件查詢服務使用構建工程一直想用做個微服務練練手為后續部署到打下基礎今天比較空閑就開始把部分想法落地了概覽用來練手的應用是一個市長信箱的內容抓取與檢索頁面鑒于我的八卦特質總想了解下周邊的一些投訴信息而成都的市長信箱是一個絕好的信息來
市長信箱郵件查詢服務: 使用SpringBoot構建工程
一直想用SpringBoot做個微服務,練練手, 為后續部署到docker打下基礎. 今天比較空閑, 就開始把部分想法落地了.
https://github.com/ybak/mycrawler
用來練手的demo應用是一個市長信箱的內容抓取與檢索頁面. 鑒于我的八卦特質,總想了解下周邊的一些投訴信息. 而成都的市長信箱是一個絕好的信息來源.
信件格式:來信情況 | 張三 |
---|---|
來信標題 | 生活困擾 |
來信內容 | 尊敬市長你好我們有十三戶污水到我處無法排走... |
辦理結果 | 郫縣(2016-05-20 11:31:10): 來信人: 您好! ... |
這個demo應用的主要功能有:
從市長信箱抓取所有的市民投訴并保存
提供按關鍵字檢索的web頁面來檢索感興趣的投訴信息
按照循序漸進的原則, 先實現只實現基本功能, 不考慮性能, 后續再進行優化.
Mysql的提供了基本的模糊匹配功能, 且SpringBoot中,能方便的集成JPA.
使用Mysql保存抓取信息, 并提供給Web應用查詢, 是很容易實現的. 所以該demo應用的第一版技術設計如下:
SpringBoot的代碼使用maven的多模塊組織:
父模塊(聲明此工程的spring-boot的版本)
pom.xml
org.springframework.boot spring-boot-starter-parent 1.3.5.RELEASE
crawler-downloader:抓取模塊
: pom.xml
crawler-persistence:存儲模塊(使用spring的jpa實現orm)
: pom.xml
org.springframework.boot spring-boot-starter-data-jpa
crawler-search-web:頁面模塊(使用spring的thymeleaf實現mvc和rest api)
: pom.xml
org.springframework.boot spring-boot-starter-thymeleaf
接下來,分別介紹各個模塊的細節:
crawler-persistence:存儲模塊根據信件內容的格式,設計存儲信件的表結構如下:
這里我使用的rxjava-jdbc來進行數據的插入.相比JPA, rxjava-jdbc如果做基礎的查詢和插入操作使用起來很方便.
// 查詢郵件詳情url IterableWEB展示的DB操作> results = db .select("select id, url from chengdu12345 limit ?,?").parameters(i * 50, 50) .getAs(Integer.class, String.class).toBlocking().toIterable(); //插入郵件記錄 int updates = db.update("insert into chengdu12345(url, title, sender, accept_unit, status, category, views, create_date) values (?,?,?,?,?,?,?,?)") .parameters(url, title, sender, receiveUnit, status, category, views, publishDate) .execute();
查詢數據庫的郵件信息時, 會涉及到分頁, 模糊匹配, 這個時候rxjava-jdbc顯的有些力不從心了. 而spring-data的大量的模板方法,會讓查詢代碼簡化. 所以這里我使用了spring-data-jpa的方式來進行查詢.
@Table(name = "chengdu12345") @NamedQuery(name = "Mail.search", query = "select m from Mail m where m.title like ?1 or m.content like ?1 or m.result like ?1") public class Mail implements Serializable {...} ...... public interface MailRepository extends Repository{ Page search(String keyword, Pageable pageable); } ...... public class MailService { @Autowired private MailRepository mailRepository; public Page search(String keyword, Pageable pageable) { return mailRepository.search("%" + keyword + "%", pageable); } }
MailService 的search方法,只需傳入Pageable 實例, spring-data將自動為我們處理好分頁的邏輯, 非常方便.
crawler-downloader:抓取模塊市長信箱的郵件展示列表中只有郵件標題和郵件詳情鏈接等基礎信息,沒有郵件正文和處理結果詳情. 我的抓取流程是:
遍歷所有的郵件列表的分頁信息, 將郵件基礎信息保存到數據庫.
遍歷數據庫中的所有已保存的郵件基礎信息, 取出郵件詳情鏈接, 再對該鏈接進行抓取, 取得內容進行分析并保存到數據庫中.
我用來抓取頁面的http客戶端類庫是okhttp,
okhttp不但提供了簡潔的api, 還在內部建立了url連接池, 在快速抓取頁面時, 減少了tcp鏈接的建立, 提高了速度, 也降低了抓取失敗的幾率.
public class HtmlUtil { static OkHttpClient client = new OkHttpClient(); public static String getURLBody(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { response.body().close(); throw new IllegalArgumentException(response.message()); } return response.body().string(); } }
頁面解析的列庫我使用了Jsoup, Jsoup也可以直接用來抓取頁面. 但它沒有提供易用的連接池機制. 默認每次抓取都會創建tcp連接. 在快速抓取頁面的情況下很容易打開過多的端口,從而造成抓取失敗. 但Jsoup的html解析api卻是相當的強大. 尤其它的對css selector的支持, 選取dom就像使用jquery一樣方便.
String html = HtmlUtil.getURLBody(pageUrl); Document doc = Jsoup.parse(html); Elements elements = doc.select("div.left5 ul li.f12px"); for (Element element : elements) { String url = urlPrefix + element.select("css").attr("href"); ...... }crawler-search-web:頁面模塊
頁面模塊是使用SpringBoot啟動的模塊. 該模塊功能非常簡單:
提供一個靜態頁面
提供一個搜索API
這里使用Spring MVC來提供實現:
@Controller public class WelcomeController { @Autowired private MailService mailService; @RequestMapping("/") public String welcome() { return "welcome";//提供靜態頁面 } @RequestMapping("/search") @ResponseBody public Pagesearch(String keyword) { Pageable query = new PageRequest(0, 100);//提供一個搜索API return mailService.search(keyword, query); } }
有了Controller和頁面, 剩下的工作就是利用Spring Boot來啟動工程了. 使用Spring Boot啟動應用非常方便, 只需幾行代碼:
@SpringBootApplication(scanBasePackages = { "org.ybak.crawler.persistence.service", "org.ybak.crawler.web" }) @EnableJpaRepositories("org.ybak.crawler.persistence.repo") @EntityScan("org.ybak.crawler.persistence.vo") public class WebApplication { public static void main(String[] args) throws Exception { SpringApplication.run(WebApplication.class, args); } }
有了Spring Boot的啟動類, 只用運行main就可以啟動應用了. 最后的頁面是這樣的:
應用啟動報錯, 提示"Service not found."
因為Spring Boot默認會掃描啟動類所在包(org.ybak.crawler.web)下的Spring注解.但我的Service類在另外一個包:org.ybak.crawler.persistence.service, 所以Spring啟動時沒有將service初始化. 解決的方法很簡單. 參照上面的WebApplication代碼中scanBasePackages設置, 制定掃描的包列表即可.
應用啟動報錯, 提示"Repository not found."
和之前的問題類似, 需要通過EnableJpaRepositories指定repo的掃描路徑.
應用啟動報錯,提示"Entity not found."
和之前的問題類似, 需要通過EntityScan指定Entity的掃描路徑.
使用SpringBoot開發時, 頁面模板文件修改后瀏覽器不生效, Java邏輯修改后不生效.
引入spring-boot-devtools,該模塊可在調試時設置各種禁止模板緩存的配置, 方便開發調試.
使用了SpringBootDevtools開發時, 任何文件修改都會導致SpringBoot重啟. 影響開發效率.
devtools通過重啟來加載新類,讓新代碼生效. 但沒完沒了的重啟也會降低開發效率.幸好spring提供了spring-loaded工具, 可以理解為開源的針對spring的JRebel. 使用了它以后, 就可以享受無重啟熱部署了.
通過使用Spring Boot來快速實現一個web應用, 確實感受到它的方便. 大量約定的默認配置能讓代碼簡潔不少, 但當需要自定義配置時, 面對spring-boot凌亂的文檔, 有著實讓人頭大. 必須經常google才能解決不斷冒出的問題.
另一方面, 使用Spring Boot開發一個簡單的Web應用,并不能展示Spring Boot作為微服務開發框架的威力. 后續我將調整這個web應用的架構, 配以docker+ elasticsearch, 來實現這個應用的微服務化.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65970.html
摘要:市長信箱郵件查詢服務將應用部署到在上一章我完成了將部署到的工作和都具有能快速啟動的特性因此是一對用來部署微服務的黃金搭檔在計劃中基于的應用也將部署到之上那我們就開始行動吧將部署到上需要執行以下步驟保證打包后的可執行能正常啟動在應用中編寫鏡像 市長信箱郵件查詢服務: 將SpringBoot應用部署到Docker 在上一章, 我完成了將ES部署到Docker的工作. SpringBoot和...
摘要:集成上服務在我的應用中希望能使用一些的特性比如這樣的數據結構如果能方便的在開發環境中使用起來就好了如何集成呢這里依然使用和來幫忙通過使用我們就能快速的部署好服務而通過使用我們能快速的把集成進我們的服務并能使用提供的模板方法方便的調用的使用快 SpringBoot集成Docker上Redis服務 在我的應用中, 希望能使用一些redis的特性:比如zset這樣的數據結構,如果能方便的在開...
閱讀 1233·2021-11-23 09:51
閱讀 678·2021-11-19 09:40
閱讀 1337·2021-10-11 10:58
閱讀 2347·2021-09-30 09:47
閱讀 3726·2021-09-22 15:55
閱讀 2160·2021-09-03 10:49
閱讀 1250·2021-09-03 10:33
閱讀 698·2019-08-29 17:12