本文會使用一個案例,就mybatis的一些基礎語法進行講解。案例中使用到的數據庫表和對象以下:javascript
article表:這個表存放的是文章的基礎信息 php
-- ---------------------------- -- Table structure for article -- ---------------------------- DROP TABLE IF EXISTS `article`; CREATE TABLE `article` ( `article_id` int(11) NOT NULL AUTO_INCREMENT, `article_user_id` int(11) unsigned DEFAULT NULL, `article_title` varchar(255) DEFAULT NULL, `article_content` mediumtext, `article_view_count` int(11) DEFAULT '0', `article_comment_count` int(11) DEFAULT '0', `article_like_count` int(11) DEFAULT '0', `article_is_comment` int(1) unsigned DEFAULT NULL, `article_status` int(1) unsigned DEFAULT '1', `article_order` int(11) unsigned DEFAULT NULL, `article_update_time` datetime DEFAULT NULL, `article_create_time` datetime DEFAULT NULL, `article_summary` text, PRIMARY KEY (`article_id`) ) ENGINE=MyISAM AUTO_INCREMENT=36 DEFAULT CHARSET=utf8;
表中的記錄以下:css
-- ---------------------------- -- Records of article -- ---------------------------- INSERT INTO `article` VALUES ('1', '1', '[轉載]SpringMVC中使用Interceptor攔截器', '<p>SpringMVC 中的Interceptor 攔截器也是至關重要和至關有用的,它的主要做用是攔截用戶的請求並進行相應的處理。好比經過它來進行權限驗證,或者是來判斷用戶是否登錄,或者是像12306 那樣子判斷當前時間是不是購票時間。</p><p><br></p><p>1、定義Interceptor實現類</p><p>SpringMVC 中的Interceptor 攔截請求是經過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 很是簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,好比Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。</p><p><br></p><p>(一)實現HandlerInterceptor接口</p><p>HandlerInterceptor 接口中定義了三個方法,咱們就是經過這三個方法來對用戶的請求進行攔截處理的。</p><p><br></p><p>(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理以前進行調用。SpringMVC 中的Interceptor 是鏈式的調用的,在一個應用中或者說是在一個請求中能夠同時存在多個Interceptor 。每一個Interceptor 的調用會依據它的聲明順序依次執行,並且最早執行的都是Interceptor 中的preHandle 方法,因此能夠在這個方法中進行一些前置初始化操做或者是對當前請求的一個預處理,也能夠在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值Boolean 類型的,當它返回爲false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行;當返回值爲true 時就會繼續調用下一個Interceptor 的preHandle 方法,若是已是最後一個Interceptor 的時候就會是調用當前請求的Controller 方法。</p><p><br></p><p>(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋咱們知道這個方法包括後面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值爲true 時才能被調用。postHandle 方法,顧名思義就是在當前請求進行處理以後,也就是Controller 方法調用以後執行,可是它會在DispatcherServlet 進行視圖返回渲染以前被調用,因此咱們能夠在這個方法中對Controller 處理以後的ModelAndView 對象進行操做。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會後執行,這和Struts2裏面的Interceptor 的執行過程有點類型。Struts2 裏面的Interceptor 的執行過程也是鏈式的,只是在Struts2 裏面須要手動調用ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的調用,而後每個Interceptor 中在invoke 方法調用以前的內容都是按照聲明順序執行的,而invoke 方法以後的內容就是反向的。</p><p><br></p><p>(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是須要當前對應的Interceptor 的preHandle 方法的返回值爲true 時纔會執行。顧名思義,該方法將在整個請求結束以後,也就是在DispatcherServlet 渲染了對應的視圖以後執行。這個方法的主要做用是用於進行資源清理工做的。</p><p><br></p><p>下面是一個簡單的代碼說明:</p><p><br></p><p>import javax.servlet.http.HttpServletRequest;</p><p>import javax.servlet.http.HttpServletResponse;</p><p>import org.springframework.web.servlet.HandlerInterceptor;</p><p>import org.springframework.web.servlet.ModelAndView;</p><p>public class SpringMVCInterceptor implements HandlerInterceptor {</p><p> /** </p><p> * preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理以前進行調用,SpringMVC中的Interceptor攔截器是鏈式的,能夠同時存在 </p><p> * 多個Interceptor,而後SpringMVC會根據聲明的先後順序一個接一個的執行,並且全部的Interceptor中的preHandle方法都會在 </p><p> * Controller方法調用以前調用。SpringMVC的這種Interceptor鏈式結構也是能夠進行中斷的,這種中斷方式是令preHandle的返 </p><p> * 回值爲false,當preHandle的返回值爲false的時候整個請求就結束了。 </p><p> */</p><p> @Override</p><p> public boolean preHandle(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> return false;</p><p> }</p><p> /** </p><p> * 這個方法只會在當前這個Interceptor的preHandle方法返回值爲true的時候纔會執行。postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之 </p><p> * 後,也就是在Controller的方法調用以後執行,可是它會在DispatcherServlet進行視圖的渲染以前執行,也就是說在這個方法中你能夠對ModelAndView進行操 </p><p> * 做。這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會後調用,這跟Struts2裏面的攔截器的執行過程有點像, </p><p> * 只是Struts2裏面的intercept方法中要手動的調用ActionInvocation的invoke方法,Struts2中調用ActionInvocation的invoke方法就是調用下一個Interceptor </p><p> * 或者是調用action,而後要在Interceptor以前調用的內容都寫在調用invoke以前,要在Interceptor以後調用的內容都寫在調用invoke方法以後。 </p><p> */</p><p> @Override</p><p> public void postHandle(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler,</p><p> ModelAndView modelAndView) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> }</p><p> /** </p><p> * 該方法也是須要當前對應的Interceptor的preHandle方法的返回值爲true時纔會執行。該方法將在整個請求完成以後,也就是DispatcherServlet渲染了視圖執行, </p><p> * 這個方法的主要做用是用於清理資源的,固然這個方法也只能在當前這個Interceptor的preHandle方法的返回值爲true時纔會執行。 </p><p> */</p><p> @Override</p><p> public void afterCompletion(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler, Exception ex)</p><p> throws Exception {</p><p> // TODO Auto-generated method stub </p><p> }</p><p>}</p><p>(二)實現WebRequestInterceptor 接口</p><p>WebRequestInterceptor 中也定義了三個方法,咱們也是經過這三個方法來實現攔截的。這三個方法都傳遞了同一個參數WebRequest ,那麼這個WebRequest 是什麼呢?這個WebRequest 是Spring 定義的一個接口,它裏面的方法定義都基本跟HttpServletRequest 同樣,在WebRequestInterceptor 中對WebRequest 進行的全部操做都將同步到HttpServletRequest 中,而後在當前請求中一直傳遞。</p><p><br></p><p>(1 )preHandle(WebRequest request) 方法。該方法將在請求處理以前進行調用,也就是說會在Controller 方法調用以前被調用。這個方法跟HandlerInterceptor 中的preHandle 是不一樣的,主要區別在於該方法的返回值是void ,也就是沒有返回值,因此咱們通常主要用它來進行資源的準備工做,好比咱們在使用Hibernate 的時候能夠在這個方法中準備一個Hibernate 的Session 對象,而後利用WebRequest 的setAttribute(name, value, scope) 把它放到WebRequest 的屬性中。這裏能夠說說這個setAttribute 方法的第三個參數scope ,該參數是一個Integer 類型的。在WebRequest 的父層接口RequestAttributes 中對它定義了三個常量:</p><p><br></p><p>SCOPE_REQUEST :它的值是0 ,表明只有在request 中能夠訪問。</p><p><br></p><p>SCOPE_SESSION :它的值是1 ,若是環境容許的話它表明的是一個局部的隔離的session,不然就表明普通的session,而且在該session範圍內能夠訪問。</p><p><br></p><p>SCOPE_GLOBAL_SESSION :它的值是2 ,若是環境容許的話,它表明的是一個全局共享的session,不然就表明普通的session,而且在該session 範圍內能夠訪問。</p><p><br></p><p>(2 )postHandle(WebRequest request, ModelMap model) 方法。該方法將在請求處理以後,也就是在Controller 方法調用以後被調用,可是會在視圖返回被渲染以前被調用,因此能夠在這個方法裏面經過改變數據模型ModelMap 來改變數據的展現。該方法有兩個參數,WebRequest 對象是用於傳遞整個請求數據的,好比在preHandle 中準備的數據均可以經過WebRequest 來傳遞和訪問;ModelMap 就是Controller 處理以後返回的Model 對象,咱們能夠經過改變它的屬性來改變返回的Model 模型。</p><p><br></p><p>(3 )afterCompletion(WebRequest request, Exception ex) 方法。該方法會在整個請求處理完成,也就是在視圖返回並被渲染以後執行。因此在該方法中能夠進行資源的釋放操做。而WebRequest 參數就能夠把咱們在preHandle 中準備的資源傳遞到這裏進行釋放。Exception 參數表示的是當前請求的異常對象,若是在Controller中拋出的異常已經被Spring 的異常處理器給處理了的話,那麼這個異常對象就是是null 。</p><p><br></p><p> </p><p><br></p><p>下面是一個簡單的代碼說明:</p><p><br></p><p>import org.springframework.ui.ModelMap;</p><p>import org.springframework.web.context.request.WebRequest;</p><p>import org.springframework.web.context.request.WebRequestInterceptor;</p><p>public class AllInterceptor implements WebRequestInterceptor {</p><p> /** </p><p> * 在請求處理以前執行,該方法主要是用於準備資源數據的,而後能夠把它們當作請求屬性放到WebRequest中 </p><p> */</p><p> @Override</p><p> public void preHandle(WebRequest request) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> System.out.println(\"AllInterceptor...............................\");</p><p> request.setAttribute(\"request\", \"request\", WebRequest.SCOPE_REQUEST);//這個是放到request範圍內的,因此只能在當前請求中的request中獲取到 </p><p> request.setAttribute(\"session\", \"session\", WebRequest.SCOPE_SESSION);//這個是放到session範圍內的,若是環境容許的話它只能在局部的隔離的會話中訪問,不然就是在普通的當前會話中能夠訪問 </p><p> request.setAttribute(\"globalSession\", \"globalSession\", WebRequest.SCOPE_GLOBAL_SESSION);//若是環境容許的話,它能在全局共享的會話中訪問,不然就是在普通的當前會話中訪問 </p><p> }</p><p> /** </p><p> * 該方法將在Controller執行以後,返回視圖以前執行,ModelMap表示請求Controller處理以後返回的Model對象,因此能夠在 </p><p> * 這個方法中修改ModelMap的屬性,從而達到改變返回的模型的效果。 </p><p> */</p><p> @Override</p><p> public void postHandle(WebRequest request, ModelMap map) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> for (String key:map.keySet())</p><p> System.out.println(key + \"-------------------------\");;</p><p> map.put(\"name3\", \"value3\");</p><p> map.put(\"name1\", \"name1\");</p><p> }</p><p> /** </p><p> * 該方法將在整個請求完成以後,也就是說在視圖渲染以後進行調用,主要用於進行一些資源的釋放 </p><p> */</p><p> @Override</p><p> public void afterCompletion(WebRequest request, Exception exception)</p><p> throws Exception {</p><p> // TODO Auto-generated method stub </p><p> System.out.println(exception + \"-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=\");</p><p> }</p><p>}</p><p><br></p><p> 2、把定義的攔截器類加到SpringMVC的攔截體系中</p><p>1.在SpringMVC的配置文件中加上支持MVC的schema</p><p><br></p><p>xmlns:mvc=\"http://www.springframework.org/schema/mvc\"</p><p>xsi:schemaLocation=\" http://www.springframework.org/schema/mvc</p><p> http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd\"</p><p>下面是個人聲明示例:</p><p><br></p><p><br></p><p><br></p><p>這樣在SpringMVC的配置文件中就能夠使用mvc標籤了,mvc標籤中有一個mvc:interceptors是用於聲明SpringMVC的攔截器的。</p><p><br></p><p> </p><p><br></p><p>(二)使用mvc:interceptors標籤來聲明須要加入到SpringMVC攔截器鏈中的攔截器</p><p><br></p><p><br></p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p><br></p><p><br></p><p>由上面的示例能夠看出能夠利用mvc:interceptors標籤聲明一系列的攔截器,而後它們就能夠造成一個攔截器鏈,攔截器的執行順序是按聲明的前後順序執行的,先聲明的攔截器中的preHandle方法會先執行,然而它的postHandle方法和afterCompletion方法卻會後執行。</p><p><br></p><p>在mvc:interceptors標籤下聲明interceptor主要有兩種方式:</p><p><br></p><p>(1)直接定義一個Interceptor實現類的bean對象。使用這種方式聲明的Interceptor攔截器將會對全部的請求進行攔截。</p><p><br></p><p>(2)使用mvc:interceptor標籤進行聲明。使用這種方式進行聲明的Interceptor能夠經過mvc:mapping子標籤來定義須要進行攔截的請求路徑。</p><p><br></p><p>通過上述兩步以後,定義的攔截器就會發生做用對特定的請求進行攔截了。</p><p><br></p><p><br></p><p><br></p>', '27', '0', '3', '1', '1', '1', '2018-11-25 20:51:52', '2017-10-06 23:54:18', null); INSERT INTO `article` VALUES ('2', '1', 'springmvc 表單中文亂碼解決方案', '<p>基本上經過在 web.xml 了配置攔截器就能夠解決。</p><p>這裏須要注意的是,最好把這段代碼放在web.xml中開頭的位置,由於攔截有順序,若是放在後面的話容易攔截不到。</p><p>攔截器代碼以下</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span><span class=\"comments\"><!--post亂碼過濾器--></span><span> </span></span></li><li class=\"\"><span><span class=\"comments\"><!-- 配置springMVC編碼過濾器 --></span><span> </span></span></li><li class=\"alt\"><span><span class=\"tag\"><</span><span class=\"tag-name\">filter</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span>CharacterEncodingFilter</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-class</span><span class=\"tag\">></span><span>org.springframework.web.filter.CharacterEncodingFilter</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">filter-class</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"\"><span> <span class=\"comments\"><!-- 設置過濾器中的屬性值 --></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span>encoding</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span>UTF-8</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"\"><span> <span class=\"tag\"><!--</span--><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span> <span class=\"comments\"><!-- 啓動過濾器 --></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span>forceEncoding</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span>true</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span> <span class=\"tag\"><!--</span--><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"\"><span><span class=\"tag\"><!--</span--><span class=\"tag-name\">filter</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span><span class=\"comments\"><!-- 過濾全部請求 --></span><span> </span></span></li><li class=\"\"><span><span class=\"tag\"><</span><span class=\"tag-name\">filter-mapping</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span>CharacterEncodingFilter</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span><span>/*</span><span class=\"tag\"><!--</span--><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span><span> </span></span></span></li><li class=\"alt\"><span><span class=\"tag\"><!--</span--><span class=\"tag-name\">filter-mapping</span><span class=\"tag\">></span><span> </span></span></span></li></ol></div></div><p><br></p><p>順便再補充其餘的幾個可能緣由。</p><p></p><p>一、數據庫和數據表不是 utf-8 編碼</p><p>就在前幾天,我遇到的問題正是這個。當時是剛從 windows 搬到 mac。也是在提交 post 表單的時候,中文一直是亂碼,後臺百度發現,原來是 navicat 的緣由。就是在新建 數據庫鏈接(注意是鏈接),不能選擇 utf-8,應該選擇默認的自動。這個地方很坑人。</p><p>數據庫和數據表固然是 utf-8,通常這種狀況不多出錯。</p><p> </p><p>二、修改 Tomcat 的 server.xml 文件,添加 utf-8 編碼</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span><connector port=< span=\"\"><span class=\"string\">\"8080\"</span><span> protocol=</span><span class=\"string\">\"HTTP/1.1\"</span><span> </span></connector port=<></span></span></li><li class=\"\"><span> connectionTimeout=<span class=\"string\">\"20000\"</span><span> </span></span></li><li class=\"alt\"><span> redirectPort=<span class=\"string\">\"8443\"</span><span> URIEncoding=</span><span class=\"string\">\"UTF-8\"</span><span> </span></span></li><li class=\"\"><span> useBodyEncodingForURI=<span class=\"string\">\"true\"</span><span> /> </span></span></li></ol></div></div><br><p></p><p>三、注意你的 IDE (如Eclipse,IntelliJ IDEA)的 jsp 文件編碼,通常在右下角能夠看出來,一般咱們也要把默認的編碼設置爲 utf-8。</p><p> </p><p>四、還有一種方法就是 直接對接收到的數據編碼轉換,我感受有點麻煩,因此不是很喜歡</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span>String name=</span><span class=\"keyword\">new</span><span> String((user.getUname()).getBytes(</span><span class=\"string\">\"ISO-8859-1\"</span><span>),</span><span class=\"string\">\"utf8\"</span><span>); </span></span></li></ol></div></div><p><span>總結:通常來講,第一種攔截器方法是可用的,要注意的是要把攔截器代碼放到 web.xml 頭部,防止攔截不到,還有表單必定要 post 方式提交。</span></p><p></p>', '16', '2', '1', '1', '1', '1', '2018-11-25 20:52:13', '2017-10-07 12:12:42', null); INSERT INTO `article` VALUES ('4', '1', '[轉載]HTTP的冪等性', '<div id=\"header\"><h2>理解HTTP冪等性</h2></div><div id=\"post_detail\"><div class=\"post\"><div class=\"postText\"><div id=\"cnblogs_post_body\"><p>基於HTTP協議的Web API是時下最爲流行的一種分佈式服務提供方式。不管是在大型互聯網應用仍是企業級架構中,咱們都見到了愈來愈多的SOA或RESTful的Web API。爲何Web API如此流行呢?我認爲很大程度上應歸功於簡單有效的HTTP協議。HTTP協議是一種分佈式的面向資源的網絡應用層協議,不管是服務器端提供Web服務,仍是客戶端消費Web服務都很是簡單。再加上瀏覽器、<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看與 Java 相關的文章\" target=\"_blank\">Java</a>script、AJAX、JSON以及HTML5等技術和工具的發展,互聯網應用架構設計表現出了從傳統的PHP、JSP、ASP.NET等服務器端動態網頁向Web API + RIA(富互聯網應用)過渡的趨勢。Web API專一於提供業務服務,RIA專一於用戶界面和交互設計,今後兩個領域的分工更加明晰。在這種趨勢下,Web API設計將成爲服務器端程序員的必修課。然而,正如簡單的<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看與 Java 相關的文章\" target=\"_blank\">Java</a>語言並不意味着高質量的<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看與 Java 相關的文章\" target=\"_blank\">Java</a>程序,簡單的HTTP協議也不意味着高質量的Web API。要想設計出高質量的Web API,還須要深刻理解分佈式系統及HTTP協議的特性。</p><h2>冪等性定義</h2><p>本文所要探討的正是HTTP協議涉及到的一種重要性質:冪等性(Idempotence)。在HTTP/1.1規範中冪等性的定義是:</p><blockquote><p>Methods can also have the property of \"idempotence\" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.</p></blockquote><p>從定義上看,HTTP方法的冪等性是指一次和屢次請求某一個資源應該具備一樣的反作用。冪等性屬於語義範疇,正如編譯器只能幫助檢查語法錯誤同樣,HTTP規範也沒有辦法經過消息格式等語法手段來定義它,這多是它不太受到重視的緣由之一。但實際上,冪等性是分佈式系統設計中十分重要的概念,而HTTP的分佈式本質也決定了它在HTTP中具備重要地位。</p><h2>分佈式事務 vs 冪等設計</h2><p>爲何須要冪等性呢?咱們先從一個例子提及,假設有一個從帳戶取錢的遠程API(能夠是HTTP的,也能夠不是),咱們暫時用類函數的方式記爲:</p><pre><code>bool withdraw(account_id, amount)\r\n</code></pre><p>withdraw的語義是從account_id對應的帳戶中扣除amount數額的錢;若是扣除成功則返回true,帳戶餘額減小amount;若是扣除失敗則返回false,帳戶餘額不變。值得注意的是:和本地環境相比,咱們不能輕易假設分佈式環境的可靠性。一種典型的狀況是withdraw請求已經被服務器端正確處理,但服務器端的返回結果因爲網絡等緣由被掉丟了,致使客戶端沒法得知處理結果。若是是在網頁上,一些不恰當的設計可能會使用戶認爲上一次操做失敗了,而後刷新頁面,這就致使了withdraw被調用兩次,帳戶也被多扣了一次錢。如圖1所示:</p><p><img src=\"/uploads/2017/10/20171007153621950.png\" alt=\"20171007153621950.png\"><br></p><p>圖1</p><p>這個問題的解決方案一是採用分佈式事務,經過引入支持分佈式事務的中間件來保證withdraw功能的事務性。分佈式事務的優勢是對於調用者很簡單,複雜性都交給了中間件來管理。缺點則是一方面架構過重量級,容易被綁在特定的中間件上,不利於異構系統的集成;另外一方面分佈式事務雖然能保證事務的ACID性質,而但卻沒法提供性能和可用性的保證。</p><p>另外一種更輕量級的解決方案是冪等設計。咱們能夠經過一些技巧把withdraw變成冪等的,好比:</p><pre><code>int create_ticket() \r\nbool idempotent_withdraw(ticket_id, account_id, amount)\r\n</code></pre><p>create_ticket的語義是獲取一個服務器端生成的惟一的處理號ticket_id,它將用於標識後續的操做。idempotent_withdraw和withdraw的區別在於關聯了一個ticket_id,一個ticket_id表示的操做至多隻會被處理一次,每次調用都將返回第一次調用時的處理結果。這樣,idempotent_withdraw就符合冪等性了,客戶端就能夠放心地屢次調用。</p><p>基於冪等性的解決方案中一個完整的取錢流程被分解成了兩個步驟:1.調用create_ticket()獲取ticket_id;2.調用idempotent_withdraw(ticket_id, account_id, amount)。雖然create_ticket不是冪等的,但在這種設計下,它對系統狀態的影響能夠忽略,加上idempotent_withdraw是冪等的,因此任何一步因爲網絡等緣由失敗或超時,客戶端均可以重試,直到得到結果。如圖2所示:</p><p><img src=\"/uploads/2017/10/20171007153648208.png\" alt=\"20171007153648208.png\"><br></p><div id=\"cnblogs_post_body\"><p>圖2</p><p>和分佈式事務相比,冪等設計的優點在於它的輕量級,容易適應異構環境,以及性能和可用性方面。在某些性能要求比較高的應用,冪等設計每每是惟一的選擇。</p><h2>HTTP的冪等性</h2><p>HTTP協議自己是一種面向資源的應用層協議,但對HTTP協議的使用實際上存在着兩種不一樣的方式:一種是RESTful的,它把HTTP當成應用層協議,比較忠實地遵照了HTTP協議的各類規定;另外一種是SOA的,它並無徹底把HTTP當成應用層協議,而是把HTTP協議做爲了傳輸層協議,而後在HTTP之上創建了本身的應用層協議。本文所討論的HTTP冪等性主要針對RESTful風格的,不過正如上一節所看到的那樣,冪等性並不屬於特定的協議,它是分佈式系統的一種特性;因此,不管是SOA仍是RESTful的Web API設計都應該考慮冪等性。下面將介紹HTTP GET、DELETE、PUT、POST四種主要方法的語義和冪等性。</p><p>HTTP GET方法用於獲取資源,不該有反作用,因此是冪等的。好比:GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次仍是N次都沒有反作用。請注意,這裏強調的是一次和N次具備相同的反作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次獲得不一樣的結果,但它自己並無產生任何反作用,於是是知足冪等性的。</p><p>HTTP DELETE方法用於刪除資源,有反作用,但它應該知足冪等性。好比:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的反作用是相同的,即刪掉id爲4231的帖子;所以,調用者能夠屢次調用或刷新頁面而沒必要擔憂引發錯誤。</p><p>比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認爲「POST表示建立資源,PUT表示更新資源」;而實際上,兩者都可用於建立資源,更爲本質的差異是在冪等性方面。在HTTP規範中對POST和PUT是這樣定義的:</p><blockquote><p>The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.</p><p>The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.</p></blockquote><p>POST所對應的URI並不是建立的資源自己,而是資源的接收者。好比:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下建立一篇帖子,HTTP響應中應包含帖子的建立狀態以及帖子的URI。兩次相同的POST請求會在服務器端建立兩份資源,它們具備不一樣的URI;因此,POST方法不具有冪等性。而PUT所對應的URI是要建立或更新的資源自己。好比:PUT http://www.forum/articles/4231的語義是建立或更新ID爲4231的帖子。對同一URI進行屢次PUT的反作用和一次PUT是相同的;所以,PUT方法具備冪等性。</p><p>在介紹了幾種操做的語義和冪等性以後,咱們來看看如何經過Web API的形式實現前面所提到的取款功能。很簡單,用POST /tickets來實現create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx來實現idempotent_withdraw。值得注意的是嚴格來說amount參數不該該做爲URI的一部分,真正的URI應該是/accounts/account_id/ticket_id,而amount應該放在請求的body中。這種模式能夠應用於不少場合,好比:論壇網站中防止意外的重複發帖。</p><h2>總結</h2><p>上面簡單介紹了冪等性的概念,用冪等設計取代分佈式事務的方法,以及HTTP主要方法的語義和冪等性特徵。其實,若是要追根溯源,冪等性是數學中的一個概念,表達的是N次變換與1次變換的結果相同,有興趣的讀者能夠從Wikipedia上進一步瞭解。</p><h2>參考</h2><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html\">RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions</a></p><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://devhawk.net/2007/11/09/the-importance-of-idempotence/\">The Importance of Idempotence</a></p><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://stackoverflow.com/questions/630453/put-vs-post-in-rest\">Stackoverflow - PUT vs POST in REST</a></p></div><p> </p><p> </p><p>原文地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html</a></p></div></div></div></div>', '13', '0', '0', '1', '1', '1', '2018-11-25 20:51:05', '2017-10-07 15:37:20', null); INSERT INTO `article` VALUES ('3', '1', '使用rapid-framework繼承jsp頁面', '<p>對於多張網頁頁面,許多部分都是相同的,應該繼承同一個頁面,該頁面是全部頁面的父頁面。<br></p><p>後來搜了一下找到一個<code>rapid-framework</code>的東西,因爲我使用的是<code>maven</code>,因此引入很簡單。</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">dependency</span><span class=\"tag\">></span> </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">groupId</span><span class=\"tag\">></span>com.googlecode.rapid-framework<span class=\"tag\"><!--</span--><span class=\"tag-name\">groupId</span><span class=\"tag\">></span> </span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span>rapid-core<span class=\"tag\"><!--</span--><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span> </span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">version</span><span class=\"tag\">></span>4.0.5<span class=\"tag\"><!--</span--><span class=\"tag-name\">version</span><span class=\"tag\">></span> </span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">dependency</span><span class=\"tag\">></span> </span></li></ol></div></div><p>父頁面</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\">... </li><li class=\"\"><span class=\"tag\"><</span>%@ taglib <span class=\"attribute\">prefix</span>=<span class=\"attribute-value\">\"rapid\"</span> <span class=\"attribute\">uri</span>=<span class=\"attribute-value\">\"http://www.rapid-framework.org.cn/rapid\"</span> %<span class=\"tag\">></span> </li><li class=\"alt\">... </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">body</span><span class=\"tag\">></span> </li><li class=\"alt\"> <span class=\"comments\"><!-- 正文 --></span> </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">rapid:block</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"content\"</span><span class=\"tag\">></span> </li><li class=\"alt\"> 123 </li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">rapid:block</span><span class=\"tag\">></span> </span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">body</span><span class=\"tag\">></span> </span></li></ol></div></div><p></p><p></p><ul></ul><p> <code><rapid:block name=\"content\"></rapid:block></code>定義叫作<code>content</code>的一塊,該部分可讓子頁面重寫。</p><p></p><p>子頁面</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span class=\"tag\"><</span>%@ page <span class=\"attribute\">contentType</span>=<span class=\"attribute-value\">\"text/html;charset=UTF-8\"</span> <span class=\"attribute\">language</span>=<span class=\"attribute-value\">\"java\"</span> %<span class=\"tag\">></span> </li><li class=\"\"><span class=\"tag\"><</span>%@ taglib <span class=\"attribute\">prefix</span>=<span class=\"attribute-value\">\"rapid\"</span> <span class=\"attribute\">uri</span>=<span class=\"attribute-value\">\"http://www.rapid-framework.org.cn/rapid\"</span> %<span class=\"tag\">></span> </li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">rapid:override</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"content\"</span><span class=\"tag\">></span> </li><li class=\"\"> 這是內容 </li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">rapid:override</span><span class=\"tag\">></span> </span></li><li class=\"\"><span class=\"tag\"><</span>%@ include <span class=\"attribute\">file</span>=<span class=\"attribute-value\">\"base.jsp\"</span>%<span class=\"tag\">></span> </li></ol></div></div><p></p><p></p><li> <%@ include file=\"base.jsp\"%>引入父頁面</li><p></p><li>重寫父頁面中叫作content的部分。</li><p></p><li>訪問子頁面,父頁面內部的元素不會顯示,代替的是子頁面重寫的內容。</li>', '2', '0', '0', '1', '1', '1', '2018-11-25 20:54:02', '2017-10-07 15:30:17', null); INSERT INTO `article` VALUES ('5', '1', 'JDBC經常使用API和使用', '<h2>1、JDBC 經常使用 API</h2><p><strong>一、Connection 接口</strong></p><table width=\"695\" class=\"layui-table\"><tbody><tr><td>方法名稱</td><td>功能描述</td></tr><tr><td>getMetaData()</td><td>該方法用於返回數據庫的元數據的 DatabaseMetaData 對象</td></tr><tr><td>createStatement</td><td>用於建立一個 Statement 對象來將 SQL 語句發送到數據庫</td></tr><tr><td>preparedStatement(String sql)</td><td>用於建立一個 PreparedStatement 對象來將參數化的SQL語句發送到數據庫</td></tr><tr><td>prepareCall(String sql)</td><td>用於建立一個 CallableStatement 對象來調用數據庫存儲過程</td></tr></tbody></table><p><strong>二、Statement 接口</strong></p><table width=\"696\" class=\"layui-table\"><tbody><tr><td>方法名稱</td><td>功能描述</td></tr><tr><td>boolean execute(String sql)</td><td>用於執行各類 SQL 語句,該方法返回一個 boolean 類型的值。若是爲 true,表示所執行的 SQL 語句具有查詢結果,可經過 Statement 的getResultSet() 方法查詢結果</td></tr><tr><td>int executeUpdate(String sql)</td><td>用於執行 SQL 中的 insert、update 和 delete 語句,該方法返回一個 int 類型的值,表示影響數據庫中的行數</td></tr><tr><td>ResultSet executeQuery(String sql)</td><td>用於執行 SQL 中的 select 語句(查詢,遍歷),該方法返回一個表示查詢結果的 ResultSet 對象</td></tr></tbody></table><p><strong> <span>execute是executeQuery和executeUpdate的綜合.</span></strong></p><p><strong><span>一般咱們沒有必要使用execute方法來執行SQL語句,而是使用 executeQuery 或 executeUpdate 更適合。</span></strong></p><p>具體可參考:<a href=\"https://liuyanzhao.com/5278.html\" target=\"_blank\" rel=\"noopener noreferrer\">execute、executeUpdate、executeQuery三者的區別</a></p><p><strong>三、PreparedStatement 接口</strong></p><table width=\"695\" class=\"layui-table\"><tbody><tr><td>方法名稱</td><td>功能描述</td></tr><tr><td>executeUpdate()</td><td>在此 PreparedStatement 對象中執行 SQL 語句,該語句必須是一個 DML 語句,或者無返回內容的 SQL 語句,好比 DDL 語句</td></tr><tr><td>executeQuery()</td><td>在此 PreparedStatement 對象中執行 SQL 語句,該方法返回的是 ResultSet 對象</td></tr><tr><td>setInt(int parameterIndex, int x)</td><td>將指定的參數設置爲 int 值</td></tr><tr><td>setFloat(int parameterIndex, float x)</td><td>將指定的參數設置爲 Float 值</td></tr><tr><td>setString(int parameterIndex, String x)</td><td>將指定參數設置的給定的 Date 值</td></tr><tr><td>setDate(int parameterIndex, Date x)</td><td>將指定參數設置給定的 Date 值</td></tr><tr><td>addBatch()</td><td>將一組參數添加到此 PreparedStatement 對象的批處理命令中</td></tr><tr><td>setCharacterStream(parameterIndex, reader, length)</td><td>將指定的輸入流寫入數據庫的文本字段</td></tr><tr><td>setBinaryStream(parameterIndex, x, length)</td><td>將二進制的輸入流數據寫入到二進制的字段中</td></tr></tbody></table><p>DML 語句:SELECT、UPDATE、INSERT、DELETE</p><p>DLL 語句:CREATE DROP ALERT</p><p>具體參考: <a href=\"https://liuyanzhao.com/5283.html\" target=\"_blank\" rel=\"noopener noreferrer\">sql語句分爲三類(DML,DDL,DCL)-介紹</a></p><p>四、ResultSet 接口</p><table class=\"layui-table\"><tbody><tr><td>getString(int columnIndex)</td><td>用於獲取 指定字段的 String 類型的值,參數 columnIndex 表明字段的索引</td></tr><tr><td>getString(String columnName)</td><td> 用於獲取指定字段的 String 類型的值,參數 columnIndex 表明字段名稱</td></tr><tr><td>getInt(int columnIndex)</td><td> 用於獲取指定字段的 int 類型的值,參數 columnIndex 表明字段的索引</td></tr><tr><td>getInt(String columnName)</td><td> 用於獲取指定字段的 int 類型的值,參數 columnIndex 表明字段名稱</td></tr><tr><td>getDate(int columnIndex)</td><td> 用於獲取指定字段的 Date類型的值,參數 columnIndex 表明字段索引</td></tr><tr><td>getDate(String columnName)</td><td> 用於獲取指定字段的 Date類型的值,參數 columnIndex 表明字段名稱</td></tr><tr><td>next()</td><td> 將遊標從當前位置移到下一位置</td></tr><tr><td>absolute(int row)</td><td>將遊標移到此 ResultSet 對象的指定行</td></tr><tr><td>afterLast()</td><td>將遊標移動到此 ResultSet 對象的末尾,即最後一行以後</td></tr><tr><td>beforeFirst()</td><td>將遊標移動到此 ResultSet 對象開頭,即第一行以前</td></tr><tr><td>previous()</td><td>將遊標移動到此 ResultSet 對象的上一行</td></tr><tr><td>last()</td><td>將遊標移動到此 Result 對象的最後一行</td></tr></tbody></table><h2>2、案例</h2><p><strong>一、往數據庫裏添加數據</strong></p><p>① 數據表結構以下</p><p><img src=\"/uploads/2017/10/2017100715402014.png\" alt=\"2017100715402014.png\"><br></p><p><span>② 代碼以下</span></p><p><span></span></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span class=\"keyword\">package</span><span> com.liuyanzhao; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.Connection; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.Date; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.DriverManager; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.PreparedStatement; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.SQLException; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.text.ParseException; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.text.SimpleDateFormat; </span></span></li><li class=\"alt\"><span><span class=\"comment\">/*</span> </span></li><li class=\"\"><span><span class=\"comment\"> * @author LiuYanzhao</span> </span></li><li class=\"alt\"><span><span class=\"comment\"> */</span><span> </span></span></li><li class=\"\"><span><span class=\"keyword\">public</span><span> </span><span class=\"keyword\">class</span><span> Demo1 { </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String URL = </span><span class=\"string\">\"jdbc:mysql://127.0.0.1:3306/jdbc_study?useUnicode=true&characterEncoding=utf8\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String USER = </span><span class=\"string\">\"root\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String PASSWORD = </span><span class=\"string\">\"\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> Connection conn = </span><span class=\"keyword\">null</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">void</span><span> main(String[] args) </span><span class=\"keyword\">throws</span><span> ClassNotFoundException, SQLException, ParseException { </span></span></li><li class=\"\"><span> <span class=\"comment\">//一、加載驅動,須要提早把 jar 包添加到 classpath 中</span><span> </span></span></li><li class=\"alt\"><span> Class.forName(<span class=\"string\">\"com.mysql.jdbc.Driver\"</span><span>); </span></span></li><li class=\"\"><span> <span class=\"comment\">//二、建立應用程序與數據庫鏈接的 Connection 對象</span><span> </span></span></li><li class=\"alt\"><span> conn = DriverManager.getConnection(URL, USER, PASSWORD); </span></li><li class=\"\"><span> <span class=\"comment\">//三、要執行的 sql 語句:name,password,email,status經過佔位符填數,create_date 自動爲當前時間</span><span> </span></span></li><li class=\"alt\"><span> String sql = <span class=\"string\">\" INSERT INTO users\"</span><span>+ </span></span></li><li class=\"\"><span> <span class=\"string\">\"(name,password,birthday,email,create_date,status) \"</span><span>+ </span></span></li><li class=\"alt\"><span> <span class=\"string\">\"VALUES(\"</span><span>+ </span></span></li><li class=\"\"><span> <span class=\"string\">\"?,?,?,?,current_date(),?)\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//四、建立執行 SQL 語句的 PreparedStatement 對象</span><span> </span></span></li><li class=\"\"><span> PreparedStatement ptmt = conn.prepareStatement(sql); </span></li><li class=\"alt\"><span> ptmt.setString(<span class=\"number\">1</span><span>, </span><span class=\"string\">\"小美\"</span><span>); </span></span></li><li class=\"\"><span> ptmt.setString(<span class=\"number\">2</span><span>, </span><span class=\"string\">\"123456\"</span><span>); </span></span></li><li class=\"alt\"><span> ptmt.setDate(<span class=\"number\">3</span><span>,</span><span class=\"keyword\">new</span><span> Date((</span><span class=\"keyword\">new</span><span> SimpleDateFormat(</span><span class=\"string\">\"yyyy-MM-dd\"</span><span>).parse(</span><span class=\"string\">\"2011-10-1\"</span><span>)).getTime()) ); </span></span></li><li class=\"\"><span> ptmt.setString(<span class=\"number\">4</span><span>, </span><span class=\"string\">\"xiaomei@126.com\"</span><span>); </span></span></li><li class=\"alt\"><span> ptmt.setInt(<span class=\"number\">5</span><span>, </span><span class=\"number\">1</span><span>); </span></span></li><li class=\"\"><span> <span class=\"comment\">//五、真正執行 sql 語句,並返回影響的行數</span><span> </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">int</span><span> x = ptmt.executeUpdate(); </span></span></li><li class=\"\"><span> System.out.println(<span class=\"string\">\"影響行數:\"</span><span> + x); </span><span class=\"comment\">//返回1</span><span> </span></span></li><li class=\"alt\"><span> } </span></li><li class=\"\"><span>} </span></li></ol></div></div><br><p></p><p>③運行結果</p><p>上面的操做,將在 jdbc_study 數據庫的 users 表中添加一條記錄,終端顯示 1</p><p><strong>二、查詢(打印)數據庫信息</strong></p><p>①數據表以下</p><p><img src=\"/uploads/2017/10/20171007154127663.png\" alt=\"20171007154127663.png\"><br></p><p><span>②代碼以下</span></p><p><span></span></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span class=\"keyword\">package</span><span> com.liuyanzhao; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.Connection; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.Date; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.DriverManager; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.PreparedStatement; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.ResultSet; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.SQLException; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.text.ParseException; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.text.SimpleDateFormat; </span></span></li><li class=\"\"><span><span class=\"comment\">/*</span> </span></li><li class=\"alt\"><span><span class=\"comment\"> * @author LiuYanzhao</span> </span></li><li class=\"\"><span><span class=\"comment\"> */</span><span> </span></span></li><li class=\"alt\"><span><span class=\"keyword\">public</span><span> </span><span class=\"keyword\">class</span><span> Demo2 { </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String URL = </span><span class=\"string\">\"jdbc:mysql://127.0.0.1:3306/jdbc_study?useUnicode=true&characterEncoding=utf8\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String USER = </span><span class=\"string\">\"root\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String PASSWORD = </span><span class=\"string\">\"\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> Connection conn = </span><span class=\"keyword\">null</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">void</span><span> main(String[] args) </span><span class=\"keyword\">throws</span><span> ClassNotFoundException, SQLException, ParseException { </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//一、加載驅動,須要提早把 jar 包添加到 classpath 中</span><span> </span></span></li><li class=\"\"><span> Class.forName(<span class=\"string\">\"com.mysql.jdbc.Driver\"</span><span>); </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//二、建立應用程序與數據庫鏈接的 Connection 對象</span><span> </span></span></li><li class=\"\"><span> conn = DriverManager.getConnection(URL, USER, PASSWORD); </span></li><li class=\"alt\"><span> <span class=\"comment\">//三、要執行的 sql 語句:name,password,email,satic 經過佔位符填數,create_date 自動爲當前時間</span><span> </span></span></li><li class=\"\"><span> String sql = <span class=\"string\">\" SELECT * FROM users\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//四、建立執行 SQL 語句的 PreparedStatement 對象</span><span> </span></span></li><li class=\"\"><span> PreparedStatement ptmt = conn.prepareStatement(sql); </span></li><li class=\"alt\"><span> <span class=\"comment\">//五、真正執行 sql 語句,並返回影響的 ResultSet</span><span> </span></span></li><li class=\"\"><span> ResultSet rs = ptmt.executeQuery(); </span></li><li class=\"alt\"><span> <span class=\"comment\">//六、打印 ResultSet 數據集</span><span> </span></span></li><li class=\"\"><span> <span class=\"keyword\">while</span><span>(rs.next()) { </span></span></li><li class=\"alt\"><span> System.out.print(rs.getInt(<span class=\"string\">\"id\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getString(<span class=\"string\">\"name\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getString(<span class=\"string\">\"password\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getDate(<span class=\"string\">\"birthday\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getString(<span class=\"string\">\"email\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getDate(<span class=\"string\">\"create_date\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getInt(<span class=\"string\">\"status\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.println(); </span></li><li class=\"alt\"><span> } </span></li><li class=\"\"><span> } </span></li><li class=\"alt\"><span>} </span></li></ol></div></div><p>③ 運行結果</p><p></p><p>控制檯上能夠看到以下界面</p><p><img src=\"/uploads/2017/10/20171007154222212.jpg\" alt=\"20171007154222212.jpg\"><br></p>', '0', '0', '0', '1', '1', '1', '2018-11-25 20:51:27', '2017-10-07 15:42:43', null); INSERT INTO `article` VALUES ('6', '1', 'Hibernate 簡單的CURD操做', '<h2>1、單表操做 CURD 實例</h2><ul><li>save</li><li>update</li><li>delete</li><li>get/load (查詢單個記錄)</li></ul><p> </p><h2>2、代碼實現</h2><p><strong>StudentTest.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testSaveStudnets() {</li><li class=\"alt\"> <span class=\"comment\">//生成學生對象</span></li><li class=\"\"> Student s = <span class=\"keyword\">new</span> Student();</li><li class=\"alt\"> s.setName(<span class=\"string\">\"陶淵明\"</span>);</li><li class=\"\"> s.setSex(<span class=\"number\">1</span>);</li><li class=\"alt\"> s.setBirthday(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> Address address = <span class=\"keyword\">new</span> Address(<span class=\"string\">\"332000\"</span>,<span class=\"string\">\"13512345678\"</span>,<span class=\"string\">\"江西九江\"</span>);</li><li class=\"alt\"> s.setAddress(address);</li><li class=\"\"> session.save(s);<span class=\"comment\">//保存對象進入數據庫</span></li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testGetStudents() {</li><li class=\"alt\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> System.out.println(s);</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testLoadStudents() {</li><li class=\"alt\"> Student s = (Student) session.load(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> System.out.println(s);</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testUpdateStudents() {</li><li class=\"alt\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> s.setName(<span class=\"string\">\"五柳先生\"</span>);</li><li class=\"alt\"> session.update(s);</li><li class=\"\">}</li><li class=\"alt\"></li><li class=\"\"><span class=\"annotation\">@Test</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testDeleteStudents() {</li><li class=\"\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"alt\"> session.delete(s);</li><li class=\"\">}</li></ol></div><p> </p><h2>3、get 和 load 的區別</h2><p><strong>區別1、</strong></p><ul><li>不考慮緩存的狀況下,get 方法會在調用以後,當即向數據庫發送 sql 語句,返回持久化對象。</li><li>load 方法會在調用後返回一個持久化對象。該代理對象只保留了實體對象的 id,直到使用實體對象的非主鍵屬性時才發出 sql 語句。</li></ul><p><strong>區別2、</strong></p><ul><li>查詢數據庫中不存在的數據時,get 方法返回 null 。</li><li>load 方法返回異常 org.hibernate.ObjectNotFoundException</li></ul><p>p</p><div><br></div>', '3', '2', '0', '1', '1', '1', '2018-11-25 20:52:33', '2017-10-07 15:49:54', null); INSERT INTO `article` VALUES ('7', '1', 'Hibernate 基本類型', '<p>這裏介紹幾個特殊的 <a href=\"https://liuyanzhao.com/tag/hibernate/\" title=\"查看與 Hibernate 相關的文章\" target=\"_blank\">Hibernate</a> 類型和屬性</p><h2>1、日期類型</h2><p>咱們的 Student 類有一個成員變量 birthday</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li></ol></div><p>在咱們的 Studnet.hbm.xml 對應的是自動生成的 屬性</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"birthday\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"java.util.Date\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">column</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"BIRTHDAY\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">property</span><span class=\"tag\">></span></span></li></ol></div><p>type 表示該字段的類型,不一樣的類型,會讓數據表的字段類型也不一樣</p><table class=\"layui-table\"><tbody><tr><td>type(映射類型)</td><td>描述</td></tr><tr><td>java.util.Date</td><td>年月日時分秒(2017-07-25 18:20:12)</td></tr><tr><td>date</td><td>年月日(2017-07-25)</td></tr><tr><td>time</td><td>時分秒(18:20:12)</td></tr><tr><td>timestamp</td><td>年月日時分秒(2017-07-25 18:20:12)</td></tr></tbody></table><h2>2、對象類型</h2><p>咱們這裏使用使用 Blob 類型存照片</p><p>一、Student 類中 成員變量以下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sid;<span class=\"comment\">//學號</span></li><li class=\"\"><span class=\"keyword\">private</span> String name;<span class=\"comment\">//姓名</span></li><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sex;<span class=\"comment\">//性別</span></li><li class=\"\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li><li class=\"alt\"><span class=\"keyword\">private</span> String address;<span class=\"comment\">//地址</span></li><li class=\"\"><span class=\"keyword\">private</span> Blob picture;<span class=\"comment\">//照片 </span></li></ol></div><p>二、而後刪除原來的 Student.hbm.xml 文件,從新生成</p><p>三、在測試類添加 testWriteBlob方法</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testWriteBlob() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> Student s = <span class=\"keyword\">new</span> Student(<span class=\"number\">1</span>,<span class=\"string\">\"杜甫\"</span>,<span class=\"number\">1</span>,<span class=\"keyword\">new</span> Date(),<span class=\"string\">\"四川\"</span>);</li><li class=\"\"> <span class=\"comment\">//先得到照片文件</span></li><li class=\"alt\"> File f = <span class=\"keyword\">new</span> File(<span class=\"string\">\"d:\"</span>+File.separator+<span class=\"string\">\"boy.jpg\"</span>);</li><li class=\"\"> <span class=\"comment\">//得到照片文件的輸入流</span></li><li class=\"alt\"> InputStream input = <span class=\"keyword\">new</span> FileInputStream(f);</li><li class=\"\"> <span class=\"comment\">//建立Blob對象</span></li><li class=\"alt\"> Blob image = <a href=\"https://liuyanzhao.com/tag/hibernate/\" title=\"查看與 Hibernate 相關的文章\" target=\"_blank\">Hibernate</a>.getLobCreator(session).createBlob(input,input.available());</li><li class=\"\"> <span class=\"comment\">//設置照片屬性</span></li><li class=\"alt\"> s.setPicture(image);</li><li class=\"\"> session.save(s);</li><li class=\"alt\">}</li></ol></div><p>注意:這裏 Blob 是 java.sql.Blob 包下</p><p>四、而後使用 Junit Test 運行 testWriteBlob 方法</p><p><img src=\"/uploads/2017/10/2017100715505630.png\" alt=\"2017100715505630.png\"><br></p><p>五、爲了證實是否真的是寫入數據庫中,咱們從新把照片讀出來</p><p>在測試類中添加 testReadBlob 方法</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testReadBlob() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> Student s = (Student)session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> <span class=\"comment\">//得到Blob對象</span></li><li class=\"alt\"> Blob image = s.getPicture();</li><li class=\"\"> <span class=\"comment\">//得到照片的輸入流</span></li><li class=\"alt\"> InputStream input = image.getBinaryStream();</li><li class=\"\"> <span class=\"comment\">//建立輸出流</span></li><li class=\"alt\"> File f = <span class=\"keyword\">new</span> File(<span class=\"string\">\"d:\"</span>+File.separator+<span class=\"string\">\"dest.jpg\"</span>);</li><li class=\"\"> <span class=\"comment\">//得到輸出流</span></li><li class=\"alt\"> OutputStream output = <span class=\"keyword\">new</span> FileOutputStream(f);</li><li class=\"\"> <span class=\"comment\">//建立緩衝區</span></li><li class=\"alt\"> <span class=\"keyword\">byte</span>[] buff = <span class=\"keyword\">new</span> <span class=\"keyword\">byte</span>[input.available()];</li><li class=\"\"> input.read(buff);</li><li class=\"alt\"> output.write(buff);</li><li class=\"\"> input.close();</li><li class=\"alt\"> output.close();</li><li class=\"\">}</li></ol></div><p>六、使用 Junit Test 運行 testReadBlob 方法</p><p>咱們能夠看到 D 盤,已經生成了一張新照片,dest.jpg</p><p> </p><p><img src=\"/uploads/2017/10/20171007155038568.png\" alt=\"20171007155038568.png\"><br></p><h2>3、組件屬性</h2><p>實體類中某個屬性屬於用戶自定義的類的對象,下面咱們經過一個例子來解釋</p><p>一、實體類 Student.java 成員變量以下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sid;<span class=\"comment\">//學號</span></li><li class=\"\"><span class=\"keyword\">private</span> String name;<span class=\"comment\">//姓名</span></li><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sex;<span class=\"comment\">//性別</span></li><li class=\"\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li><li class=\"alt\"><span class=\"comment\">//private String address;//地址</span></li><li class=\"\"><span class=\"keyword\">private</span> Blob picture;<span class=\"comment\">//照片 </span></li><li class=\"alt\"><span class=\"keyword\">private</span> Address address; <span class=\"comment\">//地址</span></li></ol></div><p>咱們這裏把以前的 String 類型的 address 改爲 Address 類型</p><p>二、Address 類 部分代碼以下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> String postcode;<span class=\"comment\">//郵編</span></li><li class=\"\"><span class=\"keyword\">private</span> String phone;<span class=\"comment\">//手機</span></li><li class=\"alt\"><span class=\"keyword\">private</span> String address;<span class=\"comment\">//地址</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> Address(String postcode, String phone, String address) {</li><li class=\"\"> <span class=\"keyword\">this</span>.postcode = postcode;</li><li class=\"alt\"> <span class=\"keyword\">this</span>.phone = phone;</li><li class=\"\"> <span class=\"keyword\">this</span>.address = address;</li><li class=\"alt\">}</li></ol></div><p>三、修改 Student.hbm.xml</p><p>將以前的</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"java.lang.String\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">column</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"ADDRESS\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">property</span><span class=\"tag\">></span></span></li></ol></div><p>改爲</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">component</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">class</span>=<span class=\"attribute-value\">\"Address\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"postcode\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"POSTCODE\"</span><span class=\"tag\">/></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"phone\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"PHONE\"</span><span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"ADDRESS\"</span><span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">component</span><span class=\"tag\">></span></span></li></ol></div><p>注意:單詞不要打錯</p><p>四、修改 測試類 testSaveStudent 代碼</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testSaveStudnets() {</li><li class=\"alt\"> <span class=\"comment\">//生成學生對象</span></li><li class=\"\"> Student s = <span class=\"keyword\">new</span> Student();</li><li class=\"alt\"> s.setName(<span class=\"string\">\"陶淵明\"</span>);</li><li class=\"\"> s.setSex(<span class=\"number\">1</span>);</li><li class=\"alt\"> s.setBirthday(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> <span class=\"comment\">//s.setAddress(\"江西九江\");</span></li><li class=\"alt\"> Address address = <span class=\"keyword\">new</span> Address(<span class=\"string\">\"332000\"</span>,<span class=\"string\">\"13512345678\"</span>,<span class=\"string\">\"江西九江\"</span>);</li><li class=\"\"> s.setAddress(address);</li><li class=\"alt\"> session.save(s);<span class=\"comment\">//保存對象進入數據庫</span></li><li class=\"\"> }</li></ol></div><p>五、修改 hibernate.cfg.xml 裏的建立表的策略</p><p>由於要修改表結構,暫且把 update 改爲 create</p><p>六、用 Junit Test 運行 testSaveStudent 方法</p><p>運行成功,查看數據表</p><p><img src=\"/uploads/2017/10/2017100715512437.jpg\" alt=\"2017100715512437.jpg\"><br></p><p>查看 表結構</p><p><img src=\"/uploads/2017/10/20171007155135604.jpg\" alt=\"20171007155135604.jpg\"><br></p><p> </p>', '1', '0', '0', '1', '1', '1', '2018-11-25 20:55:13', '2017-10-07 15:51:57', null); INSERT INTO `article` VALUES ('8', '1', 'Mybatis高級映射多對多查詢', '<p>緊接着上一篇文章:<a href=\"https://liuyanzhao.com/5847.html\" target=\"_blank\" rel=\"noopener noreferrer\">Mybatis高級映射一對多查詢</a> 寫</p><h2>1、開發準備</h2><p><strong>一、新建數據表(四張表)和添加測試數據</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-sql\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `items`;</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `orders`;</li><li class=\"alt\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `<span class=\"func\">user</span>`;</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `orderdetail`;</li><li class=\"alt\"></li><li class=\"\">/*items是商品表*/</li><li class=\"alt\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `items` (</li><li class=\"\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"alt\"> `<span class=\"keyword\">name</span>` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品名稱\',</li><li class=\"\"> `price` <span class=\"keyword\">FLOAT</span>(10,1) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品訂價\',</li><li class=\"alt\"> `detail` TEXT COMMENT \'商品描述\',</li><li class=\"\"> `pic` <span class=\"keyword\">VARCHAR</span>(64) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'商品圖片\',</li><li class=\"alt\"> `createtime` DATETIME <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'生產日期\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`)</li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=4 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*<span class=\"func\">user</span>是用戶表*/</li><li class=\"\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `<span class=\"func\">user</span>` (</li><li class=\"alt\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"\"> `username` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'用戶名稱\',</li><li class=\"alt\"> `birthday` <span class=\"keyword\">DATE</span> <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'生日\',</li><li class=\"\"> `gender` <span class=\"keyword\">CHAR</span>(1) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'性別\',</li><li class=\"alt\"> `address` <span class=\"keyword\">VARCHAR</span>(256) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'地址\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`)</li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=27 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*orders是訂單表*/</li><li class=\"\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `orders` (</li><li class=\"alt\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"\"> `user_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'下單用戶id\',</li><li class=\"alt\"> `number` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'訂單號\',</li><li class=\"\"> `createtime` DATETIME <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'建立訂單時間\',</li><li class=\"alt\"> `note` <span class=\"keyword\">VARCHAR</span>(100) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'備註\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`),</li><li class=\"alt\"> <span class=\"keyword\">KEY</span> `FK_orders_1` (`user_id`),</li><li class=\"\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orders_id` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`user_id`) <span class=\"keyword\">REFERENCES</span> `<span class=\"func\">user</span>` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span></li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=6 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*orderdetail是訂單明細表*/</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS orderdetail;</li><li class=\"alt\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `orderdetail` (</li><li class=\"\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"alt\"> `orders_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'訂單id\',</li><li class=\"\"> `items_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品id\',</li><li class=\"alt\"> `items_num` <span class=\"keyword\">INT</span>(11) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'商品購買數量\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`),</li><li class=\"alt\"> <span class=\"keyword\">KEY</span> `FK_orderdetail_1` (`orders_id`),</li><li class=\"\"> <span class=\"keyword\">KEY</span> `FK_orderdetail_2` (`items_id`),</li><li class=\"alt\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orderdetail_1` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`orders_id`) <span class=\"keyword\">REFERENCES</span> `orders` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span>,</li><li class=\"\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orderdetail_2` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`items_id`) <span class=\"keyword\">REFERENCES</span> `items` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span></li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=5 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li></ol></div><p>爲了測試,我這裏隨便填了些數據</p><p><img src=\"/uploads/2017/10/20171007155334244.png\" alt=\"20171007155334244.png\"><br></p><p><img src=\"/uploads/2017/10/20171007155349805.png\" alt=\"20171007155349805.png\"><br></p><p><br></p><p><img src=\"/uploads/2017/10/20171007155410485.png\" alt=\"20171007155410485.png\"><br></p><p><br></p><p><strong><img src=\"/uploads/2017/10/20171007155450773.png\" alt=\"20171007155450773.png\"></strong></p><p><strong>二、思路分析</strong></p><p><img src=\"/uploads/2017/10/20171007155545742.png\" alt=\"20171007155545742.png\"><br></p><p>訂單項和訂單明細是一對多的關係,因此本文主要來查詢訂單表,而後關聯訂單明細表,這樣就有一對多的問題出來了。</p><p><span>由於多對多比較複雜,總公共有四張表,咱們先來分析一下思路:</span></p><blockquote><p><span>一、將用戶信息映射到User中;</span></p><p><span>二、在User類中添加訂單列表屬性<code>List<orders>ordersList</orders></code>,將用戶建立的訂單映射到ordersList中;</span></p><p><span>三、在Orders中添加訂單明細列表屬性<code>List<orderdetail>orderDetails</orderdetail></code>,將訂單的明細映射到orderDetails中;</span></p><p><span>四、在OrderDetail中添加Items屬性,將訂單明細所對應的商品映射到Items中。</span></p></blockquote><p>通過這樣分析後,感受雖然有點複雜,可是好像不是很難的樣子,映射的方法也跟前面的同樣,只不過這裏表有點多,關係有點複雜。下面來寫映射文件:</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-sql\" start=\"1\"><li class=\"alt\"><<span class=\"keyword\">select</span> id=<span class=\"string\">\"findUserAndItemsResultMap\"</span> resultMap=<span class=\"string\">\"UserAndItemsResultMap\"</span>></li><li class=\"\"> <span class=\"keyword\">SELECT</span></li><li class=\"alt\"> orders.*,</li><li class=\"\"> <span class=\"func\">user</span>.`username`,</li><li class=\"alt\"> <span class=\"func\">user</span>.`sex`,</li><li class=\"\"> <span class=\"func\">user</span>.`address`,</li><li class=\"alt\"> orderdetail.`id` orderdetail_id,</li><li class=\"\"> orderdetail.`items_id`,</li><li class=\"alt\"> orderdetail.`items_num`,</li><li class=\"\"> orderdetail.`orders_id`,</li><li class=\"alt\"> items.`<span class=\"keyword\">name</span>` items_name,</li><li class=\"\"> items.`detail` items_detail,</li><li class=\"alt\"> items.`price` items_price</li><li class=\"\"> <span class=\"keyword\">FROM</span></li><li class=\"alt\"> orders,</li><li class=\"\"> <span class=\"func\">USER</span>,</li><li class=\"alt\"> orderdetail,</li><li class=\"\"> items</li><li class=\"alt\"> <span class=\"keyword\">WHERE</span> orders.`user_id`=<span class=\"func\">user</span>.`id` <span class=\"op\">AND</span> orders.`id` = orderdetail.`orders_id` <span class=\"op\">AND</span> orderdetail.`items_id`=items.`id`</li><li class=\"\"><!--<span class=\"keyword\"-->select></li></ol></div><p>咱們先看一下查詢結果:</p><p><img src=\"/uploads/2017/10/2017100717420134.png\" alt=\"2017100717420134.png\"><br></p><p><br></p><h2>2、代碼實現</h2><p><strong>一、四個持久化類</strong></p><p>① User.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 用戶的持久類</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> User {</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id; <span class=\"comment\">//編號</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> String username; <span class=\"comment\">//用戶名</span></li><li class=\"\"> <span class=\"keyword\">private</span> String gender; <span class=\"comment\">//性別</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Date birthday; <span class=\"comment\">//生日</span></li><li class=\"\"> <span class=\"keyword\">private</span> String address; <span class=\"comment\">//地址</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> List<orders> getOrdersList() {</orders></li><li class=\"alt\"> <span class=\"keyword\">return</span> ordersList;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrdersList(List<orders> ordersList) {</orders></li><li class=\"alt\"> <span class=\"keyword\">this</span>.ordersList = ordersList;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//用戶建立的訂單列表</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> List<orders> ordersList;</orders></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getUsername() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> username;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUsername(String username) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.username = username;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getGender() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> gender;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setGender(String gender) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.gender = gender;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getBirthday() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> birthday;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setBirthday(Date birthday) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.birthday = birthday;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getAddress() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> address;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setAddress(String address) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.address = address;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\">}</li></ol></div><p>注意:須要在用戶表中加入 訂單列表</p><p> </p><p>② Items.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 商品的持久類</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Items {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"\"> <span class=\"keyword\">private</span> String name;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">double</span> price;</li><li class=\"\"> <span class=\"keyword\">private</span> String detail;</li><li class=\"alt\"> <span class=\"keyword\">private</span> String pic;</li><li class=\"\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getName() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> name;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setName(String name) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.name = name;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">double</span> getPrice() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> price;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setPrice(<span class=\"keyword\">double</span> price) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.price = price;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getDetail() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> detail;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setDetail(String detail) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.detail = detail;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getPic() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> pic;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setPic(String pic) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.pic = pic;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getCreateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setCreateTime(Date createTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.createTime = createTime;</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p> </p><p>③ Orders.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 訂單的持久類和擴展類</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Orders {</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> userId;</li><li class=\"\"> <span class=\"keyword\">private</span> String number;</li><li class=\"alt\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"\"> <span class=\"keyword\">private</span> String note;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//訂單明細</span></li><li class=\"\"> <span class=\"keyword\">private</span> List<orderdetail> orderdetails;</orderdetail></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> List<orderdetail> getOrderdetails() {</orderdetail></li><li class=\"alt\"> <span class=\"keyword\">return</span> orderdetails;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrderdetails(List<orderdetail> orderdetails) {</orderdetail></li><li class=\"alt\"> <span class=\"keyword\">this</span>.orderdetails = orderdetails;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getUserId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> userId;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUserId(<span class=\"keyword\">int</span> userId) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.userId = userId;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getNumber() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> number;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setNumber(String number) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.number = number;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getCreateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setCreateTime(Date createTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.createTime = createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getNote() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> note;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setNote(String note) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.note = note;</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p>注意:訂單列表中,須要訂單的詳細信息,不須要用戶信息</p><p> </p><p>④ Orderdetail.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 訂單明細的持久類</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Orderdetail {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> ordersId;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> itemsId;</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> itemsNum;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//明細對應的商品信息</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Items items;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> Items getItems() {</li><li class=\"\"> <span class=\"keyword\">return</span> items;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItems(Items items) {</li><li class=\"\"> <span class=\"keyword\">this</span>.items = items;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"\"> <span class=\"keyword\">return</span> id;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getOrdersId() {</li><li class=\"\"> <span class=\"keyword\">return</span> ordersId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrdersId(<span class=\"keyword\">int</span> ordersId) {</li><li class=\"\"> <span class=\"keyword\">this</span>.ordersId = ordersId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getItemsId() {</li><li class=\"\"> <span class=\"keyword\">return</span> itemsId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItemsId(<span class=\"keyword\">int</span> itemsId) {</li><li class=\"\"> <span class=\"keyword\">this</span>.itemsId = itemsId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getItemsNum() {</li><li class=\"\"> <span class=\"keyword\">return</span> itemsNum;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItemsNum(<span class=\"keyword\">int</span> itemsNum) {</li><li class=\"\"> <span class=\"keyword\">this</span>.itemsNum = itemsNum;</li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p>注意:訂單明細裏,須要 商品信息</p><p> </p><p><strong>二、訂單代理 即mapper.java</strong></p><p>OrdersMapperCustom.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.mapper;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.po.User;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 訂單 mapper</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">interface</span> OrdersMapperCustom {</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//查詢用戶購買的商品信息</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> List<user> findUserAndItemsResultMap() <span class=\"keyword\">throws</span> Exception;</user></li><li class=\"\">}</li></ol></div><p> </p><p><span><strong>三、OrdersMapperCustom.xml 映射文件</strong></span></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><!--?</span--><span class=\"tag-name\">xml</span> <span class=\"attribute\">version</span>=<span class=\"attribute-value\">\"1.0\"</span> <span class=\"attribute\">encoding</span>=<span class=\"attribute-value\">\"UTF-8\"</span> <span class=\"tag\">?></span></span></li><li class=\"\"></li><li class=\"alt\"> PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"</li><li class=\"\"> \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"<span class=\"tag\">></span></li><li class=\"alt\"></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">mapper</span> <span class=\"attribute\">namespace</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.mapper.OrdersMapperCustom\"</span><span class=\"tag\">></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--查詢用戶購買的商品--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">resultMap</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"UserAndItemsResultMap\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.User\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!--用戶信息--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"user_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"username\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"username\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"gender\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"gender\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"address\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comments\"><!--訂單信息--></span></li><li class=\"\"> <span class=\"comments\"><!--一個用戶能夠對應多個訂單,故使用collection映射--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">collection</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"ordersList\"</span> <span class=\"attribute\">ofType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Orders\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"user_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"userId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"number\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"number\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"createtime\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"createTime\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"node\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"node\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--訂單明細--></span></li><li class=\"alt\"> <span class=\"comments\"><!--一個訂單包括多個明細,故使用collection--></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">collection</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"orderdetails\"</span> <span class=\"attribute\">ofType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Orderdetail\"</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"orderdetail_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"itemsId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_num\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"itemsNum\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"orders_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"ordersId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--商品信息--></span></li><li class=\"alt\"> <span class=\"comments\"><!--一個訂單明細對應一個商品--></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">association</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"items\"</span> <span class=\"attribute\">javaType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Items\"</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_name\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"name\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_price\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"price\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_detail\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"detail\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">association</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">collection</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">collection</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">resultMap</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">select</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"findUserAndItemsResultMap\"</span> <span class=\"attribute\">resultMap</span>=<span class=\"attribute-value\">\"UserAndItemsResultMap\"</span><span class=\"tag\">></span></li><li class=\"alt\"> SELECT</li><li class=\"\"> orders.*,</li><li class=\"alt\"> user.username,</li><li class=\"\"> user.gender,</li><li class=\"alt\"> user.address,</li><li class=\"\"> orderdetail.id orderdetail_id,</li><li class=\"alt\"> orderdetail.items_id,</li><li class=\"\"> orderdetail.items_num,</li><li class=\"alt\"> orderdetail.orders_id,</li><li class=\"\"> items.name items_name,</li><li class=\"alt\"> items.detail items_detail,</li><li class=\"\"> items.price items_price</li><li class=\"alt\"> FROM</li><li class=\"\"> orders,</li><li class=\"alt\"> user,</li><li class=\"\"> orderdetail,</li><li class=\"alt\"> items</li><li class=\"\"> WHERE <span class=\"attribute\">orders.user_id</span>=user.id AND <span class=\"attribute\">orders.id</span> = <span class=\"attribute-value\">orderdetail</span>.orders_id AND <span class=\"attribute\">orderdetail.items_id</span>=items.id</li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">select</span><span class=\"tag\">></span></span></li><li class=\"\"></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">mapper</span><span class=\"tag\">></span></span></li></ol></div><p> </p><p><span>四、測試類 OrderMapperCustomTest.java</span></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.test;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.mapper.OrdersMapperCustom;</li><li class=\"\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.po.User;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.apache.ibatis.io.Resources;</li><li class=\"\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSession;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSessionFactory;</li><li class=\"\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSessionFactoryBuilder;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.junit.Before;</li><li class=\"\"><span class=\"keyword\">import</span> org.junit.Test;</li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">import</span> java.io.InputStream;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * Created by Liu_Yanzhao on 2017/8/12.</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> OrderMapperCustomTest {</li><li class=\"alt\"> SqlSessionFactory sqlSessionFactory;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Before</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUp() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> String resource = <span class=\"string\">\"Configuration.xml\"</span>;</li><li class=\"\"> InputStream inputStream = Resources.getResourceAsStream(resource);</li><li class=\"alt\"> sqlSessionFactory = <span class=\"keyword\">new</span> SqlSessionFactoryBuilder()</li><li class=\"\"> .build(inputStream);</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testFindUserAndItemsResultMap() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> SqlSession sqlSession = sqlSessionFactory.openSession();</li><li class=\"\"> <span class=\"comment\">//建立代理對象</span></li><li class=\"alt\"> OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.<span class=\"keyword\">class</span>);</li><li class=\"\"> <span class=\"comment\">//調用mapper對象</span></li><li class=\"alt\"> List<user> list = ordersMapperCustom.findUserAndItemsResultMap();</user></li><li class=\"\"> System.out.println(list);</li><li class=\"alt\"> <span class=\"comment\">//釋放資源</span></li><li class=\"\"> sqlSession.close();</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p>還有其餘文件就不補充了,如 mybatis 全局配置文件</p><p> </p><h2>小結</h2><p><span>這樣多對多的映射就搞定了。不過還有個問題,就是這裏多對多的查詢會把全部關聯的表的信息都查詢出來,而後放到pojo中的對應的List或者某個類中,因此即便我只查了個用戶信息,可是這個用戶裏包含了訂單,訂單項,商品等信息,感受裝的有點多,好像有時候並不須要這麼多冗餘的數據出來,可是若是用resultType的話查詢出來的字段必須對應pojo中的屬性,若是有List等,須要手動裝入才行。因此下面總結一下對於這種查詢數據比較多的時候,resultType和resultMap各有什麼做用?</span></p><blockquote><ol><li>好比咱們只須要將查詢用戶購買的商品信息明細清單(如用戶名、用戶地址、購買商品名稱、購買商品時間、購買商品數量),那麼咱們徹底不須要其餘的信息,這個時候就不必使用resultMap將全部的信息都搞出來,咱們能夠本身定義一個pojo,包含咱們須要的字段便可,而後查詢語句只查詢咱們須要的字段,這樣使用resultType會方便不少。</li><li>若是咱們須要查詢該用戶的全部詳細信息,好比用戶點擊該用戶或者鼠標放上去,會出來跟該用戶相關的訂單啊,訂單明細啊,商品啊之類的,而後咱們要點進去看下詳細狀況的時候,那就須要使用resultMap了,必須將全部信息都裝到這個User中,而後具體啥信息再從User中取,很好理解。</li><li>總結一點:使用resultMap是針對那些對查詢結果映射有特殊要求的功能,,好比特殊要求映射成list中包括多個list。不然使用resultType比較直接。</li></ol></blockquote><p><span>到這裏,mybatis的多對多映射就總結完了。 </span></p>', '8', '3', '0', '1', '1', '1', '2018-11-25 20:53:43', '2017-10-07 15:56:00', null); INSERT INTO `article` VALUES ('9', '1', 'Servlet 實現驗證碼', '<h2>分析</h2><p><strong>生成圖片實現類</strong></p><p>Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a> 類</p><p>① 定義BufferedImage 對象</p><p>② 得到 Graphics 對象</p><p>③ 經過 Random 產生隨機驗證碼信息</p><p>④ 使用 Graphics 繪製圖片</p><p>⑤ 記錄驗證碼信息到 session 中</p><p>⑥ 使用 ImageIO 輸出圖片</p><h2>代碼實現</h2><p>一、新建 web 項目 CheckCode,在 WebContent 下新建 index.jsp</p><p><strong>index.jsp</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span>%@ page <span class=\"attribute\">language</span>=<span class=\"attribute-value\">\"java\"</span> <span class=\"attribute\">contentType</span>=<span class=\"attribute-value\">\"text/html; charset=UTF-8\"</span></li><li class=\"\"> <span class=\"attribute\">pageEncoding</span>=<span class=\"attribute-value\">\"UTF-8\"</span>%<span class=\"tag\">></span></li><li class=\"alt\">></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">html</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">head</span><span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">meta</span> <span class=\"attribute\">http-equiv</span>=<span class=\"attribute-value\">\"Content-Type\"</span> <span class=\"attribute\">content</span>=<span class=\"attribute-value\">\"text/html; charset=UTF-8\"</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">title</span><span class=\"tag\">></span>Insert title here<span class=\"tag\"><!--</span--><span class=\"tag-name\">title</span><span class=\"tag\">></span></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">script</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"text/javascript\"</span><span class=\"tag\">></span></li><li class=\"alt\"> function reloadCode() {</li><li class=\"\"> //傳個時間參數,防止緩存</li><li class=\"alt\"> var <span class=\"attribute\">time</span> = <span class=\"attribute-value\">new</span> Date().getTime();</li><li class=\"\"> document.getElementById(\"imageCode\")<span class=\"attribute\">.src</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>?d=\"</span>+time;</li><li class=\"alt\"> }</li><li class=\"\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">script</span><span class=\"tag\">></span></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">head</span><span class=\"tag\">></span></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">body</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">form</span> <span class=\"attribute\">action</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Login<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>\"</span> <span class=\"attribute\">method</span>=<span class=\"attribute-value\">\"post\"</span><span class=\"tag\">></span></li><li class=\"\"> 驗證碼:<span class=\"tag\"><</span><span class=\"tag-name\">input</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"text\"</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"checkcode\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">img</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"imageCode\"</span> <span class=\"attribute\">src</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>\"</span> <span class=\"attribute\">alt</span>=<span class=\"attribute-value\">\"驗證碼\"</span> <span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">a</span> <span class=\"attribute\">href</span>=<span class=\"attribute-value\">\"javascript:reloadCode();\"</span><span class=\"tag\">></span>看不清楚<span class=\"tag\"><!--</span--><span class=\"tag-name\">a</span><span class=\"tag\">></span> <span class=\"tag\"><</span><span class=\"tag-name\">br</span> <span class=\"tag\">/></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">input</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"submit\"</span> <span class=\"attribute\">value</span>=<span class=\"attribute-value\">\"提交\"</span><span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">form</span><span class=\"tag\">></span></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">body</span><span class=\"tag\">></span></span></li><li class=\"\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">html</span><span class=\"tag\">></span></span></li></ol></div><p>二、在 src 下新建 com.liuyanzhao 包,而後分別新建用於動態畫圖的 Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a> 類和用於判斷驗證碼是否正確的 Login<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a> 類</p><p><strong>Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.awt.Color;</li><li class=\"\"><span class=\"keyword\">import</span> java.awt.Graphics;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.awt.image.BufferedImage;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Random;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> javax.imageio.ImageIO;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>Exception;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.Http<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看與 Servlet 相關的文章\" target=\"_blank\">Servlet</a>;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletResponse;</li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> ImageServlet <span class=\"keyword\">extends</span> HttpServlet {</li><li class=\"\"> <span class=\"annotation\">@Override</span></li><li class=\"alt\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"\"> BufferedImage bi = <span class=\"keyword\">new</span> BufferedImage(<span class=\"number\">68</span>, <span class=\"number\">22</span>, BufferedImage.TYPE_INT_RGB);</li><li class=\"alt\"> Graphics g = bi.getGraphics();</li><li class=\"\"> Color c = <span class=\"keyword\">new</span> Color(<span class=\"number\">200</span>,<span class=\"number\">155</span>,<span class=\"number\">255</span>);</li><li class=\"alt\"> g.setColor(c);</li><li class=\"\"> g.fillRect(<span class=\"number\">0</span>, <span class=\"number\">0</span>, <span class=\"number\">68</span>, <span class=\"number\">22</span>);</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">char</span>[] ch = <span class=\"string\">\"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"</span>.toCharArray();</li><li class=\"alt\"> Random r = <span class=\"keyword\">new</span> Random();</li><li class=\"\"> <span class=\"keyword\">int</span> len = ch.length,index;</li><li class=\"alt\"> StringBuffer sb = <span class=\"keyword\">new</span> StringBuffer();</li><li class=\"\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">int</span> i=<span class=\"number\">0</span>;i<<span class=\"number\">4</span>;i++) {</li><li class=\"alt\"> index = r.nextInt(len);</li><li class=\"\"> g.setColor(<span class=\"keyword\">new</span> Color(r.nextInt(<span class=\"number\">88</span>),r.nextInt(<span class=\"number\">188</span>),r.nextInt(<span class=\"number\">255</span>)));</li><li class=\"alt\"> g.drawString(ch[index]+<span class=\"string\">\"\"</span>, (i*<span class=\"number\">15</span>)+<span class=\"number\">3</span>, <span class=\"number\">18</span>);</li><li class=\"\"> sb.append(ch[index]);</li><li class=\"alt\"> }</li><li class=\"\"> request.getSession().setAttribute(<span class=\"string\">\"piccode\"</span>, sb.toString());</li><li class=\"alt\"> ImageIO.write(bi, <span class=\"string\">\"JPG\"</span>, response.getOutputStream());</li><li class=\"\"> }</li><li class=\"alt\"> <span class=\"annotation\">@Override</span></li><li class=\"\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"alt\"> doGet(request, response);</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p><strong>LoginServlet.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.PrintWriter;</li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.ServletException;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServlet;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletResponse;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> LoginServlet <span class=\"keyword\">extends</span> HttpServlet{</li><li class=\"alt\"> <span class=\"annotation\">@Override</span></li><li class=\"\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"alt\"> String piccode = (String)request.getSession().getAttribute(<span class=\"string\">\"piccode\"</span>);</li><li class=\"\"> String checkcode = request.getParameter(<span class=\"string\">\"checkcode\"</span>);</li><li class=\"alt\"> checkcode = checkcode.toUpperCase();<span class=\"comment\">//不區分大小寫</span></li><li class=\"\"> response.setContentType(<span class=\"string\">\"text/html;charset=utf-8\"</span>);</li><li class=\"alt\"> PrintWriter out = response.getWriter();</li><li class=\"\"> <span class=\"keyword\">if</span>(piccode.equals(checkcode)) {</li><li class=\"alt\"> out.println(<span class=\"string\">\"驗證碼輸入正確\"</span>);</li><li class=\"\"> } <span class=\"keyword\">else</span> {</li><li class=\"alt\"> out.println(<span class=\"string\">\"驗證碼輸入錯誤\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"> out.flush();</li><li class=\"\"> out.close();</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"annotation\">@Override</span></li><li class=\"alt\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"\"> doPost(request, response);</li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p>三、在 web.xml 裏添加 Servlet 映射</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>ImageServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span>com.liuyanzhao.ImageServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!-- 映射爲 ImageServlet --></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>ImageServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span>/ImageServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>LoginServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span>com.liuyanzhao.LoginServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!-- 映射爲 IndexServlet --></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>LoginServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span>/LoginServlet<span class=\"tag\"><!--</span--><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></span></li></ol></div><p>四、運行 Tomcat 服務器,打開瀏覽器,訪問 http://localhost:8080/CheckCode</p><p>效果以下</p><p><img src=\"/uploads/2017/10/20171007155723341.png\" alt=\"20171007155723341.png\"><br></p><p>驗證碼不區分大小寫,點擊 「看不清楚」能夠更換</p>', '5', '2', '0', '1', '1', '1', '2018-11-25 20:53:29', '2017-10-07 15:57:38', null); INSERT INTO `article` VALUES ('10', '1', 'Integer與int的種種比較你知道多少?', '<p>若是面試官問Integer與int的區別:估計大多數人只會說道兩點,Ingeter是int的包裝類,int的初值爲0,Ingeter的初值爲null。可是若是面試官再問一下Integer a = 1;int b = 1; a==b爲true仍是爲false?估計就有一部分人答不出來了,若是再問一下其餘的,估計更多的人會頭腦一片混亂。因此我對它們進行了總結,但願對你們有幫助。</p><p><strong>首先看代碼:</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/* </span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">int</span> i = <span class=\"number\">128</span>;</li><li class=\"\"> Integer i2 = <span class=\"number\">128</span>;</li><li class=\"alt\"> Integer i3 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">128</span>);</li><li class=\"\"> <span class=\"comment\">//Integer會自動拆箱爲int,因此爲true</span></li><li class=\"alt\"> System.out.println(i == i2);<span class=\"comment\">//true</span></li><li class=\"\"> System.out.println(i == i3);<span class=\"comment\">//true</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//java在編譯的時候,被翻譯成-> Integer i5 = Integer.valueOf(127);</span></li><li class=\"alt\"> Integer i5 = <span class=\"number\">127</span>;</li><li class=\"\"> Integer i6 = <span class=\"number\">127</span>;</li><li class=\"alt\"> System.out.println(i5 == i6);<span class=\"comment\">//true</span></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> Integer i7 = <span class=\"number\">128</span>;</li><li class=\"alt\"> Integer i8 = <span class=\"number\">128</span>;</li><li class=\"\"> System.out.println(i7 == i8);<span class=\"comment\">//false</span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> Integer i9 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">127</span>);</li><li class=\"\"> Integer i10 = <span class=\"number\">127</span>;</li><li class=\"alt\"> System.out.println(i9 == i10); <span class=\"comment\">//false</span></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> Integer i11 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">128</span>);</li><li class=\"alt\"> Integer i12 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">123</span>);</li><li class=\"\"> System.out.println(i11 == i12); <span class=\"comment\">//false</span></li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\">}</li></ol></div><p><strong>詳解以下:</strong></p><p>首先,13行和14行輸出結果都爲true,由於Integer和int比都會自動拆箱(jdk1.5以上)。</p><p>19行的結果爲true,而24行則爲false,不少人都不懂爲何。其實java在編譯Integer i5 = 127的時候,被翻譯成-> Integer i5 = Integer.valueOf(127);因此關鍵就是看valueOf()函數了。只要看看valueOf()函數的源碼就會明白了。JDK源碼的valueOf函數式這樣的:</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Integer valueOf(<span class=\"keyword\">int</span> i) {</li><li class=\"\"> <span class=\"keyword\">assert</span> IntegerCache.high >= <span class=\"number\">127</span>;</li><li class=\"alt\"> <span class=\"keyword\">if</span> (i >= IntegerCache.low && i <= IntegerCache.high)</li><li class=\"\"> <span class=\"keyword\">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</li><li class=\"alt\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> Integer(i);</li><li class=\"\">}</li></ol></div><p>看一下源碼你們都會明白,對於-128到127之間的數,會進行緩存,Integer i5 = 127時,會將127進行緩存,下次再寫Integer i6 = 127時,就會直接從緩存中取,就不會new了。因此22行的結果爲true,而25行爲false。</p><p>對於29行和34行,由於對象不同,因此爲false。</p><p>我對於以上的狀況總結以下:</p><p>① 不管如何,<span><strong>Integer與new Integer不會相等</strong></span>。不會經歷拆箱過程,i3的引用指向堆,而i4指向專門存放他的內存(常量池),他們的內存地址不同,因此爲false</p><p>② <strong><span>兩個都是非new出來的Integer,若是數在-128到127之間,則是true,不然爲false</span></strong></p><p>java在編譯Integer i2 = 128的時候,被翻譯成-> Integer i2 = Integer.valueOf(128);而valueOf()函數會對-128到127之間的數進行緩存</p><p>③ <strong><span>兩</span><span>個都是new出來的,都爲false</span></strong></p><p>④ <strong><span>int和Integer(不管new否)比,都爲true</span></strong>,由於會把Integer自動拆箱爲int再去比</p><p> </p><p>參考:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html</a></p><div><br></div>', '1', '1', '1', '1', '1', '1', '2018-11-25 20:52:45', '2017-10-07 15:58:51', null); INSERT INTO `article` VALUES ('11', '1', 'Java如何讓程序一直運行,不中止', '<p>如何讓程序一直運行,很容易實現,只須要一直等待輸出便可啦</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Scanner;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">static</span> <span class=\"keyword\">final</span> String OPERATION_EXIT = <span class=\"string\">\"EXIT\"</span>;</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"請開始您的輸入,EXIT/E 退出\"</span>);</li><li class=\"\"> <span class=\"comment\">//怎麼讓程序一直運行</span></li><li class=\"alt\"> Scanner scan = <span class=\"keyword\">new</span> Scanner(System.in);</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">while</span>(scan.hasNext()) {</li><li class=\"\"> String in = scan.next().toString();</li><li class=\"alt\"> <span class=\"keyword\">if</span>(OPERATION_EXIT.equals(in.toUpperCase())</li><li class=\"\"> || OPERATION_EXIT.substring(<span class=\"number\">0</span>, <span class=\"number\">1</span>).equals(in.toUpperCase())) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"您成功已退出!\"</span>);</li><li class=\"\"> <span class=\"keyword\">break</span>;</li><li class=\"alt\"> }</li><li class=\"\"> System.out.println(<span class=\"string\">\"您輸入的值:\"</span>+in);</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\"> }</li><li class=\"\">}</li><li></li></ol></div>', '12', '2', '0', '1', '1', '1', '2018-11-25 20:47:52', '2017-10-07 15:59:33', null); INSERT INTO `article` VALUES ('12', '1', 'Java中靜態代碼塊、構造代碼塊的區別', '<p>直接在類中定義且沒有加static關鍵字的代碼塊稱爲{}構造代碼塊。</p><p><strong><span>構造代碼塊在建立對象時被調用,每次建立對象都會被調用</span></strong>,而且構造代碼塊的執行次序優先於類構造函數。</p><p>靜態代碼塊:在java中使用static關鍵字聲明的代碼塊。<span><strong>靜態塊用於初始化類,爲類的屬性初始化。每一個靜態代碼塊只會執行一次。因爲JVM在加載類時會執行靜態代碼塊,因此靜態代碼塊先於主方法執行</strong></span>。</p><p>注意:1 靜態代碼塊不能存在於任何方法體內。2 靜態代碼塊不能直接訪問靜態實例變量和實例方法,須要經過類的實例對象來訪問。</p><p>靜態代碼塊、構造代碼塊、構造函數同時存在時的執行順序:<strong><span>靜態代碼塊 > 構造代碼塊 > 構造函數</span></strong>;</p><p> </p><p>下面咱們來舉幾個例子說明一切</p><p><strong>demo1:構造方法</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"靜態塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"構造塊,在類中定義\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"構造方法執行\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\">靜態塊</span></li><li class=\"alt\"><span class=\"comment\">構造塊,在類中定義</span></li><li class=\"\"><span class=\"comment\">構造方法執行</span></li><li class=\"alt\"><span class=\"comment\">構造塊,在類中定義</span></li><li class=\"\"><span class=\"comment\">構造方法執行</span></li><li class=\"alt\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo2:普通代碼塊</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*普通代碼塊:在方法或語句中出現的{}就稱爲普通代碼塊。</span></li><li class=\"\"><span class=\"comment\">普通代碼塊和通常的語句執行順序由他們在代碼中出現的次序決定--「先出現先執行」*/</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> <span class=\"keyword\">int</span> x = <span class=\"number\">3</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"1,普通代碼塊內的變量x=\"</span> + x);</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">int</span> x = <span class=\"number\">1</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"主方法內的變量x=\"</span> + x);</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> <span class=\"keyword\">int</span> y = <span class=\"number\">7</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"2,普通代碼塊內的變量y=\"</span> + y);</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/* </span></li><li class=\"\"><span class=\"comment\">1,普通代碼塊內的變量x=3</span></li><li class=\"alt\"><span class=\"comment\">主方法內的變量x=1</span></li><li class=\"\"><span class=\"comment\">2,普通代碼塊內的變量y=7</span></li><li class=\"alt\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo3:構造代碼塊</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*構造塊:直接在類中定義且沒有加static關鍵字的代碼塊稱爲{}構造代碼塊。</span></li><li class=\"\"><span class=\"comment\">構造代碼塊在建立對象時被調用,每次建立對象都會被調用,</span></li><li class=\"alt\"><span class=\"comment\">而且構造代碼塊的執行次序優先於類構造函數。*/</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"第一代碼塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"構造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"第二構造塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\">第一代碼塊</span></li><li class=\"\"><span class=\"comment\">第二構造塊</span></li><li class=\"alt\"><span class=\"comment\">構造方法</span></li><li class=\"\"><span class=\"comment\">第一代碼塊</span></li><li class=\"alt\"><span class=\"comment\">第二構造塊</span></li><li class=\"\"><span class=\"comment\">構造方法</span></li><li class=\"alt\"><span class=\"comment\">第一代碼塊</span></li><li class=\"\"><span class=\"comment\">第二構造塊</span></li><li class=\"alt\"><span class=\"comment\">構造方法</span></li><li class=\"\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo4:靜態代碼塊</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*靜態代碼塊:在java中使用static關鍵字聲明的代碼塊。</span></li><li class=\"\"><span class=\"comment\">靜態塊用於初始化類,爲類的屬性初始化。</span></li><li class=\"alt\"><span class=\"comment\">每一個靜態代碼塊只會執行一次。</span></li><li class=\"\"><span class=\"comment\">因爲JVM在加載類時會執行靜態代碼塊,因此靜態代碼塊先於主方法執行。</span></li><li class=\"alt\"><span class=\"comment\">若是類中包含多個靜態代碼塊,那麼將按照\"先定義的代碼先執行,後定義的代碼後執行\"。</span></li><li class=\"\"><span class=\"comment\">注意:1 靜態代碼塊不能存在於任何方法體內。</span></li><li class=\"alt\"><span class=\"comment\"> 2 靜態代碼塊不能直接訪問靜態實例變量和實例方法,須要經過類的實例對象來訪問。*/</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">class</span> Code {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的構造塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的靜態代碼塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Code() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的構造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的構造塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的靜態代碼塊\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的構造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的主方法\"</span>);</li><li class=\"\"> <span class=\"keyword\">new</span> Code();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Code();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\">Test的靜態代碼塊</span></li><li class=\"\"><span class=\"comment\">Test的主方法</span></li><li class=\"alt\"><span class=\"comment\">Code的靜態代碼塊</span></li><li class=\"\"><span class=\"comment\">Code的構造塊</span></li><li class=\"alt\"><span class=\"comment\">Code的構造方法</span></li><li class=\"\"><span class=\"comment\">Code的構造塊</span></li><li class=\"alt\"><span class=\"comment\">Code的構造方法</span></li><li class=\"\"><span class=\"comment\">Test的構造塊</span></li><li class=\"alt\"><span class=\"comment\">Test的構造方法</span></li><li class=\"\"><span class=\"comment\">Test的構造塊</span></li><li class=\"alt\"><span class=\"comment\">Test的構造方法</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li></li></ol></div>', '2', '0', '0', '1', '1', '1', '2018-11-25 20:47:40', '2017-10-07 16:00:06', null); INSERT INTO `article` VALUES ('13', '1', 'sql語句分爲三類(DML,DDL,DCL)-介紹', '<p><span>DML(data manipulation language):數據庫操做語言</span><br><span>它們是SELECT、UPDATE、INSERT、DELETE,就象它的名字同樣</span></p><p> </p><p><span>DDL(data definition language):的數據庫定義語言</span><br><span>主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定義或改變表(TABLE)的結構,數據類型,表之間的連接和約束等初始化工做上,他們大多在創建表時使用</span></p><p> </p><p><span>DCL(Data Control Language): 數據庫控制語言</span><br><span>是用來設置或更改數據庫用戶或角色權限的語句,包括(grant,deny,revoke等)語句。在默認狀態下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人員纔有權力執行DCL</span></p><p> </p><p><strong>詳細解釋:</strong></p><h2>1、DDL is Data Definition Language statements</h2><p>數據定義語言,用於定義和管理 <a href=\"https://liuyanzhao.com/tag/sql/\" title=\"查看與 SQL 相關的文章\" target=\"_blank\">SQL</a> 數據庫中的全部對象的語言</p><p>1.CREATE - to create objects in the database 建立</p><p>2.ALTER - alters the structure of the database 修改</p><p>3.DROP - delete objects from the database 刪除</p><p>4.TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed</p><p>TRUNCATE TABLE [Table Name]。</p><p>下面是對Truncate語句在MS<a href=\"https://liuyanzhao.com/tag/sql/\" title=\"查看與 SQL 相關的文章\" target=\"_blank\">SQL</a>Server2000中用法和原理的說明:</p><p>Truncate table 表名 速度快,並且效率高,由於:</p><p>TRUNCATE TABLE 在功能上與不帶 WHERE 子句的 DELETE 語句相同:兩者均刪除表中的所有行。但</p><p>TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少。</p><p>DELETE 語句每次刪除一行,並在事務日誌中爲所刪除的每行記錄一項。TRUNCATE TABLE 經過釋放存</p><p>儲表數據所用的數據頁來刪除數據,而且只在事務日誌中記錄頁的釋放。</p><p>TRUNCATE TABLE 刪除表中的全部行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置爲該列的種子。若是想保留標識計數值,請改用 DELETE。若是要刪除表定義及其數據,請使用 DROP TABLE 語句。</p><p>對於由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。因爲 TRUNCATE TABLE 不記錄在日誌中,因此它不能激活觸發器。</p><p>TRUNCATE TABLE 不能用於參與了索引視圖的表。</p><p>5.COMMENT - add comments to the data dictionary 註釋</p><p>6.GRANT - gives user\'s access privileges to database 受權</p><p>7.REVOKE - withdraw access privileges given with the GRANT command 收回已經授予的權限</p><p> </p><h2>2、DML is Data Manipulation Language statements</h2><p>數據操做語言,SQL中處理數據等操做統稱爲數據操縱語言</p><p>1.SELECT - retrieve data from the a database 查詢</p><p>2.INSERT - insert data into a table 添加</p><p>3.UPDATE - updates existing data within a table 更新</p><p>4.DELETE - deletes all records from a table, the space for the records remain 刪除</p><p>5.CALL - call a PL/SQL or Java subprogram</p><p>6.EXPLAIN PLAN - explain access path to data</p><p>Oracle RDBMS執行每一條SQL語句,都必須通過Oracle優化器的評估。因此,瞭解優化器是如何選擇(搜索)路徑以及索引是如何被使用的,對優化SQL語句有很大的幫助。Explain能夠用來迅速方便地查出對於給定SQL語句中的查詢數據是如何獲得的即搜索路徑(咱們一般稱爲Access Path)。從而使咱們選擇最優的查詢方式達到最大的優化效果。</p><p>7.LOCK TABLE - control concurrency 鎖,用於控制併發</p><p> </p><h2>3、DCL is Data Control Language statements</h2><p>數據控制語言,用來授予或回收訪問數據庫的某種特權,並控制數據庫操縱事務發生的時間及效果,對數據庫實行監視等</p><p>1.COMMIT - save work done 提交</p><p>2.SAVEPOINT - identify a point in a transaction to which you can later roll back 保存點</p><p>3.ROLLBACK - restore database to original since the last COMMIT 回滾</p><p>4.SET TRANSACTION - Change transaction options like what rollback segment to use 設置當前事務的特性,它對後面的事務沒有影響</p><div><br></div>', '1', '3', '1', '1', '1', '1', '2018-11-25 20:47:30', '2017-10-07 16:00:50', null); INSERT INTO `article` VALUES ('14', '1', 'execute、executeUpdate、executeQuery三者的區別', '<p>1. ResultSet executeQuery(String sql); 執行SQL查詢,並返回 ResultSet 對象。</p><p>例如:被執行最多的 SELECT 語句。</p><p>2.int executeUpdate(String sql); 可執行增,刪,改,返回執行受到影響的行數。</p><p>例如: INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數據定義語言)語句</p><p>3. boolean execute(String sql); 可執行任何SQL語句,返回一個布爾值,表示是否返回 ResultSet 。</p><p><strong> <span> execute是executeQuery和executeUpdate的綜合.</span></strong></p><p><strong><span>一般咱們沒有必要使用execute方法來執行SQL語句,而是使用 executeQuery 或 executeUpdate 更適合。</span></strong></p><p>-----</p><p> </p><p>executeUpdate() 這是 PreparedStatement 接口中的方法</p><p>executeUpdate(String sql) 這是 PreparedStatement 從父接口 Statement 中繼承過來的方法</p><p>executeUpdate() 中執行 SQL 語句須要在建立 PerparedStatement 時經過 Connection 的 prepareStatement(String sql) 方法中寫出,由於 PerparedStatement 中的 SQL 語句數據庫須要進行預編譯和緩存,所以要在建立 PerparedStatement 對象時給出 SQL 語句。</p><p>而 executeUpdate(String sql) 是 Statement 中的方法,參數中的 SQL 語句只是提交給數據庫去執行,並不須要預編譯。</p><p><strong>若是 SQL 語句中有 ? 佔位符,那麼在設置好佔位符中的值後,必須使用 executeUpdate() 執行。而 executeUpdate(String sql) 只是提交一個 SQL 語句,且這個語句中不能帶有 ? 佔位符。</strong></p><p>固然,咱們最好不要用 Statement 接口<br>參考:http://www.cnblogs.com/bukudekong/archive/2011/06/22/2086531.html</p>', '4', '3', '0', '1', '1', '1', '2018-11-25 20:45:25', '2017-10-07 16:02:12', null); INSERT INTO `article` VALUES ('15', '1', 'JSP 中 forward 轉發 和 sendRedirect 重定向的區別', '<h2>本質區別:</h2><div> <b>一句話歸納:</b>重定向是客戶端行爲,轉發是服務器行爲.</div><div><b> 1.請求次數:</b></div><div> 重定向:重定向行爲是作了兩次請求,及產生了兩個request對象,重定向會致使request對象信息丟失。</div><div> 請求轉發:轉發作了一次請求, 瀏覽器的地址欄一直是第一次請求的地址。轉發是服務器內部request/response控制權的移交。</div><div> <b>2.請求資源地址:</b></div><p><strong>重定向</strong>:web組件能夠將請求重定向到任意一個url,而不只僅是同一個應用。</p><p>重定向的源組件與目標組件不共用同一個HttpServletRequest對象,所以不能在request範圍內共享數據。</p><p><strong>請求轉發</strong>:轉發的源組件與目標組件必須在同一個應用中,二者能夠在request範圍內共享數據。</p><div><strong> 3.一種解釋:</strong></div><div><p>假設你去辦理某個執照</p><p><strong>重定向</strong>:你先去了A局,A局的人說:「這個事情不歸咱們管,去B局」,而後,你就從A退了出來,本身乘車去了B局。</p><p><strong>請求轉發</strong>:你先去了A局,A局看了之後,知道這個事情其實應該B局來管,可是他沒有把你退回來,而是讓你坐一下子,本身到後面辦公室聯繫了B的人,讓他們辦好後,送了過來。</p></div><div><h2><b>工做流程:</b></h2></div><p><strong>1.重定向</strong></p><p>瀏覽器發出http請求 <b>>></b> 服務器接受請求併發送302狀態碼和新的對應的url到瀏覽器 <b>>></b></p><p>瀏覽器接收響應並自動請求新的url <b>>></b> 服務器接收請求並尋找客戶所需的資源響應到瀏覽器</p><p><strong>2.轉發</strong></p><p>瀏覽器發出http求其 <b>>></b> 服務器接收請求 <b>>></b> 服務器調用內部的一個方法在容器內完成請求處理和轉發動做 <b>>></b></p><p>將客戶所需資源發送到瀏覽</p><p> </p><h2><b>調用方式:</b></h2><p>咱們知道,在servlet中調用轉發、重定向的語句以下:</p><p>request.getRequestDispatcher(\"new.jsp\").forward(request, response); //轉發到new.jsp</p><p>response.sendRedirect(\"new.jsp\"); //重定向到new.jsp</p><p>在jsp頁面中你也會看到經過下面的方式實現轉發:</p><p><jsp:forward page=\"apage.jsp\"></jsp:forward></p><p>固然也能夠在jsp頁面中實現重定向:</p><p><%response.sendRedirect(\"new.jsp\"); %> //重定向到new.jsp</p><p> </p><div> <strong> 1.重定向:</strong></div><div> 1).response.sendRedirect(url);</div><div> 2).response.setState(302);</div><div> response.setHeader(\"location\",url);</div><div><strong> 2.轉發:</strong></div><div> 1).request.getRequestDispatcher(url).forward(request,response);</div><div> 2).request.getRequestDispatcher(url).include(request,response);</div><div> 3).<jsp:forward page=\"url\"></jsp:forward></div>', '1', '0', '0', '1', '1', '1', '2018-11-25 20:47:10', '2017-10-07 16:03:08', null); INSERT INTO `article` VALUES ('16', '1', 'Java中File類的使用', '<h2>1、File類經常使用API介紹</h2><p>內容見代碼和註釋</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.File;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> * @author WellsLiu</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"\"> <span class=\"comment\">//1.建立一個文件夾對象</span></li><li class=\"alt\"> File file = <span class=\"keyword\">new</span> File(<span class=\"string\">\"F:\\\\桌面\\\\music\"</span>);</li><li class=\"\"> <span class=\"comment\">//判斷文件是否存在</span></li><li class=\"alt\"> System.out.println(file.exists());<span class=\"comment\">//true</span></li><li class=\"\"> <span class=\"comment\">//若是文件夾不存在建立之,不然刪除之</span></li><li class=\"alt\"> <span class=\"keyword\">if</span>(!file.exists())</li><li class=\"\"> file.mkdir();<span class=\"comment\">//建立文件夾</span></li><li class=\"alt\"> <span class=\"comment\">//else </span></li><li class=\"\"> <span class=\"comment\">//file.delete();</span></li><li class=\"alt\"> <span class=\"comment\">//是不是一個目錄</span></li><li class=\"\"> System.out.println(file.isDirectory());<span class=\"comment\">//true</span></li><li class=\"alt\"> <span class=\"comment\">//是不是一個文件</span></li><li class=\"\"> System.out.println(file.isFile());<span class=\"comment\">//false</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//2.建立一個文件對象</span></li><li class=\"alt\"> File file2 = <span class=\"keyword\">new</span> File(<span class=\"string\">\"F:\\\\桌面\\\\music\\\\1.mp3\"</span>);</li><li class=\"\"> System.out.println(file.exists());</li><li class=\"alt\"> <span class=\"comment\">//若是文件不存在建立之,不然刪除 之</span></li><li class=\"\"> <span class=\"keyword\">if</span>(file2.exists())</li><li class=\"alt\"> <span class=\"keyword\">try</span> {</li><li class=\"\"> file2.createNewFile();</li><li class=\"alt\"> } <span class=\"keyword\">catch</span> (IOException e) {</li><li class=\"\"> e.printStackTrace();</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"comment\">//else </span></li><li class=\"alt\"> <span class=\"comment\">//file2.delete();</span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//3.經常使用的File對象API</span></li><li class=\"\"> System.out.println(file);<span class=\"comment\">//file.toString()的內容,F:\\桌面\\music</span></li><li class=\"alt\"> System.out.println(file.getAbsolutePath());<span class=\"comment\">//file的絕對路徑F:\\桌面\\music</span></li><li class=\"\"> System.out.println(file.getName());<span class=\"comment\">//music</span></li><li class=\"alt\"> System.out.println(file2.getName());<span class=\"comment\">//1.mp3</span></li><li class=\"\"> System.out.println(file.getParent());<span class=\"comment\">//F:\\桌面</span></li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p> </p><h2>2、遍歷目錄</h2><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.File;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> * @author WellsLiu</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">//列出File類一些經常使用操做好比過濾、遍歷等操做</span></li><li class=\"alt\"><span class=\"keyword\">class</span> FileUtils {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//列出指定目錄下(包括子目錄)的全部文件</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> listDirectory(File dir) <span class=\"keyword\">throws</span> IOException{</li><li class=\"alt\"> <span class=\"keyword\">if</span>(!dir.exists()) {</li><li class=\"\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> IllegalArgumentException(<span class=\"string\">\"目錄\"</span>+dir+<span class=\"string\">\"不存在\"</span>);</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"keyword\">if</span>(!dir.isDirectory()) { <span class=\"comment\">//判斷File類的對象是否爲文件夾</span></li><li class=\"alt\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> IllegalArgumentException(dir+<span class=\"string\">\"不是目錄\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"> <span>/*</span></li><li class=\"\"><span class=\"comment\"> //1.輸出dir目錄下的一級文件夾和文件</span></li><li class=\"alt\"><span class=\"comment\"> String [] filenames = dir.list();//返回的是字符串數組 直接子名稱</span></li><li class=\"\"><span class=\"comment\"> for (String string : filenames) {</span></li><li class=\"alt\"><span class=\"comment\"> System.out.println(dir+\"\\\\\"+string);//dirstring是文件或文件夾名</span></li><li class=\"\"><span class=\"comment\"> }</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//2.若是要遍歷子目錄下的目錄及全部文件,就須要構造File對象作遞歸操做</span></li><li class=\"\"> File[] files = dir.listFiles();<span class=\"comment\">//返回的是直接子目錄(文件)的抽象</span></li><li class=\"alt\"> <span class=\"keyword\">if</span>(files!=<span class=\"keyword\">null</span>&&files.length><span class=\"number\">0</span>) {</li><li class=\"\"> <span class=\"keyword\">for</span>(File file:files) {</li><li class=\"alt\"> <span class=\"keyword\">if</span>(file.isDirectory()) {</li><li class=\"\"> <span class=\"comment\">//遞歸</span></li><li class=\"alt\"> listDirectory(file);</li><li class=\"\"> } <span class=\"keyword\">else</span> {</li><li class=\"alt\"> System.out.println(file);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test1 {</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) <span class=\"keyword\">throws</span> IOException{</li><li class=\"alt\"> FileUtils.listDirectory(<span class=\"keyword\">new</span> File(\"C:\\\\Users\\\\Liu_Yanzhao\"));</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div>', '5', '0', '0', '1', '1', '1', '2018-11-25 20:46:43', '2017-10-07 16:04:25', null); INSERT INTO `article` VALUES ('17', '1', 'java中ImageIcon路徑問題', '<h2><strong>1、問題</strong></h2><p>ImageIcon icon = new ImageIcon(\"logo.jpg\");</p><p>執行結果是icon沒法顯示</p><p> </p><h2><strong>2、解決</strong></h2><p>類中有以下調用:</p><p><span>ImageIcon icon = new ImageIcon(\"1.jpg\");</span></p><p> </p><p>很天然地認爲當前類文件和圖片在同一路徑下便可。</p><p><span><strong>其實所謂的相對路徑起點是工程的根目錄,即project。</strong></span></p><p>這行代碼執行時在project目錄下查找名爲a.gif的文件,結果固然是找不到。</p><p>要獲得工程的相對路徑可經過System.getProperty(\"user.dir\")獲得。</p><p>對圖片和對文件的查找應該是一致的,如new File()。</p><p> </p><p>一、假如你的工程根目錄爲:Project1</p><p>你的圖片文件放在:Project1/src/images/1.jpg</p><p>因此正確的調用是(不要加Project1):</p><p>ImageIcon icon = new ImageIcon(\"src/images/1.jpg\");</p><p> </p><p>二、假如你的工程根目錄爲:Project1</p><p>你的圖片文件在:Project1/src/com.liuyanzhao/1.jpg</p><p>因此正確的調用是(<strong>com.liuyanzhao</strong>是包名)</p><p>ImageIcon icon = new ImageIcon(\"src/com/liuyanzhao/1.jpg\");</p><p>這行代碼執行時在project/test目錄下查找到了文件</p><p> </p><p><strong>總結起來就是一句話:所謂相對路徑就是相對於工程根目錄的位置^_^</strong></p><p> </p><h2>3、其餘</h2><p>查看了一下ImageIcon的構造函數。</p><p>Public ImageIcon(String filename)//參數能夠是絕對路徑也能夠是相對路徑</p><p>Public ImageIcon(URL url)</p><p> </p><p>第一種構造不在贅述。</p><p>第二種經過URL來獲得圖片</p><p>URL url = getClass().getResource(\"a.gif\"); //當前編譯後class文件所在目錄查找</p><p>ImageIcon icon = new ImageIcon(url);</p><p> </p><p>ImageIcon支持GIF、JPG、PNG等格式。</p>', '10', '5', '0', '1', '1', '1', '2018-11-25 20:46:27', '2017-10-07 16:05:55', null); INSERT INTO `article` VALUES ('27', '1', 'SpringCloud 中使用 Eureka 和 Feign 實現增刪改查', '<p>在沒有接觸微服務或者分佈式項目以前,咱們的項目時沒有分層的,咱們的服務也是沒有分層的。</p><p>好比,咱們有5臺服務器使用 Nginx 作負載均衡,上面都是安裝了咱們的 Tomcat 服務器,部署的同樣的項目。當用戶訪問某個請求的時候,按照負載均衡的機制(隨機、輪詢之類)來轉發到對應的服務器上,而後在該服務器上先是到 Controller,而後 Service,再到 DAO,而後返回給 Service,返回給 Controller,最後返回給前臺。彷佛這樣也行。</p><p>可是當咱們網站訪問量不斷飆升的時候,彷佛有點撐不住了,只能加服務器,成本也明顯增長。咱們能不能再分一分呢 ?</p><p>同時,咱們發現真正比較耗費時間的是一些 IO 操做,好比數據庫操做、上傳文件之類的。爲了方便開發,咱們能夠把 DAO 和 Service 層放在一塊兒,暫且稱爲業務層。業務層耗費的遠遠大於 Controller 層的。咱們能夠在 5 臺服務器中拿 1 臺部署 Controller 層,另外 4 臺部署業務層代碼。</p><p>若是將他們鏈接起來呢?</p><p>Eureka + Feign!</p><p>Eureka 作註冊中心,業務層和控制器層每個實例能夠做爲一個服務,好比 UserService 是一個服務,UserController 也能夠是一個服務,一個服務能夠有多個狀態(能夠有多臺機器註冊到該服務)。</p><p>下面經過一個例子來說解</p><p> </p><p>源碼地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/saysky/spring-cloud-demo\">https://github.com/saysky/spring-cloud-demo</a></p><p> </p><h2>1、下載源碼</h2><p>請上 Github 上下載本例子源碼</p><p>源碼地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/saysky/spring-cloud-demo\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/saysky/spring-cloud-demo</a></p><p> </p><h2>2、項目結構</h2><p>注意這是三個項目(不是一個項目),用 IDEA 打開分別打開三個項目,最終如圖</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8631 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"595\" height=\"224\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-300x113.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-768x289.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-530x200.png 530w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40.png 1334w\" sizes=\"(max-width: 595px) 100vw, 595px\"></a></p><p> </p><p>一、eureka-server(一個 SpringBoot 項目)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8633 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"420\" height=\"262\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png 772w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server-300x187.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server-768x480.png 768w\" sizes=\"(max-width: 420px) 100vw, 420px\"></a></p><p> </p><p> </p><p>二、cloud (一個多模塊項目,API + 業務層) <a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8632 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"418\" height=\"121\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png 574w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2-300x87.png 300w\" sizes=\"(max-width: 418px) 100vw, 418px\"></a></p><p> </p><p> </p><p>(1)其中 cloud-api 是 api,裏面有 model 和 service接口,cloud-core 和 cloud-web 將依賴它</p><p>到時候須要首先將該模塊 install,即打包到本地倉庫中</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8634 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"463\" height=\"414\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png 672w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/api-300x269.png 300w\" sizes=\"(max-width: 463px) 100vw, 463px\"></a></p><p> </p><p>(2)其中 cloud-core,裏面 dao 和 serviceImpl,做爲生產者的存在</p><p>啓動類在這裏面</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8635 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"439\" height=\"460\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png 800w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/core-286x300.png 286w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/core-768x804.png 768w\" sizes=\"(max-width: 439px) 100vw, 439px\"></a></p><p> </p><p>三、cloud-web( 一個 SpringBoot 項目)</p><p>只有控制器層,須要依賴 cloud-api ,做爲消費者的存在(能夠是其餘人調用)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8636 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"439\" height=\"359\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png 746w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web-300x245.png 300w\" sizes=\"(max-width: 439px) 100vw, 439px\"></a></p><p> </p><h2>3、如何啓動</h2><p>一、新建數據庫 summer,導入 user.sql</p><p>二、導入新項目,前後順序隨便(如eureka-server、cloud、cloud-web)</p><p>三、啓動 eureka-server 項目,端口爲 8761</p><p>四、對 cloud 項目中的 cloud-api 模塊進行install,maven命令是 mvn clean install</p><p>五、啓動 cloud-core 項目,端口爲 8090</p><p>六、(可選)其實這時候咱們能夠在地址欄訪問一下 localhost:8090/user 實際上是能夠訪問的,若是你不行,說明有問題</p><p>七、啓動 cloud-web 項目,端口爲 8080</p><p>八、在地址欄訪問 localhost:8080/user,若是能夠看到數據,說明成功</p><p> </p><h2>4、補充</h2><p>一、我這裏模擬了四臺註冊了業務層服務(cloud-producer) 和 一臺控制器層服務(cloud-consumer)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8637 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"644\" height=\"412\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-300x192.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-768x491.png 768w\" sizes=\"(max-width: 644px) 100vw, 644px\"></a></p><p>ps:由於我是用本機測試,因此開了不一樣的端口表示不一樣的服務器</p><p> </p><p>二、訪問控制器層,而後 Feign 會幫咱們在註冊中心中找到對應的服務名和對應的方法</p><p>咱們訪問 localhost:8080/user/1 首先到的是控制器層,控制器層調用 userService,userService 是 Cloud-API 裏的,添加了 @FeignClient(name=\"cloud-producer\") 註解,而後找到在註冊中心中尋找 cloud-producer 的服務,從一臺(負載均衡)服務器中找到 userService 的實現類,即 userServiceImpl,也就是進入了 cloud-core,而後完成一系列 DAO 和 Service 操做,最後返回給 Controller。</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8638 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"625\" height=\"415\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-300x199.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-768x510.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080.png 1148w\" sizes=\"(max-width: 625px) 100vw, 625px\"></a></p><p>其中 Service 和 Service 的實現都須要加 RequestMapping,Service 實現須要加 @RestController,不然會出現 404</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8639 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"627\" height=\"228\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-300x109.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-768x280.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api.png 1538w\" sizes=\"(max-width: 627px) 100vw, 627px\"></a></p><p>因此,其實咱們能夠直接訪問 cloud-core 這一層,在地址欄訪問 localhost:8090/user/1</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8640 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"497\" height=\"383\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png 784w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2-300x231.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2-768x592.png 768w\" sizes=\"(max-width: 497px) 100vw, 497px\"></a></p><p> </p><p>事實上,咱們訪問 控制器的時候,當須要某個 Service 的時候,Feign 幫咱們向 Service 又發了一個一樣的請求。咱們能夠直接訪問這個 Service 請求</p><p>可是,一般咱們會在生產環境中,不讓別人直接訪問到 Service,能夠經過一些機制實現,好比內網啦。</p><p> </p><h2>6、學習過程當中遇到的問題</h2><p>一、cloud-web 中注入 userService,一直注入失敗,沒法掃描到 userServiceImpl</p><p>解決方案:在 cloud-web 啓動類上添加</p><p>@EnableFeignClients(basePackages = \"com.liuyanzhao.cloud\")</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8641 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"566\" height=\"159\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-300x84.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-768x216.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22.png 1572w\" sizes=\"(max-width: 566px) 100vw, 566px\"></a></p><p> </p><p>二、出現 404 錯誤</p><p>cloud-core 裏的 userServiceImpl 也須要加 @RequestMapping,而且須要將 @Service 改爲 @RestController</p><p> </p><p>UserService(cloud-api)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8643 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"615\" height=\"363\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-300x177.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-768x454.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23.png 1334w\" sizes=\"(max-width: 615px) 100vw, 615px\"></a></p><p> </p><p>UserServiceImpl(cloud-core)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8642 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"623\" height=\"278\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-300x134.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-768x343.png 768w\" sizes=\"(max-width: 623px) 100vw, 623px\"></a></p><p> </p>', '0', '0', '0', '1', '1', '1', '2019-04-25 21:43:14', '2018-11-25 20:56:50', '在沒有接觸微服務或者分佈式項目以前,咱們的項目時沒有分層的,咱們的服務也是沒有分層的。好比,咱們有5臺服務器使用 Nginx 作負載均衡,上面都是安裝了咱們的 Tomcat 服務器,部署的同樣的項目。當用戶訪問某個請求的時候,按照負載均衡的機制(隨機、輪詢之類)來轉發到對應的服務器上,而後在該服務器'); INSERT INTO `article` VALUES ('23', '1', '是是是搜索', '是是', '5', '0', '0', '1', '0', '1', '2018-11-25 23:56:08', '2018-11-25 16:47:05', null); INSERT INTO `article` VALUES ('24', '1', 'sssss', 'sssss', '0', '0', '0', '1', '0', '1', '2018-11-25 17:28:38', '2018-11-25 17:19:09', null); INSERT INTO `article` VALUES ('25', '1', 'sssssssss', 'ssssssss', '1', '0', '0', '1', '0', '1', '2018-11-25 17:25:31', '2018-11-25 17:22:10', null); INSERT INTO `article` VALUES ('26', '1', 'SpringBoot 整合 elasticsearch 實例', '<p>上一篇文章介紹了安裝 <a href=\"https://liuyanzhao.com/7152.html\" target=\"_blank\" rel=\"noopener noreferrer\">mac 上安裝 elasticsearch</a></p><p>本文介紹 <a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a> 集成 elasticsearch</p><p> </p><h2>1、下載 並啓動 elasticsearch</h2><p>下載地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://www.elastic.co/downloads/past-releases\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.elastic.co/downloads/past-releases</a></p><p>選擇一個版本,下載</p><p>博主這裏測試使用的是 2.4.4</p><p>下載方式能夠選擇 ZIP 包</p><p> </p><p>啓動的話,windows 和 mac 有些細微區別</p><p>windows :進入文件目錄下的 bin,而後點擊 elasticsearch.bat 便可</p><p>mac:在終端執行命令 bin/elasticsearch</p><p> </p><p> </p><h2>2、配置 Maven</h2><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"comments\"><!-- Spring Boot Elasticsearch 依賴 --></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">dependency</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">groupId</span><span class=\"tag\">></span>org.springframework.boot<span class=\"tag\"></</span><span class=\"tag-name\">groupId</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span>spring-boot-starter-data-elasticsearch<span class=\"tag\"></</span><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">dependency</span><span class=\"tag\">></span></li></ol></div><p> </p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">properties</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">elasticsearch.version</span><span class=\"tag\">></span>2.4.4<span class=\"tag\"></</span><span class=\"tag-name\">elasticsearch.version</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">properties</span><span class=\"tag\">></span></li></ol></div><p> </p><p> </p><p>添加 spring-boot-starter-data-elasticsearch 依賴,並設置 elasticsearch 版本爲 2.4.4</p><p> </p><p>ES 和 SpirngBoot 版本參考:</p><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/spring-projects/spring-data-elasticsearch/wiki/Spring-Data-Elasticsearch---Spring-Boot---version-matrix\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/spring-projects/spring-data-elasticsearch/wiki/Spring-Data-Elasticsearch---Spring-Boot---version-matrix</a></p><p> </p><h2>3、修改 application.properties</h2><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\">#Project</li><li class=\"\"><span class=\"attribute\">server.port</span>=<span class=\"attribute-value\">8080</span></li><li class=\"alt\"><span class=\"attribute\">debug</span>=<span class=\"attribute-value\">true</span></li><li class=\"\"><span class=\"attribute\">server.context-path</span>=/chuyun</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"># DataSource</li><li class=\"\"><span class=\"attribute\">spring.datasource.driver-class-name</span>=<span class=\"attribute-value\">com</span>.mysql.jdbc.Driver</li><li class=\"alt\"><span class=\"attribute\">spring.datasource.username</span>=<span class=\"attribute-value\">root</span></li><li class=\"\"><span class=\"attribute\">spring.datasource.password</span>=<span class=\"attribute-value\">123456</span></li><li class=\"alt\"><span class=\"attribute\">spring.datasource.url</span>=<span class=\"attribute-value\">jdbc</span>:mysql://localhost:3306/chuyun?<span class=\"attribute\">characterEncodeing</span>=<span class=\"attribute-value\">utf</span>-8&<span class=\"attribute\">useSSL</span>=<span class=\"attribute-value\">false</span></li><li class=\"\"></li><li class=\"alt\"># JPA</li><li class=\"\"><span class=\"attribute\">spring.jpa.show-sql</span>=<span class=\"attribute-value\">true</span></li><li class=\"alt\"><span class=\"attribute\">spring.jpa.hibernate.ddl-auto</span>=<span class=\"attribute-value\">update</span></li><li class=\"\"></li><li class=\"alt\">#Thymeleaf</li><li class=\"\"><span class=\"attribute\">spring.thymeleaf.encoding</span>=<span class=\"attribute-value\">UTF</span>-8</li><li class=\"alt\"><span class=\"attribute\">spring.thymeleaf.cache</span>=<span class=\"attribute-value\">false</span></li><li class=\"\"><span class=\"attribute\">spring.thymeleaf.cache-period</span>=<span class=\"attribute-value\">0</span></li><li class=\"alt\"><span class=\"attribute\">spring.template.cache</span>=<span class=\"attribute-value\">false</span></li><li class=\"\"><span class=\"attribute\">spring.thymeleaf.mode</span>=<span class=\"attribute-value\">HTML5</span></li><li class=\"alt\"><span class=\"attribute\">spring.thymeleaf.prefix</span>=<span class=\"attribute-value\">classpath</span>:templates/</li><li class=\"\"><span class=\"attribute\">spring.thymeleaf.suffix</span>=.html</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\">#Elasticsearch</li><li class=\"\"><span class=\"attribute\">spring.data.elasticsearch.cluster-nodes</span>=<span class=\"attribute-value\">localhost</span>:9300</li><li class=\"alt\"><span class=\"attribute\">spring.data.elasticsearch.properties.transport.tcp.connect_timeout</span>=<span class=\"attribute-value\">120s</span></li></ol></div><p>主要是添加最後面兩條</p><p> </p><h2>4、建立 ES Bean 和 Repository</h2><p>Article.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.chuyun.domain.es;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.elasticsearch.annotations.Document;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> javax.persistence.Id;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"\"><span class=\"comment\"> * @date 2018/1/22 下午4:45</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Document</span>(indexName=<span class=\"string\">\"chuyun\"</span>,type=<span class=\"string\">\"article\"</span>,indexStoreType=<span class=\"string\">\"fs\"</span>,shards=<span class=\"number\">5</span>,replicas=<span class=\"number\">1</span>,refreshInterval=<span class=\"string\">\"-1\"</span>)</li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Article {</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//文章ID,這裏必須爲 id</span></li><li class=\"alt\"> <span class=\"annotation\">@Id</span></li><li class=\"\"> <span class=\"keyword\">private</span> Long id;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//標題</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> String title;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//內容</span></li><li class=\"\"> <span class=\"keyword\">private</span> String content;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//瀏覽量</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Integer viewCount;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//發佈時間</span></li><li class=\"\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//更新時間</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Date updateTime;</li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Article() {</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Long getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(Long id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getTitle() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> title;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setTitle(String title) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.title = title;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getContent() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> content;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setContent(String content) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.content = content;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Integer getViewCount() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> viewCount;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setViewCount(Integer viewCount) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.viewCount = viewCount;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getCreateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setCreateTime(Date createTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.createTime = createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getUpdateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> updateTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUpdateTime(Date updateTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.updateTime = updateTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Override</span></li><li class=\"\"> <span class=\"keyword\">public</span> String toString() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> <span class=\"string\">\"Article{\"</span> +</li><li class=\"\"> <span class=\"string\">\"id=\"</span> + id +</li><li class=\"alt\"> <span class=\"string\">\", title=\'\"</span> + title + <span class=\"string\">\'\\\'\'</span> +</li><li class=\"\"> <span class=\"string\">\", content=\'\"</span> + content + <span class=\"string\">\'\\\'\'</span> +</li><li class=\"alt\"> <span class=\"string\">\", viewCount=\"</span> + viewCount +</li><li class=\"\"> <span class=\"string\">\", createTime=\"</span> + createTime +</li><li class=\"alt\"> <span class=\"string\">\", updateTime=\"</span> + updateTime +</li><li class=\"\"> \'}\';</li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p> </p><p>ArticleRepository.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.chuyun.repository.es;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.chuyun.domain.es.Article;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Page;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.domain.Pageable;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.elasticsearch.repository.ElasticsearchRepository;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"\"><span class=\"comment\"> * @date 2018/1/22 下午5:05</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">interface</span> ArticleRepository <span class=\"keyword\">extends</span> ElasticsearchRepository<Article, Long> {</li><li class=\"\"></li><li class=\"alt\"> Page<Article> findDistinctByTitleContainingOrContentContaining(String title, String content, Pageable pageable);</li><li class=\"\">}</li></ol></div><p> </p><p> </p><h2>5、建立測試類</h2><p>ArticleRepositoryTest.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.chuyun.repository.es;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.chuyun.domain.es.Article;</li><li class=\"\"><span class=\"keyword\">import</span> com.liuyanzhao.chuyun.entity.User;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.junit.Before;</li><li class=\"\"><span class=\"keyword\">import</span> org.junit.Test;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.junit.runner.RunWith;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Autowired;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.boot.test.context.<a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a>Test;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Page;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.domain.PageRequest;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Pageable;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.test.context.junit4.SpringRunner;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"alt\"><span class=\"comment\"> * @date 2018/1/21 下午5:03</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@RunWith</span>(SpringRunner.<span class=\"keyword\">class</span>)</li><li class=\"\"><span class=\"annotation\">@<a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a>Test</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> ArticleRepositoryTest {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Autowired</span></li><li class=\"\"> <span class=\"keyword\">private</span> ArticleRepository articleRepository;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"annotation\">@Before</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> initRepositoryData() {</li><li class=\"\"> <span class=\"comment\">//清除全部數據</span></li><li class=\"alt\"> articleRepository.deleteAll();</li><li class=\"\"> Article article = <span class=\"keyword\">new</span> Article();</li><li class=\"alt\"> article.setId((<span class=\"keyword\">long</span>) <span class=\"number\">1</span>);</li><li class=\"\"> article.setTitle(<span class=\"string\">\"《蝶戀花》\"</span>);</li><li class=\"alt\"> article.setContent(<span class=\"string\">\"檻菊愁煙蘭泣露,羅幕輕寒,燕子雙飛去。明月不諳離恨苦,斜光到曉穿朱戶。昨夜西風凋碧樹,獨上高樓,望盡天涯路。欲寄彩箋兼尺素,山長水闊知何處?\"</span>);</li><li class=\"\"> article.setCreateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"alt\"> article.setUpdateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> article.setViewCount(<span class=\"number\">678</span>);</li><li class=\"alt\"> articleRepository.save(article);</li><li class=\"\"></li><li class=\"alt\"> Article article2 = <span class=\"keyword\">new</span> Article();</li><li class=\"\"> article2.setId((<span class=\"keyword\">long</span>) <span class=\"number\">2</span>);</li><li class=\"alt\"> article2.setTitle(<span class=\"string\">\"《蝶戀花》\"</span>);</li><li class=\"\"> article2.setContent(<span class=\"string\">\"佇倚危樓風細細,望極春愁,黯黯生天際。草色煙光殘照裏,無言誰會憑闌意。擬把疏狂圖一醉,對酒當歌,強樂還無味。衣帶漸寬終不悔,爲伊消得人憔悴。\"</span>);</li><li class=\"alt\"> article2.setCreateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> article2.setUpdateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"alt\"> article.setViewCount(<span class=\"number\">367</span>);</li><li class=\"\"> articleRepository.save(article2);</li><li class=\"alt\"></li><li class=\"\"> Article article3 = <span class=\"keyword\">new</span> Article();</li><li class=\"alt\"> article3.setId((<span class=\"keyword\">long</span>) <span class=\"number\">3</span>);</li><li class=\"\"> article3.setTitle(<span class=\"string\">\"《青玉案·元夕》\"</span>);</li><li class=\"alt\"> article3.setContent(<span class=\"string\">\"東風夜放花千樹,更吹落,星如雨。寶馬雕車香滿路。鳳簫聲動,玉壺光轉,一晚上魚龍舞。蛾兒雪柳黃金縷,笑語盈盈暗香去。衆裏尋他千百度,驀然回首,那人卻在,燈火闌珊處。\"</span>);</li><li class=\"\"> article3.setCreateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"alt\"> article3.setUpdateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> article3.setViewCount(<span class=\"number\">786</span>);</li><li class=\"alt\"> articleRepository.save(article3);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"annotation\">@Test</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> findDistinctByTitleContainingOrContentContainingTest() <span class=\"keyword\">throws</span> Exception {</li><li class=\"\"> Pageable pageable = <span class=\"keyword\">new</span> PageRequest(<span class=\"number\">0</span>,<span class=\"number\">20</span>);</li><li class=\"alt\"> String title = <span class=\"string\">\"我愛羅琪\"</span>;</li><li class=\"\"> String content = <span class=\"string\">\"花千樹\"</span>;</li><li class=\"alt\"> Page<Article> page = articleRepository.findDistinctByTitleContainingOrContentContaining(title, content, pageable);</li><li class=\"\"> System.out.println(page);</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"---start---\"</span>);</li><li class=\"\"> <span class=\"keyword\">for</span>(Article article : page.getContent()) {</li><li class=\"alt\"> System.out.println(article.toString());</li><li class=\"\"> }</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"---end---\"</span>);</li><li class=\"\"></li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\">}</li></ol></div><p> </p><p>運行 @Test 註解的方法</p><p>根據 title 和 content 內容查到一條數據</p><p><img class=\"wp-image-7176 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es9-1024x243.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es9-1024x243.jpg\" alt=\"SpringBoot 整合 elasticsearch 實例\" width=\"652\" height=\"155\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es9-1024x243.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es9-300x71.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es9-768x182.jpg 768w\" sizes=\"(max-width: 652px) 100vw, 652px\"></p><p> </p><p>修改 title 和 content</p><pre>String title = \"蝶戀\";\r\nString content = \"東風\";</pre><p>查到三條數據</p><p><img class=\"wp-image-7177 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es10-1024x135.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es10-1024x135.jpg\" alt=\"SpringBoot 整合 elasticsearch 實例\" width=\"654\" height=\"86\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es10-1024x135.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es10-300x40.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es10-768x102.jpg 768w\" sizes=\"(max-width: 654px) 100vw, 654px\"></p><p> </p><h2>6、訪問 http://localhost:9200/_plugin/head/</h2><p>由於上一篇文章中,咱們講了裝一個 head 插件,如今咱們就能看到裏面的數據了(多餘的數據是以前測試的)</p><p><img class=\"wp-image-7182 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es12-1024x363.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es12-1024x363.jpg\" alt=\"SpringBoot 整合 elasticsearch 實例\" width=\"667\" height=\"236\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es12-1024x363.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es12-300x106.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es12-768x272.jpg 768w\" sizes=\"(max-width: 667px) 100vw, 667px\"></p><h2></h2><h2>7、新建 Controller 類</h2><p>ArticleController.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.chuyun.controller;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.chuyun.domain.es.Article;</li><li class=\"\"><span class=\"keyword\">import</span> com.liuyanzhao.chuyun.repository.es.ArticleRepository;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Autowired;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Page;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.domain.PageRequest;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Pageable;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.web.bind.annotation.RequestMapping;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.web.bind.annotation.RequestParam;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.web.bind.annotation.RestController;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"alt\"><span class=\"comment\"> * @date 2018/1/22 下午9:07</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@RestController</span></li><li class=\"\"><span class=\"annotation\">@RequestMapping</span>(<span class=\"string\">\"/article\"</span>)</li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> ArticleController {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Autowired</span></li><li class=\"\"> <span class=\"keyword\">private</span> ArticleRepository ArticleRepository;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"annotation\">@RequestMapping</span>(<span class=\"string\">\"\"</span>)</li><li class=\"alt\"> <span class=\"keyword\">public</span> List<Article> list(<span class=\"annotation\">@RequestParam</span>(value = <span class=\"string\">\"title\"</span>, required = <span class=\"keyword\">false</span>) String title,</li><li class=\"\"> <span class=\"annotation\">@RequestParam</span>(value = <span class=\"string\">\"content\"</span>, required = <span class=\"keyword\">false</span>) String content,</li><li class=\"alt\"> <span class=\"annotation\">@RequestParam</span>(value = <span class=\"string\">\"pageIndex\"</span>, defaultValue = <span class=\"string\">\"0\"</span>) <span class=\"keyword\">int</span> pageIndex,</li><li class=\"\"> <span class=\"annotation\">@RequestParam</span>(value = <span class=\"string\">\"pageSize\"</span>, defaultValue = <span class=\"string\">\"10\"</span>) <span class=\"keyword\">int</span> pageSize) {</li><li class=\"alt\"> Pageable pageable = <span class=\"keyword\">new</span> PageRequest(pageIndex, pageSize);</li><li class=\"\"> Page<Article> page = ArticleRepository.findDistinctByTitleContainingOrContentContaining(title, content, pageable);</li><li class=\"alt\"> <span class=\"keyword\">return</span> page.getContent();</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p> </p><p>由於以前在 測試類 裏已經給 elasticsearch 添加了數據</p><p>全部如今能夠在瀏覽器上訪問:</p><p>http://localhost:8080/chuyun/article?title=浪淘沙&content=伊人</p><p><img class=\"wp-image-7181 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es11-1024x372.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es11-1024x372.jpg\" alt=\"SpringBoot 整合 elasticsearch 實例\" width=\"646\" height=\"235\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/01/es11-1024x372.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es11-300x109.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/01/es11-768x279.jpg 768w\" sizes=\"(max-width: 646px) 100vw, 646px\"></p><p> </p><p> </p><p> </p><p>本文地址:<a href=\"https://liuyanzhao.com/7170.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://liuyanzhao.com/7170.html</a></p>', '1', '0', '0', '1', '1', '1', '2018-11-25 20:42:58', '2018-11-25 20:42:58', null); INSERT INTO `article` VALUES ('28', '1', 'SpringCloud 中使用 Eureka 和 Feign 實現增刪改查', '<p>在沒有接觸微服務或者分佈式項目以前,咱們的項目時沒有分層的,咱們的服務也是沒有分層的。</p><p>好比,咱們有5臺服務器使用 Nginx 作負載均衡,上面都是安裝了咱們的 Tomcat 服務器,部署的同樣的項目。當用戶訪問某個請求的時候,按照負載均衡的機制(隨機、輪詢之類)來轉發到對應的服務器上,而後在該服務器上先是到 Controller,而後 Service,再到 DAO,而後返回給 Service,返回給 Controller,最後返回給前臺。彷佛這樣也行。</p><p>可是當咱們網站訪問量不斷飆升的時候,彷佛有點撐不住了,只能加服務器,成本也明顯增長。咱們能不能再分一分呢 ?</p><p>同時,咱們發現真正比較耗費時間的是一些 IO 操做,好比數據庫操做、上傳文件之類的。爲了方便開發,咱們能夠把 DAO 和 Service 層放在一塊兒,暫且稱爲業務層。業務層耗費的遠遠大於 Controller 層的。咱們能夠在 5 臺服務器中拿 1 臺部署 Controller 層,另外 4 臺部署業務層代碼。</p><p>若是將他們鏈接起來呢?</p><p>Eureka + Feign!</p><p>Eureka 作註冊中心,業務層和控制器層每個實例能夠做爲一個服務,好比 UserService 是一個服務,UserController 也能夠是一個服務,一個服務能夠有多個狀態(能夠有多臺機器註冊到該服務)。</p><p>下面經過一個例子來說解</p><p> </p><p>源碼地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/saysky/spring-cloud-demo\">https://github.com/saysky/spring-cloud-demo</a></p><p> </p><h2>1、下載源碼</h2><p>請上 Github 上下載本例子源碼</p><p>源碼地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/saysky/spring-cloud-demo\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/saysky/spring-cloud-demo</a></p><p> </p><h2>2、項目結構</h2><p>注意這是三個項目(不是一個項目),用 IDEA 打開分別打開三個項目,最終如圖</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8631 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"595\" height=\"224\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-1024x385.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-300x113.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-768x289.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40-530x200.png 530w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/springcloud40.png 1334w\" sizes=\"(max-width: 595px) 100vw, 595px\"></a></p><p> </p><p>一、eureka-server(一個 SpringBoot 項目)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8633 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"420\" height=\"262\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server.png 772w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server-300x187.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/eureka-server-768x480.png 768w\" sizes=\"(max-width: 420px) 100vw, 420px\"></a></p><p> </p><p> </p><p>二、cloud (一個多模塊項目,API + 業務層) <a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8632 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"418\" height=\"121\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2.png 574w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud2-300x87.png 300w\" sizes=\"(max-width: 418px) 100vw, 418px\"></a></p><p> </p><p> </p><p>(1)其中 cloud-api 是 api,裏面有 model 和 service接口,cloud-core 和 cloud-web 將依賴它</p><p>到時候須要首先將該模塊 install,即打包到本地倉庫中</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8634 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"463\" height=\"414\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/api.png 672w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/api-300x269.png 300w\" sizes=\"(max-width: 463px) 100vw, 463px\"></a></p><p> </p><p>(2)其中 cloud-core,裏面 dao 和 serviceImpl,做爲生產者的存在</p><p>啓動類在這裏面</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8635 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"439\" height=\"460\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/core.png 800w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/core-286x300.png 286w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/core-768x804.png 768w\" sizes=\"(max-width: 439px) 100vw, 439px\"></a></p><p> </p><p>三、cloud-web( 一個 SpringBoot 項目)</p><p>只有控制器層,須要依賴 cloud-api ,做爲消費者的存在(能夠是其餘人調用)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8636 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"439\" height=\"359\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web.png 746w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-web-300x245.png 300w\" sizes=\"(max-width: 439px) 100vw, 439px\"></a></p><p> </p><h2>3、如何啓動</h2><p>一、新建數據庫 summer,導入 user.sql</p><p>二、導入新項目,前後順序隨便(如eureka-server、cloud、cloud-web)</p><p>三、啓動 eureka-server 項目,端口爲 8761</p><p>四、對 cloud 項目中的 cloud-api 模塊進行install,maven命令是 mvn clean install</p><p>五、啓動 cloud-core 項目,端口爲 8090</p><p>六、(可選)其實這時候咱們能夠在地址欄訪問一下 localhost:8090/user 實際上是能夠訪問的,若是你不行,說明有問題</p><p>七、啓動 cloud-web 項目,端口爲 8080</p><p>八、在地址欄訪問 localhost:8080/user,若是能夠看到數據,說明成功</p><p> </p><h2>4、補充</h2><p>一、我這裏模擬了四臺註冊了業務層服務(cloud-producer) 和 一臺控制器層服務(cloud-consumer)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8637 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"644\" height=\"412\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-1024x655.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-300x192.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/server-768x491.png 768w\" sizes=\"(max-width: 644px) 100vw, 644px\"></a></p><p>ps:由於我是用本機測試,因此開了不一樣的端口表示不一樣的服務器</p><p> </p><p>二、訪問控制器層,而後 Feign 會幫咱們在註冊中心中找到對應的服務名和對應的方法</p><p>咱們訪問 localhost:8080/user/1 首先到的是控制器層,控制器層調用 userService,userService 是 Cloud-API 裏的,添加了 @FeignClient(name=\"cloud-producer\") 註解,而後找到在註冊中心中尋找 cloud-producer 的服務,從一臺(負載均衡)服務器中找到 userService 的實現類,即 userServiceImpl,也就是進入了 cloud-core,而後完成一系列 DAO 和 Service 操做,最後返回給 Controller。</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8638 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"625\" height=\"415\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-1024x680.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-300x199.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080-768x510.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/8080.png 1148w\" sizes=\"(max-width: 625px) 100vw, 625px\"></a></p><p>其中 Service 和 Service 的實現都須要加 RequestMapping,Service 實現須要加 @RestController,不然會出現 404</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8639 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"627\" height=\"228\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-1024x373.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-300x109.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api-768x280.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api.png 1538w\" sizes=\"(max-width: 627px) 100vw, 627px\"></a></p><p>因此,其實咱們能夠直接訪問 cloud-core 這一層,在地址欄訪問 localhost:8090/user/1</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8640 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"497\" height=\"383\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2.png 784w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2-300x231.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud-api2-768x592.png 768w\" sizes=\"(max-width: 497px) 100vw, 497px\"></a></p><p> </p><p>事實上,咱們訪問 控制器的時候,當須要某個 Service 的時候,Feign 幫咱們向 Service 又發了一個一樣的請求。咱們能夠直接訪問這個 Service 請求</p><p>可是,一般咱們會在生產環境中,不讓別人直接訪問到 Service,能夠經過一些機制實現,好比內網啦。</p><p> </p><h2>6、學習過程當中遇到的問題</h2><p>一、cloud-web 中注入 userService,一直注入失敗,沒法掃描到 userServiceImpl</p><p>解決方案:在 cloud-web 啓動類上添加</p><p>@EnableFeignClients(basePackages = \"com.liuyanzhao.cloud\")</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8641 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"566\" height=\"159\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-1024x288.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-300x84.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22-768x216.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/cloud22.png 1572w\" sizes=\"(max-width: 566px) 100vw, 566px\"></a></p><p> </p><p>二、出現 404 錯誤</p><p>cloud-core 裏的 userServiceImpl 也須要加 @RequestMapping,而且須要將 @Service 改爲 @RestController</p><p> </p><p>UserService(cloud-api)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8643 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"615\" height=\"363\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-1024x605.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-300x177.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23-768x454.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user23.png 1334w\" sizes=\"(max-width: 615px) 100vw, 615px\"></a></p><p> </p><p>UserServiceImpl(cloud-core)</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8642 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png\" alt=\"SpringCloud 中使用 Eureka 和 Feign 實現增刪改查\" width=\"623\" height=\"278\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-1024x457.png 1024w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-300x134.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/07/user22-768x343.png 768w\" sizes=\"(max-width: 623px) 100vw, 623px\"></a></p><p> </p>', '2', '0', '0', '1', '1', '1', '2019-04-25 21:43:11', '2018-11-25 20:58:22', '在沒有接觸微服務或者分佈式項目以前,咱們的項目時沒有分層的,咱們的服務也是沒有分層的。好比,咱們有5臺服務器使用 Nginx 作負載均衡,上面都是安裝了咱們的 Tomcat 服務器,部署的同樣的項目。當用戶訪問某個請求的時候,按照負載均衡的機制(隨機、輪詢之類)來轉發到對應的服務器上,而後在該服務器'); INSERT INTO `article` VALUES ('29', '1', 'IDEA啓動EDAS項目', '<h2>1、下載EDAS配置中心</h2><p>這個有點像咱們SpringCloud裏的Eurake註冊中心</p><p>下載地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/LCC/2018-11-01/edas-lite-configcenter.tar.gz?spm=a2c4g.11186623.2.14.1c1d4423eoGWQQ&file=edas-lite-configcenter.tar.gz\" target=\"_blank\" rel=\"noopener noreferrer\">點此</a></p><p>官網地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://help.aliyun.com/document_detail/44163.html?spm=a2c4g.11186623.6.675.71d822b8fWyaNi\" target=\"_blank\" rel=\"noopener noreferrer\">點此</a></p><p>啓動 edas配置中心:windows下點擊 edas-lite-configcenter/bin 中的 startup.bat</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/edas-startup.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8903 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/edas-startup.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/edas-startup.png\" alt=\"IDEA啓動EDAS項目\" width=\"333\" height=\"90\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/edas-startup.png 551w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/edas-startup-300x81.png 300w\" sizes=\"(max-width: 333px) 100vw, 333px\"></a></p><p>默認啓動在 8080 端口</p><p> </p><h2>2、安裝 Ali-Tomcat 和 Pandora</h2><p>一、下載 <a title=\"Ali-Tomcat\" href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/tomcat/taobao-tomcat-7.0.59.tgz\">Ali-Tomcat</a>,保存後解壓至相應的目錄(如:d:\\work\\tomcat\\)。</p><p> </p><p>二、下載 <a title=\"Pandora 容器\" href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/pandora/unauth/taobao-hsf.tgz\">Pandora 容器</a>,保存後將內容解壓至上述保存的 Ali-Tomcat 的 deploy 目錄(d:\\work\\tomcat\\deploy)下。</p><p>下載後是兩個文件夾</p><p><img class=\"size-full wp-image-8902 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/QQ截圖20181106100740.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/QQ%E6%88%AA%E5%9B%BE20181106100740.png\" alt=\"IDEA啓動EDAS項目\" width=\"229\" height=\"60\"></p><p> </p><p> </p><p>解壓後,將 taobao-haf 放到 taobao-tomcat-7.0.59/deploy 裏面</p><p> </p><p>好比咱們有三個服務,分別是A、B、C</p><p>咱們創建三個文件夾,分別是A、B 和 C,每一個文件夾裏都拷貝一份上面的 taobao-tomcat-7.0.59</p><p> </p><h2>3、IDEA 配置 Tomcat</h2><p>一、建立三個Tomcat</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8905 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server.png\" alt=\"IDEA啓動EDAS項目\" width=\"651\" height=\"473\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server.png 824w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server-300x218.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server-768x557.png 768w\" sizes=\"(max-width: 651px) 100vw, 651px\"></a></p><p>指定啓動的端口,VM options裏填寫對應的 Tomcat 的啓動參數</p><p>D:\\EDAS\\A\\taobao-tomcat-7.0.59\\deploy\\taobao-hsf.sar</p><p> </p><p>二、在Deployment裏選擇對應的項目</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8906 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2.png\" alt=\"IDEA啓動EDAS項目\" width=\"641\" height=\"481\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2.png 801w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2-300x225.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2-768x576.png 768w, https://media.liuyanzhao.com/wp-content/uploads/2018/11/tomcat-server2-280x210.png 280w\" sizes=\"(max-width: 641px) 100vw, 641px\"></a></p><p> </p><p>而後依次啓動幾個項目就好了</p><p> </p><p>官方文檔:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://help.aliyun.com/product/29500.html?spm=a2c4g.11186623.6.540.102bb8e7ETwPNH\" target=\"_blank\" rel=\"noopener noreferrer\">https://help.aliyun.com/product/29500.html?spm=a2c4g.11186623.6.540.102bb8e7ETwPNH</a></p><p> </p>', '2', '0', '0', '1', '1', '1', '2019-04-25 21:43:08', '2018-11-25 21:00:24', '1、下載EDAS配置中心這個有點像咱們SpringCloud裏的Eurake註冊中心下載地址:點此官網地址:點此啓動 edas配置中心:windows下點擊 edas-lite-configcenter/bin 中的 startup.bat默認啓動在 8080 端口 2、安裝 Ali-To'); INSERT INTO `article` VALUES ('30', '1', 'SpringBoot + mongodb 整合, 記錄網站操做日誌,經常使用查詢操做', '<div class=\"single-content\"><p>mongodb 是一種文檔型數據庫。跟 Redis 同樣是非關係型數據庫,Redis 屬於那種小而快的數據庫,經常用做緩存。</p><p>而若是咱們須要存一些相似於日誌的那種,能夠嘗試用 mongodb (固然也有人用 MySQL,就是有點慢)。咱們嘗試用 mongodb 來存儲博客的日誌信息。</p><p>本文主要介紹 <a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a> 和 mongodb 整合,和基本的查詢操做。</p><p> </p><h2>1、依賴和配置</h2><p>建立 springboot 項目,引入 web 和 lombok,而後再添加 mongodb 依賴</p><p><strong>一、pom.xml</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"comments\"><!--mongodb--></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">dependency</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">groupId</span><span class=\"tag\">></span>org.springframework.boot<span class=\"tag\"><!--</span--><span class=\"tag-name\">groupId</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span>spring-boot-starter-data-mongodb<span class=\"tag\"><!--</span--><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span></span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">dependency</span><span class=\"tag\">></span></span></li></ol></div><p>相似 Spring Data JPA</p><p> </p><p><strong>二、application.properties</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\">spring.data.mongodb.uri=mongodb:<span class=\"comment\">//localhost:27017/saysky</span></li></ol></div><p>saysky是數據庫名稱,確保你本地啓動了 mongodb</p><p> </p><h2>2、代碼實例</h2><p><strong>一、日誌實體</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mongodb.model;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> lombok.Data;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 日誌</span></li><li class=\"alt\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"\"><span class=\"comment\"> * @date 2018/9/3 20:00</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"annotation\">@Data</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Log {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> Long id;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> Long userId;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> Integer type;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> String url;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> String desc;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"\">}</li></ol></div><p> </p><p><strong>二、LogRepository</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mongodb.dao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mongodb.model.Log;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Page;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.domain.Pageable;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.mongodb.repository.MongoRepository;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.stereotype.Repository;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"alt\"><span class=\"comment\"> * @date 2018/9/3 14:17</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"annotation\">@Repository</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">interface</span> LogRepository <span class=\"keyword\">extends</span> <log, long> {</log, long></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 根據用戶ID查詢</span></li><li class=\"\"><span class=\"comment\"> * @param userId</span></li><li class=\"alt\"><span class=\"comment\"> * @return</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"> List<log> findByUserId(Long userId);</log></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 根據描述查詢</span></li><li class=\"alt\"><span class=\"comment\"> * @param desc</span></li><li class=\"\"><span class=\"comment\"> * @return</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"> List<log> findByDesc(String desc);</log></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 根據建立日期範圍查詢</span></li><li class=\"\"><span class=\"comment\"> * @param startTime</span></li><li class=\"alt\"><span class=\"comment\"> * @param endTime</span></li><li class=\"\"><span class=\"comment\"> * @return</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"> List<log> findByCreateTimeBetween(Date startTime, Date endTime);</log></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 根據描述查詢</span></li><li class=\"alt\"><span class=\"comment\"> * 分頁查詢</span></li><li class=\"\"><span class=\"comment\"> * @param desc</span></li><li class=\"alt\"><span class=\"comment\"> * @return</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"> Page<log> findByDesc(String desc, Pageable pageable);</log></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 根據建立日期範圍查詢</span></li><li class=\"alt\"><span class=\"comment\"> * 分頁查詢</span></li><li class=\"\"><span class=\"comment\"> * @param startTime</span></li><li class=\"alt\"><span class=\"comment\"> * @param endTime</span></li><li class=\"\"><span class=\"comment\"> * @return</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"> Page<log> findByCreateTimeBetween(Date startTime, Date endTime,Pageable pageable);</log></li><li class=\"alt\"></li><li class=\"\">}</li></ol></div><p> </p><p><strong>三、測試類</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mongodb.dao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mongodb.model.Log;</li><li class=\"\"><span class=\"keyword\">import</span> org.junit.Test;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.junit.runner.RunWith;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Autowired;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.boot.test.context.<a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a>Test;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.data.domain.Page;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.springframework.data.domain.PageRequest;</li><li class=\"\"><span class=\"keyword\">import</span> org.springframework.test.context.junit4.SpringRunner;</li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * @author 言曌</span></li><li class=\"alt\"><span class=\"comment\"> * @date 2018/9/3 14:21</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"annotation\">@<a href=\"https://liuyanzhao.com/tag/springboot/\" title=\"查看與 SpringBoot 相關的文章\" target=\"_blank\">SpringBoot</a>Test</span></li><li class=\"\"><span class=\"annotation\">@RunWith</span>(SpringRunner.<span class=\"keyword\">class</span>)</li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> LogRepositoryTest {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Autowired</span></li><li class=\"\"> <span class=\"keyword\">private</span> LogRepository logRepository;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"annotation\">@Test</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> save() {</li><li class=\"\"> Log log = <span class=\"keyword\">new</span> Log();</li><li class=\"alt\"> log.setId(7L);</li><li class=\"\"> log.setType(<span class=\"number\">1</span>);</li><li class=\"alt\"> log.setDesc(<span class=\"string\">\"更新用戶\"</span>);</li><li class=\"\"> log.setUserId(10002L);</li><li class=\"alt\"> log.setUrl(<span class=\"string\">\"/user/update\"</span>);</li><li class=\"\"> log.setCreateTime(<span class=\"keyword\">new</span> Date());</li><li class=\"alt\"> logRepository.save(log);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"annotation\">@Test</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> findById() {</li><li class=\"\"> Log Log = logRepository.findById(1L).get();</li><li class=\"alt\"> System.out.println(Log);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> findByDes() {</li><li class=\"alt\"> <span class=\"comment\">//不分頁</span></li><li class=\"\"><span class=\"comment\">// List<log> LogList = logRepository.findByDesc(\"添加用戶\");</log></span></li><li class=\"alt\"><span class=\"comment\">// System.out.println(LogList);</span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//分頁查詢</span></li><li class=\"\"> <span class=\"comment\">//查詢第1頁,每頁顯示2條</span></li><li class=\"alt\"> PageRequest pageRequest = <span class=\"keyword\">new</span> PageRequest(<span class=\"number\">0</span>,<span class=\"number\">2</span>);</li><li class=\"\"> Page<log> logPage = logRepository.findByDesc(<span class=\"string\">\"添加用戶\"</span>,pageRequest);</log></li><li class=\"alt\"> System.out.println(logPage);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> findByCreateTimeBetween() {</li><li class=\"alt\"> <span class=\"comment\">//根據時間區間查詢</span></li><li class=\"\"> <span class=\"comment\">//不分頁</span></li><li class=\"alt\"> Date createdAtStart = <span class=\"keyword\">new</span> Date(1535974057016L);</li><li class=\"\"> Date createdAtEnd = <span class=\"keyword\">new</span> Date(1535974145009L);</li><li class=\"alt\"><span class=\"comment\">// List<log> LogList = logRepository.findByCreateTimeBetween(createdAtStart,createdAtEnd);</log></span></li><li class=\"\"><span class=\"comment\">// System.out.println(LogList);</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//分頁查詢</span></li><li class=\"alt\"> <span class=\"comment\">//查詢第1頁,每頁顯示2條</span></li><li class=\"\"> PageRequest pageRequest = <span class=\"keyword\">new</span> PageRequest(<span class=\"number\">0</span>,<span class=\"number\">2</span>);</li><li class=\"alt\"> Page<log> logPage = logRepository.findByCreateTimeBetween(createdAtStart,createdAtEnd,pageRequest);</log></li><li class=\"\"> System.out.println(logPage);</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\">}</li></ol></div><p> </p><p>咱們經過mongodb可視化工具能夠看到數據</p><p><a href=\"https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb.png\" class=\"fancybox\" data-fancybox-group=\"button\"><img class=\"wp-image-8733 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb.png\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb.png\" alt=\"SpringBoot + mongodb 整合, 記錄網站操做日誌,經常使用查詢操做\" width=\"618\" height=\"320\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb.png 858w, https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb-300x155.png 300w, https://media.liuyanzhao.com/wp-content/uploads/2018/09/mongodb-768x397.png 768w\" sizes=\"(max-width: 618px) 100vw, 618px\"></a></p><p> </p><h2>3、更多查詢</h2><p>由於引入的 MongoRepository 是一種 JPA 框架,因此增刪改查都很容易。</p><p>能夠參考 Spring Data JPA 方法命名規範</p><p></p><p></p><p></p><p></p></div><div class=\"s-weixin\"><ul class=\"weimg1\" style=\"text-align: center;\"></ul></div>', '0', '0', '0', '1', '1', '1', '2019-04-25 21:43:06', '2018-11-25 21:01:24', 'mongodb 是一種文檔型數據庫。跟 Redis 同樣是非關係型數據庫,Redis 屬於那種小而快的數據庫,經常用做緩存。而若是咱們須要存一些相似於日誌的那種,能夠嘗試用 mongodb (固然也有人用 MySQL,就是有點慢)。咱們嘗試用 mongodb 來存儲博客的日誌信息。本文主要介紹&nb'); INSERT INTO `article` VALUES ('31', '1', 'RocketMQ 實戰之快速入門', '<div><p>最近 RocketMQ 剛剛上生產環境,閒暇之時在這裏作一些分享,主要目的是讓初學者能快速上手RocketMQ。</p>\r\n<h2>RocketMQ 是什麼</h2>\r\n<p>Github 上關於 RocketMQ 的介紹:<br>\r\nRcoketMQ 是一款低延遲、高可靠、可伸縮、易於使用的消息中間件。具備如下特性:</p>\r\n<ol>\r\n<li>支持發佈/訂閱(Pub/Sub)和點對點(P2P)消息模型</li>\r\n<li>在一個隊列中可靠的先進先出(FIFO)和嚴格的順序傳遞</li>\r\n<li>支持拉(pull)和推(push)兩種消息模式</li>\r\n<li>單一隊列百萬消息的堆積能力</li>\r\n<li>支持多種消息協議,如 JMS、MQTT 等</li>\r\n<li>分佈式高可用的部署架構,知足至少一次消息傳遞語義</li>\r\n<li>提供 docker 鏡像用於隔離測試和雲集羣部署</li>\r\n<li>提供配置、指標和監控等功能豐富的 Dashboard</li>\r\n</ol>\r\n<p>對於這些特性描述,你們簡單過一眼就便可,深刻學習以後天然就明白了。</p>\r\n<h2>專業術語</h2>\r\n<h3>Producer</h3>\r\n<p>消息生產者,生產者的做用就是將消息發送到 MQ,生產者自己既能夠產生消息,如讀取文本信息等。也能夠對外提供接口,由外部應用來調用接口,再由生產者將收到的消息發送到 MQ。</p>\r\n<h3>Producer Group</h3>\r\n<p>生產者組,簡單來講就是多個發送同一類消息的生產者稱之爲一個生產者組。在這裏能夠不用關心,只要知道有這麼一個概念便可。</p>\r\n<h3>Consumer</h3>\r\n<p>消息消費者,簡單來講,消費 MQ 上的消息的應用程序就是消費者,至於消息是否進行邏輯處理,仍是直接存儲到數據庫等取決於業務須要。</p>\r\n<h3>Consumer Group</h3>\r\n<p>消費者組,和生產者相似,消費同一類消息的多個 consumer 實例組成一個消費者組。</p>\r\n<h3>Topic</h3>\r\n<p>Topic 是一種消息的邏輯分類,好比說你有訂單類的消息,也有庫存類的消息,那麼就須要進行分類,一個是訂單 Topic 存放訂單相關的消息,一個是庫存 Topic 存儲庫存相關的消息。</p>\r\n<h3>Message</h3>\r\n<p>Message 是消息的載體。一個 Message 必須指定 topic,至關於寄信的地址。Message 還有一個可選的 tag 設置,以便消費端能夠基於 tag 進行過濾消息。也能夠添加額外的鍵值對,例如你須要一個業務 key 來查找 broker 上的消息,方便在開發過程當中診斷問題。</p>\r\n<h3>Tag</h3>\r\n<p>標籤能夠被認爲是對 Topic 進一步細化。通常在相同業務模塊中經過引入標籤來標記不一樣用途的消息。</p>\r\n<h3>Broker</h3>\r\n<p>Broker 是 RocketMQ 系統的主要角色,其實就是前面一直說的 MQ。Broker 接收來自生產者的消息,儲存以及爲消費者拉取消息的請求作好準備。</p>\r\n<h3>Name Server</h3>\r\n<p>Name Server 爲 producer 和 consumer 提供路由信息。</p>\r\n<h2>RocketMQ 架構</h2>\r\n<div class=\"image-package\">\r\n<div class=\"image-container\">\r\n<div class=\"image-container-fill\"></div>\r\n<div class=\"image-view\" data-width=\"975\" data-height=\"434\"><img data-original-src=\"//upload-images.jianshu.io/upload_images/6332814-7885601f065a3556.png\" data-original-width=\"975\" data-original-height=\"434\" data-original-format=\"image/png\" data-original-filesize=\"69606\" class=\"\" src=\"//upload-images.jianshu.io/upload_images/6332814-7885601f065a3556.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/975/format/webp\"></div>\r\n</div>\r\n<div class=\"image-caption\">RocketMQ 架構</div>\r\n</div>\r\n<p>由這張圖能夠看到有四個集羣,分別是 NameServer 集羣、Broker 集羣、Producer 集羣和 Consumer 集羣:</p>\r\n<ol>\r\n<li>NameServer: 提供輕量級的服務發現和路由。 每一個 NameServer 記錄完整的路由信息,提供等效的讀寫服務,並支持快速存儲擴展。</li>\r\n<li>Broker: 經過提供輕量級的 Topic 和 Queue 機制來處理消息存儲,同時支持推(push)和拉(pull)模式以及主從結構的容錯機制。</li>\r\n<li>Producer:生產者,產生消息的實例,擁有相同 Producer Group 的 Producer 組成一個集羣。</li>\r\n<li>Consumer:消費者,接收消息進行消費的實例,擁有相同 Consumer Group 的<br>\r\nConsumer 組成一個集羣。</li>\r\n</ol>\r\n<p>簡單說明一下圖中箭頭含義,從 Broker 開始,Broker Master1 和 Broker Slave1 是主從結構,它們之間會進行數據同步,即 Date Sync。同時每一個 Broker 與<br>\r\nNameServer 集羣中的全部節<br>\r\n點創建長鏈接,定時註冊 Topic 信息到全部 NameServer 中。</p>\r\n<p>Producer 與 NameServer 集羣中的其中一個節點(隨機選擇)創建長鏈接,按期從 NameServer 獲取 Topic 路由信息,並向提供 Topic 服務的 Broker Master 創建長鏈接,且定時向 Broker 發送心跳。Producer 只能將消息發送到 Broker master,可是 Consumer 則不同,它同時和提供 Topic 服務的 Master 和 Slave<br>\r\n創建長鏈接,既能夠從 Broker Master 訂閱消息,也能夠從 Broker Slave 訂閱消息。</p>\r\n<h2>RocketMQ 集羣部署模式</h2>\r\n<ol>\r\n<li>單 master 模式<br>\r\n也就是隻有一個 master 節點,稱不上是集羣,一旦這個 master 節點宕機,那麼整個服務就不可用,適合我的學習使用。</li>\r\n<li>多 master 模式<br>\r\n多個 master 節點組成集羣,單個 master 節點宕機或者重啓對應用沒有影響。<br>\r\n優勢:全部模式中性能最高<br>\r\n缺點:單個 master 節點宕機期間,未被消費的消息在節點恢復以前不可用,消息的實時性就受到影響。<br>\r\n<strong>注意</strong>:使用同步刷盤能夠保證消息不丟失,同時 Topic 相對應的 queue 應該分佈在集羣中各個節點,而不是隻在某各節點上,不然,該節點宕機會對訂閱該 topic 的應用形成影響。</li>\r\n<li>多 master 多 slave 異步複製模式<br>\r\n在多 master 模式的基礎上,每一個 master 節點都有至少一個對應的 slave。master<br>\r\n節點可讀可寫,可是 slave 只能讀不能寫,相似於 mysql 的主備模式。<br>\r\n優勢: 在 master 宕機時,消費者能夠從 slave 讀取消息,消息的實時性不會受影響,性能幾乎和多 master 同樣。<br>\r\n缺點:使用異步複製的同步方式有可能會有消息丟失的問題。</li>\r\n<li>多 master 多 slave 同步雙寫模式<br>\r\n同多 master 多 slave 異步複製模式相似,區別在於 master 和 slave 之間的數據同步方式。<br>\r\n優勢:同步雙寫的同步模式能保證數據不丟失。<br>\r\n缺點:發送單個消息 RT 會略長,性能相比異步複製低10%左右。<br>\r\n刷盤策略:同步刷盤和異步刷盤(指的是節點自身數據是同步仍是異步存儲)<br>\r\n同步方式:同步雙寫和異步複製(指的一組 master 和 slave 之間數據的同步)<br>\r\n<strong>注意</strong>:要保證數據可靠,需採用同步刷盤和同步雙寫的方式,但性能會較其餘方式低。</li>\r\n</ol>\r\n<h2>RocketMQ 單主部署</h2>\r\n<p>鑑因而快速入門,我選擇的是第一種單 master 的部署模式。先說明一下個人安裝環境:</p>\r\n<ol>\r\n<li>Centos 7.2</li>\r\n<li>jdk 1.8</li>\r\n<li>Maven 3.2.x</li>\r\n<li>Git</li>\r\n</ol>\r\n<p>這裏 git 可用可不用,主要是用來直接下載 github 上的源碼。也能夠選擇本身到<br>\r\ngithub 上下載,而後上傳到服務器上。以git操做爲示例。</p>\r\n<ol>\r\n<li>clone 源碼並用 maven 編譯</li>\r\n</ol>\r\n<pre class=\"hljs bash\"><code class=\"bash\">> git <span class=\"hljs-built_in\">clone</span> https://github.com/alibaba/RocketMQ.git /opt/RocketMQ\r\n> <span class=\"hljs-built_in\">cd</span> /opt/RocketMQ && mvn -Dmaven.test.skip=<span class=\"hljs-literal\">true</span> clean package install assembly:assembly -U\r\n> <span class=\"hljs-built_in\">cd</span> target/alibaba-rocketmq-broker/alibaba-rocketmq\r\n</code></pre>\r\n<p><strong>此處可能遇到的問題</strong><br>\r\n1、執行\"git clone <a href=\"https://link.jianshu.com?t=https%3A%2F%2Fgithub.com%2Falibaba%2FRocketMQ.git\" target=\"_blank\" rel=\"nofollow\">https://github.com/alibaba/RocketMQ.git</a> /home/inspkgs/RocketMQ\"時出現如下提示:</p>\r\n<pre class=\"hljs python\"><code class=\"python\">fatal: unable to access <span class=\"hljs-string\">\'https://github.com/alibaba/RocketMQ.git/\'</span>: Could <span class=\"hljs-keyword\">not</span> resolve host: github.com; Unknown error\r\n</code></pre>\r\n<p>解決辦法:通常是因爲網絡緣由形成的,執行如下命令</p>\r\n<pre class=\"hljs css\"><code class=\"css\">> <span class=\"hljs-selector-tag\">ping</span> <span class=\"hljs-selector-tag\">github</span><span class=\"hljs-selector-class\">.com</span>\r\n</code></pre>\r\n<p>肯定能夠 ping 通以後,再從新執行 git clone 命令。<br>\r\n2、執行\"mvn -Dmaven.test.skip=true clean package install assembly:assembly -U\"編譯時,可能出現下載相關jar很慢的狀況。<br>\r\n這也是因爲默認 maven 中央倉庫在國外的緣由,能夠根據須要在 /home/maven/conf/setting.xml 中的 <mirrors></mirrors> 添加如下內容後從新編譯:</p>\r\n<pre class=\"hljs xml\"><code class=\"xml\"><span class=\"hljs-tag\"><<span class=\"hljs-name\">mirror</span>></span>\r\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">id</span>></span>aliyun<span class=\"hljs-tag\"><!--<span class=\"hljs-name\"-->id</span>>\r\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">mirrorOf</span>></span>central<span class=\"hljs-tag\"><!--<span class=\"hljs-name\"-->mirrorOf</span>>\r\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">name</span>></span>aliyun maven<span class=\"hljs-tag\"><!--<span class=\"hljs-name\"-->name</span>>\r\n <span class=\"hljs-tag\"><<span class=\"hljs-name\">url</span>></span>http://maven.aliyun.com/nexus/content/groups/public/<span class=\"hljs-tag\"><!--<span class=\"hljs-name\"-->url</span>>\r\n<span class=\"hljs-tag\"><!--<span class=\"hljs-name\"-->mirror</span>>\r\n</code></pre>\r\n<ol start=\"2\">\r\n<li>啓動 Name Server</li>\r\n</ol>\r\n<pre class=\"hljs cpp\"><code class=\"cpp\">> nohup sh /opt/RocketMQ/bin/mqnamesrv &\r\n<span class=\"hljs-comment\">//執行 jps 查看進程</span>\r\n> jps\r\n<span class=\"hljs-number\">25913</span> NamesrvStartup\r\n<span class=\"hljs-comment\">//查看日誌確保服務已正常啓動</span>\r\n> tail -f ~/logs/rocketmqlogs/namesrv.<span class=\"hljs-built_in\">log</span>\r\nThe Name Server boot success...\r\n</code></pre>\r\n<ol start=\"3\">\r\n<li>啓動 broker</li>\r\n</ol>\r\n<pre class=\"hljs cpp\"><code class=\"cpp\">> nohup sh /opt/RocketMQ/bin/mqbroker -n localhost:<span class=\"hljs-number\">9876</span> &\r\n<span class=\"hljs-comment\">//執行 jps 查看進程</span>\r\n> jps\r\n<span class=\"hljs-number\">25954</span> BrokerStartup\r\n<span class=\"hljs-comment\">//查看日誌確保服務已正常啓動</span>\r\n> tail -f ~/logs/rocketmqlogs/broker.<span class=\"hljs-built_in\">log</span> \r\nThe broker[broker-a, <span class=\"hljs-number\">10.1</span><span class=\"hljs-number\">.54</span><span class=\"hljs-number\">.121</span>:<span class=\"hljs-number\">10911</span>] boot success...\r\n</code></pre>\r\n<ol start=\"4\">\r\n<li>發送和接收消息<br>\r\n發送/接收消息以前,咱們須要告訴客戶端 NameServer 地址。RocketMQ 提供了多種方式來實現這一目標。爲簡單起見,咱們使用環境變量 NAMESRV_ADDR。</li>\r\n</ol>\r\n<pre class=\"hljs bash\"><code class=\"bash\">> <span class=\"hljs-built_in\">export</span> NAMESRV_ADDR=localhost:9876\r\n> sh /opt/RocketMQ/bin/tools.sh com.alibaba.rocketmq.example.quickstart.Producer\r\nSendResult [sendStatus=SEND_OK, msgId= ...\r\n> sh /opt/RocketMQ/bin/tools.sh com.alibaba.rocketmq.example.quickstart.Consumer\r\nConsumeMessageThread_%d Receive New Messages: [MessageExt...\r\n</code></pre>\r\n<ol start=\"5\">\r\n<li>關閉服務</li>\r\n</ol>\r\n<pre class=\"hljs python\"><code class=\"python\">> sh /opt/RocketMQ/bin/mqshutdown broker\r\nThe mqbroker(<span class=\"hljs-number\">36695</span>) <span class=\"hljs-keyword\">is</span> running...\r\nSend shutdown request to mqbroker(<span class=\"hljs-number\">36695</span>) OK\r\n> sh /opt/RocketMQ/bin/mqshutdown namesrv\r\nThe mqnamesrv(<span class=\"hljs-number\">36664</span>) <span class=\"hljs-keyword\">is</span> running...\r\nSend shutdown request to mqnamesrv(<span class=\"hljs-number\">36664</span>) OK\r\n</code></pre>\r\n<h2>生產者、消費者 Demo</h2>\r\n<ol>\r\n<li>生產者</li>\r\n</ol>\r\n<pre class=\"hljs java\"><code class=\"java\"><span class=\"hljs-keyword\">public</span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">Producer</span> </span>{\r\n <span class=\"hljs-function\"><span class=\"hljs-keyword\">public</span> <span class=\"hljs-keyword\">static</span> <span class=\"hljs-keyword\">void</span> <span class=\"hljs-title\">main</span><span class=\"hljs-params\">(String[] args)</span> <span class=\"hljs-keyword\">throws</span> MQClientException, InterruptedException </span>{\r\n\r\n <span class=\"hljs-comment\">//聲明並初始化一個producer</span>\r\n <span class=\"hljs-comment\">//須要一個producer group名字做爲構造方法的參數,這裏爲producer1</span>\r\n DefaultMQProducer producer = <span class=\"hljs-keyword\">new</span> DefaultMQProducer(<span class=\"hljs-string\">\"producer1\"</span>);\r\n \r\n <span class=\"hljs-comment\">//設置NameServer地址,此處應改成實際NameServer地址,多個地址之間用;分隔</span>\r\n <span class=\"hljs-comment\">//NameServer的地址必須有,可是也能夠經過環境變量的方式設置,不必定非得寫死在代碼裏</span>\r\n producer.setNamesrvAddr(<span class=\"hljs-string\">\"10.1.54.121:9876;10.1.54.122:9876\"</span>);\r\n \r\n <span class=\"hljs-comment\">//調用start()方法啓動一個producer實例</span>\r\n producer.start();\r\n\r\n <span class=\"hljs-comment\">//發送10條消息到Topic爲TopicTest,tag爲TagA,消息內容爲「Hello RocketMQ」拼接上i的值</span>\r\n <span class=\"hljs-keyword\">for</span> (<span class=\"hljs-keyword\">int</span> i = <span class=\"hljs-number\">0</span>; i < <span class=\"hljs-number\">10</span>; i++) {\r\n <span class=\"hljs-keyword\">try</span> {\r\n Message msg = <span class=\"hljs-keyword\">new</span> Message(<span class=\"hljs-string\">\"TopicTest\"</span>,<span class=\"hljs-comment\">// topic</span>\r\n <span class=\"hljs-string\">\"TagA\"</span>,<span class=\"hljs-comment\">// tag</span>\r\n (<span class=\"hljs-string\">\"Hello RocketMQ \"</span> + i).getBytes(RemotingHelper.DEFAULT_CHARSET)<span class=\"hljs-comment\">// body</span>\r\n );\r\n \r\n <span class=\"hljs-comment\">//調用producer的send()方法發送消息</span>\r\n <span class=\"hljs-comment\">//這裏調用的是同步的方式,因此會有返回結果</span>\r\n SendResult sendResult = producer.send(msg);\r\n \r\n <span class=\"hljs-comment\">//打印返回結果,能夠看到消息發送的狀態以及一些相關信息</span>\r\n System.out.println(sendResult);\r\n } <span class=\"hljs-keyword\">catch</span> (Exception e) {\r\n e.printStackTrace();\r\n Thread.sleep(<span class=\"hljs-number\">1000</span>);\r\n }\r\n }\r\n\r\n <span class=\"hljs-comment\">//發送完消息以後,調用shutdown()方法關閉producer</span>\r\n producer.shutdown();\r\n }\r\n}\r\n</code></pre>\r\n<ol start=\"2\">\r\n<li>消費者</li>\r\n</ol>\r\n<pre class=\"hljs java\"><code class=\"java\"><span class=\"hljs-keyword\">public</span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">Consumer</span> </span>{\r\n\r\n <span class=\"hljs-function\"><span class=\"hljs-keyword\">public</span> <span class=\"hljs-keyword\">static</span> <span class=\"hljs-keyword\">void</span> <span class=\"hljs-title\">main</span><span class=\"hljs-params\">(String[] args)</span> <span class=\"hljs-keyword\">throws</span> InterruptedException, MQClientException </span>{\r\n \r\n <span class=\"hljs-comment\">//聲明並初始化一個consumer</span>\r\n <span class=\"hljs-comment\">//須要一個consumer group名字做爲構造方法的參數,這裏爲consumer1</span>\r\n DefaultMQPushConsumer consumer = <span class=\"hljs-keyword\">new</span> DefaultMQPushConsumer(<span class=\"hljs-string\">\"consumer1\"</span>);\r\n\r\n <span class=\"hljs-comment\">//一樣也要設置NameServer地址</span>\r\n consumer.setNamesrvAddr(<span class=\"hljs-string\">\"10.1.54.121:9876;10.1.54.122:9876\"</span>);\r\n\r\n <span class=\"hljs-comment\">//這裏設置的是一個consumer的消費策略</span>\r\n <span class=\"hljs-comment\">//CONSUME_FROM_LAST_OFFSET 默認策略,從該隊列最尾開始消費,即跳過歷史消息</span>\r\n <span class=\"hljs-comment\">//CONSUME_FROM_FIRST_OFFSET 從隊列最開始開始消費,即歷史消息(還儲存在broker的)所有消費一遍</span>\r\n <span class=\"hljs-comment\">//CONSUME_FROM_TIMESTAMP 從某個時間點開始消費,和setConsumeTimestamp()配合使用,默認是半個小時之前</span>\r\n consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);\r\n\r\n <span class=\"hljs-comment\">//設置consumer所訂閱的Topic和Tag,*表明所有的Tag</span>\r\n consumer.subscribe(<span class=\"hljs-string\">\"TopicTest\"</span>, <span class=\"hljs-string\">\"*\"</span>);\r\n\r\n <span class=\"hljs-comment\">//設置一個Listener,主要進行消息的邏輯處理</span>\r\n consumer.registerMessageListener(<span class=\"hljs-keyword\">new</span> MessageListenerConcurrently() {\r\n\r\n <span class=\"hljs-meta\">@Override</span>\r\n <span class=\"hljs-function\"><span class=\"hljs-keyword\">public</span> ConsumeConcurrentlyStatus <span class=\"hljs-title\">consumeMessage</span><span class=\"hljs-params\">(List<messageext> msgs,\r\n ConsumeConcurrentlyContext context)</messageext></span> </span>{\r\n\r\n System.out.println(Thread.currentThread().getName() + <span class=\"hljs-string\">\" Receive New Messages: \"</span> + msgs);\r\n \r\n <span class=\"hljs-comment\">//返回消費狀態</span>\r\n <span class=\"hljs-comment\">//CONSUME_SUCCESS 消費成功</span>\r\n <span class=\"hljs-comment\">//RECONSUME_LATER 消費失敗,須要稍後從新消費</span>\r\n <span class=\"hljs-keyword\">return</span> ConsumeConcurrentlyStatus.CONSUME_SUCCESS;\r\n }\r\n });\r\n\r\n <span class=\"hljs-comment\">//調用start()方法啓動consumer</span>\r\n consumer.start();\r\n\r\n System.out.println(<span class=\"hljs-string\">\"Consumer Started.\"</span>);\r\n }\r\n}\r\n</code></pre>\r\n<p></p></div><br><br>', '3', '0', '0', '1', '1', '1', '2019-04-25 21:43:02', '2018-11-25 21:02:40', '最近 RocketMQ 剛剛上生產環境,閒暇之時在這裏作一些分享,主要目的是讓初學者能快速上手RocketMQ。\r\nRocketMQ 是什麼\r\nGithub 上關於 RocketMQ 的介紹:\r\nRcoketMQ 是一款低延遲、高可靠、可伸縮、易於使用的消息中間件。具備如下特性:\r\n\r\n支持發佈/訂'); INSERT INTO `article` VALUES ('32', '1', 'Docker_入門?只要這篇就夠了!(純乾貨適合0基礎小白)', '<p>原文地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://blog.csdn.net/S_gy_Zetrov/article/details/78161154\" target=\"_blank\" rel=\"noopener noreferrer\">https://blog.csdn.net/S_gy_Zetrov/article/details/78161154</a></p><h2 id=\"寫在前面\">寫在前面</h2><ul><li>這篇博客適合誰?<ul><li>對於Docker並不瞭解,只是有一點模糊的感受,以爲Docker能夠當成虛擬機用之類的</li><li>只是下載了Docker軟件,對於怎麼配置,怎麼玩,第一步幹什麼,徹底一無所知</li><li>本文適用於mac,PC用戶不保證文章的效果,如今離開來得及</li></ul></li><li>網上Docker相關的教程都氾濫了,爲啥還要寫,爲啥我要看你的文章<ul><li>首先歡迎你,能搜索到個人博客就是緣分</li><li>其次,確實,如今Docker相關的文章真的太多了,那我爲何還要寫呢?緣由有三:<ul><li>其一,文章是不少,各類1小時入門什麼的,相信你已經在知乎看過不少了,我也看過,<br>由於我就是從知乎那幾篇教程爲起點,本身摳出來的,如今把本身的心得和經驗貼出來,我以爲既是對本身負責也能服務他人。</li><li>其二,我從對Docker只有及其模糊(真的是模糊,我除了知道Docker是跟虛擬系統有關其餘啥都不知道),到如今起碼一<br>問一不知(對應一問三不知)的狀態,大概花了8個小時。這期間全靠我從網絡上搜索到的資料。如今用個人話寫出來,我以爲對於跟我相同開始狀況的小白用戶,能省很多時間,因此我要寫。</li><li>其三,由於我本身是純靠搜索到的教程和技術文章學習的Docker,我天然是懂得乾澀的語言對學習的拖慢。因此我本身寫的時候,天然會考慮到這個問題。本文儘可能不用技術用語,儘可能使用通俗易懂的文字,爲進一步拉低Docker的入門門檻做出我本身的貢獻。</li></ul></li></ul></li><li>這篇文章主要是哪方面的Docker文章,純入門?你作了哪些工做?<ul><li>很高興你問了我這個問題。本文主要:<ul><li>首先對於Docker的概念做出個人解釋,儘可能通俗易懂</li><li>接着針對我用Docker的目的,從最開始的軟件下載,到最後push一個本身的鏡像到hub,整個過程以白話的形式描述出來,下降入門門檻,節省你的學習時間</li></ul></li><li>我作了哪些工做?這是個好問題!<ul><li>首先,我一直都很好奇Docker這個東西,但歷來沒有機會去使用它。可是,這學期OS課的lab,純Linux系統編程,雖然使用雙系統或者虛擬機都是純小學生的難易程度了,也不麻煩,但我想,爲何不用Docker呢?用雙系統或者虛擬機也太太小兒科!因此,我就這樣接觸了Docker</li><li>那麼我使用Docker實現了什麼?在lab中,咱們須要用到的是純終端下的gcc工具鏈還有vim等,那麼這就是我須要的所有軟件了!因而我在Docker中實現了「gcc+gdb<br>+vim」環境,並push到了hub中。</li></ul></li></ul></li><li>你這篇博客有沒有抄別人的?<ul><li>額,我學習Docker時確實看了不少不少(真的是不少)文章,如今寫這篇博客,除了本身的經驗心得,天然還得去看那些文章。但我能保證的是,我寫的都是取精華去糟粕,否則這篇文章就沒必要存在了你說是否是?</li><li>參考資料會在文後統一附上,謝謝!</li></ul></li></ul><p>好了,閒話說完,咱們開始吧!</p><p> </p><h2 id=\"入門docker你要下載什麼註冊什麼\">入門Docker,你要下載什麼?註冊什麼?</h2><p id=\"dockerapp你確定是要下載的\"><strong><span>+ Docker.app你確定是要下載的!</span></strong></p><p>Docker for mac,這個你確定要下載:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://www.docker.com/community-edition\" target=\"_blank\" rel=\"noopener noreferrer\">點我下載Docker for mac的社區免費版本</a></p><p> </p><p id=\"註冊docker官方帳號你須要它\"><strong><span>+ 註冊Docker官方帳號,你須要它!</span></strong></p><p>註冊一個Docker的官方帳號,有利而無害,相信我!<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://cloud.docker.com/swarm/sgyzetrov/dashboard/onboarding/cloud-registry\" target=\"_blank\" rel=\"noopener noreferrer\">點我註冊Docker Cloud官方帳號</a></p><p>Docker安裝好,帳號也註冊後,點擊桌面頂欄的Docker圖標,點擊sign in,登錄你的Docker帳號。</p><p> </p><h2 id=\"註冊daocloud帳號獲取加速服務\"><span>+ 註冊DaoCloud帳號,獲取加速服務!</span></h2><p>不能否認,有時直接從Docker官方往本地pull鏡像會十分緩慢。。。這時咱們能夠經過國內的Docker服務提供商免費獲取加速pull鏡像服務,阿里網易好像都有這種服務,我選擇的是DaoCloud:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://account.daocloud.io/signup\" target=\"_blank\" rel=\"noopener noreferrer\">點我註冊DaoCloud帳號</a></p><p>註冊後登錄DaoCloud,找到這個按鈕:</p><p><img title=\"\" data-original=\"https://img-blog.csdn.net/20171005113053850?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU19neV9aZXRyb3Y=/font/5a6L5L2T/fontsize/1400/fill/I0ZGMDAwMA==/dissolve/90/gravity/Center\" src=\"https://media.liuyanzhao.com/wp-content/themes/begin/img/blank.gif\" alt=\"docker1.png\"></p><p>接着,按照它的步驟,爲本身添加Docker加速服務</p><p><img title=\"\" data-original=\"https://img-blog.csdn.net/20171005113639144?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU19neV9aZXRyb3Y=/font/5a6L5L2T/fontsize/1400/fill/I0ZGMDAwMA==/dissolve/70/gravity/Center\" src=\"https://media.liuyanzhao.com/wp-content/themes/begin/img/blank.gif\" alt=\"docker2\"></p><h4></h4><p id=\"到此準備工做結束進入下一部分\"><strong><span>+ 到此準備工做結束,進入下一部分!</span></strong></p><p> </p><h2 id=\"要想入門docker首先你須要理解docker\">要想入門Docker,首先你須要理解Docker!</h2><p>我也不扯淡了,直接上我對Docker的理解:(Copyright © <a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://blog.csdn.net/s_gy_zetrov\" target=\"_blank\" rel=\"noopener noreferrer\">http://blog.csdn.net/s_gy_zetrov</a>. All Rights Reserved)</p><p>Docker,能夠說是一個終端命令行的虛擬機,但更準確的說法,其實應該是一個虛擬環境。好比,你想要在PC上無縫使用Linux麼?那麼虛擬機並非你惟一的出路,你還有Docker!我更願意稱Docker爲一個容器,固然這只是Docker的一個狹義解釋,Docker不止是一個容器。Docker包含3個重要概念:</p><ul><li>一個,是鏡像(Image),鏡像是靜態的、能夠被用戶互相分享的文件。咱們玩過雙系統和虛擬機的人都知道,首先你須要一個.iso鏡像,才能安裝系統。Docker中的鏡像也是這個東西,<strong><span>鏡像是靜態的,你不能對他操做,只能pull別人的鏡像或者push本身的鏡像</span></strong>。</li><li>還有一個,是容器(Container),前面說過,鏡像是靜態不可操做的,只能被分享和下載,那什麼是能被操做的呢?就是容器裏!容器能夠理解爲鏡像的動態狀態,也就是咱們虛擬機中系統裝好後的狀態,其實這麼說是不對的,容器最符合的描述應該是Linux的iso文件的<code>Live CD</code>模式,好比咱們玩雙系統時都進入過<code>Live CD</code>模式,不安裝系統而直接進入系統,很神奇是吧,Docker的容器就是這個概念,只不過更加輕量更加迅速便捷。可是<code>Live CD</code>的害處就是你關機後做出的修改安裝的軟件所有gg,<strong><span>容器也是同樣,一旦被直接推出,以前安裝的gcc啊vim啊啥的就會所有gg掉。若是要保存修改,就須要將當前容器封裝成一個新的鏡像,這樣下次啓動這個新的鏡像後以前做出的修改還都在</span></strong>。</li><li>最後,是倉庫(Repository)。各位在前面看到我寫的pull和push什麼的,有沒有暈?不知道各位對於git熟悉不熟悉,Docker中的倉庫很像git的代碼倉庫,你能夠pull本身以前push到本身倉庫的鏡像到本地,也能夠pull別人push到公共倉庫的鏡像到本身本地。說白了就是百度雲盤,你能夠上傳(push)本身作好環境的Docker上去,也能夠下載(pull)本身雲端的鏡像到本地。同時,咱們知道百度雲最大的特色就是分享(你懂的嘿嘿嘿),類比Docker,若是你獲得百度雲分享連接(別人的鏡像名字、標籤和別人的用戶名),你還能夠下載(pull)別人分享的鏡像到本身的本地,別人也能夠下載(pull)你的鏡像,由於Docker倉庫都是公共的。固然,每一個免費用戶有一個名額把本身的一個鏡像設爲私有,也就是禁止被分享給別人,類比百度雲上你本身保存的而沒有被生成分享連接的小姐姐。</li></ul><p>接下來來張高大上的概念圖,各位看個熱鬧2333</p><p><img title=\"\" data-original=\"https://img-blog.csdn.net/20171005120538429?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU19neV9aZXRyb3Y=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast\" src=\"https://media.liuyanzhao.com/wp-content/themes/begin/img/blank.gif\" alt=\"docker3.png\"></p><h3 id=\"接下來就是實戰了打開你的iterm2我是iterm2黨2333打開普通terminal也行這個不影響\">接下來就是實戰了!打開你的iTerm2!(我是iTerm2黨2333,打開普通terminal也行,這個不影響)</h3><p> </p><p id=\"查看docker版本信息\"><strong><span>+ 查看Docker版本信息</span></strong></p><pre class=\"prettyprint\"><code class=\"hljs livecodeserver has-numbering\">終端輸入:\r\n<strong><span>docker <span class=\"hljs-built_in\">version</span></span></strong></code></pre><p> </p><p>顯示的個人版本信息</p><pre class=\"prettyprint\"><code class=\"hljs r has-numbering\"> ~$ docker version\r\nClient:\r\n Version: <span class=\"hljs-number\">17.06</span><span class=\"hljs-number\">.2</span>-ce\r\n API version: <span class=\"hljs-number\">1.30</span>\r\n Go version: go1.8.3\r\n Git commit: cec0b72\r\n Built: Tue Sep <span class=\"hljs-number\">5</span> <span class=\"hljs-number\">20</span>:<span class=\"hljs-number\">12</span>:<span class=\"hljs-number\">06</span> <span class=\"hljs-number\">2017</span>\r\n OS/Arch: darwin/amd64\r\n <span class=\"hljs-keyword\">...</span>\r\n //omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)\r\n <span class=\"hljs-keyword\">...</span></code></pre><p>不過我通常不須要那麼多信息,因此一直用的是<code>docker -v</code>命令</p><h4></h4><p id=\"是時候pull你的第一個鏡像下來的\"><strong><span>+ 是時候pull你的第一個鏡像下來的!</span></strong></p><p>Docker安裝好後是不會自帶鏡像的,你須要從倉庫本身pull一個鏡像下來,本身製做本身的鏡像也是一個道理,你能夠經過在已有的鏡像基礎上生成本身的鏡像或者看一下這篇博客: <a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://blog.csdn.net/shiqiangdexin/article/details/52472195\" target=\"_blank\" rel=\"noopener noreferrer\">隨便百度的如何建立本身Docker鏡像獲得的教程</a></p><p>Docker鏡像官方好像只提供Linux,這個很容易想,windows和mac是要交錢的吧大概?(否)</p><p>搜索ubuntu的Docker鏡像<strong><span><code>docker search ubuntu</code></span></strong>,這個若是你想要什麼centos,直接改就行,不區分寫法,個人返回結果:</p><pre class=\"prettyprint\"><code class=\"hljs r has-numbering\">~$ docker search ubuntu\r\nNAME DESCRIPTION STARS OFFICIAL AUTOMATED\r\nubuntu Ubuntu is a Debian-based Linux operating s... <span class=\"hljs-number\">6636</span> [OK]\r\ndorowu/ubuntu-desktop-lxde-vnc Ubuntu with openssh-server and NoVNC <span class=\"hljs-number\">131</span> [OK]\r\nrastasheep/ubuntu-sshd Dockerized SSH service, built on top of of... <span class=\"hljs-number\">105</span> [OK]\r\nansible/ubuntu14.04-ansible Ubuntu <span class=\"hljs-number\">14.04</span> LTS with ansible <span class=\"hljs-number\">86</span> [OK]\r\nubuntu-upstart Upstart is an event-based replacement <span class=\"hljs-keyword\">for</span> <span class=\"hljs-keyword\">...</span> <span class=\"hljs-number\">80</span> [OK]\r\nneurodebian NeuroDebian provides neuroscience research... <span class=\"hljs-number\">40</span> [OK]\r\nubuntu-debootstrap debootstrap --variant=minbase --components... <span class=\"hljs-number\">31</span> [OK]\r\n<span class=\"hljs-keyword\">...</span>\r\n//omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)\r\n<span class=\"hljs-keyword\">...</span></code></pre><p> </p><p>拉取官方最新版的ubuntu鏡像:<strong><span><code>docker pull ubuntu:latest</code></span></strong>,其中的latest是一個標籤(tag),表示是當前最新版本。你應該獲得的信息,相似這樣的</p><pre class=\"prettyprint\"><code class=\"hljs r has-numbering\">~$ docker pull ubuntu:latest\r\nTrying to pull repository docker.io/<span class=\"hljs-keyword\">library</span>/ubuntu <span class=\"hljs-keyword\">...</span> \r\nlatest: Pulling from docker.io/<span class=\"hljs-keyword\">library</span>/ubuntu\r\naed158d74952: Pull complete \r\n773ae8273d14: Pull complete \r\nd1d487w88782: Pull complete \r\ncd3d6cd6c0cf: Pull complete \r\n8d73bu79120c: Pull complete \r\nDigest: sha256:35bc48a1ca97c3f74rhf378hj92hd82j29i4hf4hf84nf0dhnsid232de8d8\r\nStatus: Downloaded newer image <span class=\"hljs-keyword\">for</span> docker.io/ubuntu:latest</code></pre><p><strong><span>你輸入的命令實際上至關於<code>docker pull registry.hub.docker.com/ubuntu:latest</code>命令,即從註冊服務器<code>registry.hub.docker.com</code>中的名爲<code>ubuntu</code>的倉庫中下載標籤爲<code>latest</code>的鏡像</span></strong>。</p><p> </p><p>因爲個人lab統一要求,ubuntu須要14.04版本,因此我在hub裏面搜了搜,<strong><span>找到了一個用戶分享的14.04 64位純淨鏡像(base image)</span></strong>,下面將他的鏡像扒下來</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span>docker pull chug/ubuntu14.<span class=\"hljs-number\">04</span>x64</code></pre><p>這個用戶還有不少其餘版本的ubuntu系統,12 13 14的32位64位都有,全是純淨鏡像。</p><h4></h4><p id=\"查看你本地的鏡像倉庫\"><strong><span>+ 查看你本地的鏡像倉庫!</span></strong></p><p>把初始鏡像拉下來後,就能夠啓動它了,不過,能夠先使用<code>docker images</code>命令查看你本身的本地鏡像,我隨便找了個例子,你的也應該是相似這樣的:</p><pre class=\"prettyprint\"><code class=\"hljs lua has-numbering\">~$ <span><strong>docker images</strong></span>\r\nREPOSITORY TAG IMAGE ID CREATED SIZE\r\ndocker.<span class=\"hljs-built_in\">io</span>/ubuntu <span class=\"hljs-number\">16.04</span> e4415b714b62 <span class=\"hljs-number\">11</span> days ago <span class=\"hljs-number\">128.1</span> MB\r\ndocker.<span class=\"hljs-built_in\">io</span>/ubuntu latest e4415b714b62 <span class=\"hljs-number\">11</span> days ago <span class=\"hljs-number\">128.1</span> MB\r\ndocker.<span class=\"hljs-built_in\">io</span>/ubuntu <span class=\"hljs-number\">12.04</span> aefa163f7a7e <span class=\"hljs-number\">11</span> days ago <span class=\"hljs-number\">103.5</span> MB\r\ndocker.<span class=\"hljs-built_in\">io</span>/centos latest <span class=\"hljs-number\">0584</span>b3d2cf6d <span class=\"hljs-number\">3</span> weeks ago <span class=\"hljs-number\">196.5</span> MB</code></pre><p> </p><p>從網上一個教程中找到如下說法,比我說的好,那就看這個吧!</p><blockquote><p>在列出信息中,能夠看到幾個字段信息:</p><ul><li>來自於哪一個倉庫,好比 ubuntu</li><li>鏡像的標記,好比 16.04</li><li>它的 ID 號(惟一),好比e4415b714b62</li><li>建立時間</li><li>鏡像大小</li></ul><p>其中鏡像的 ID 惟一標識了鏡像,注意到 ubuntu:16.04 和 ubuntu:latest具備相同的鏡像 ID ,說明它們其實是同一鏡像。 TAG 信息用來標記來自同一個倉庫的不一樣鏡像。例如 ubuntu 倉庫中有多個鏡像,經過 TAG 信息來區分發行版本,例如10.04 、 12.04 、 12.10 、 13.04 、 14.04 等。例如能夠使用<code>docker run -t -i ubuntu:16.04 /bin/bash</code>命令指定使用鏡像<code>ubuntu:16.04</code>來啓動一個容器。若是不指定具體的標記,則默認使用<code>latest</code>標記信息。</p></blockquote><h4></h4><p id=\"啓動你的鏡像並盡情安裝軟件吧\"><strong><span>+ 啓動你的鏡像並盡情安裝軟件吧!</span></strong></p><p>如下內容均以我本身pull下來的chug的初始鏡像爲例:</p><p>如今你已經有一個初始的鏡像了,注意這個裏面是什麼都沒有的,連vim都沒裝,是精簡到不能再精簡的鏡像了。</p><p>首先啓動它:</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span>docker run -it chug/ubuntu14.<span class=\"hljs-number\">04</span>x64 /bin/bash\r\nroot<span class=\"hljs-variable\">@aa97ba3292ce</span><span class=\"hljs-symbol\">:/</span><span class=\"hljs-comment\">#</span></code></pre><p><strong><span>-it 表示運行在交互模式,是-i -t的縮寫,即-it是兩個參數:-i和-t。前者表示打開並保持stdout,後者表示分配一個終端(pseudo-tty)通常這個模式就是能夠啓動bash,而後和容器有命令行的交互</span></strong></p><p>能夠看到咱們終端的字頭變成<code>root@aa97ba3292ce:/#</code>了,這就意味着咱們的鏡像已經建立了一個容器實例。如今咱們能夠對這個「ubuntu系統」進行操做了</p><p> </p><p>好比安裝vim:</p><pre class=\"prettyprint\"><code class=\"hljs applescript has-numbering\">root@aa97ba3292ce:/<span class=\"hljs-comment\"># <strong><span>apt-get install vim</span></strong></span>\r\nReading package lists... Done\r\nBuilding dependency tree... Done\r\nThe following extra packages will be installed:\r\n <span class=\"hljs-type\">file</span> libexpat1 libffi6 libgpm2 libmagic1 libpython2<span class=\"hljs-number\">.7</span> libpython2<span class=\"hljs-number\">.7</span>-minimal libpython2<span class=\"hljs-number\">.7</span>-stdlib libsqlite3-<span class=\"hljs-number\">0</span> libssl1<span class=\"hljs-number\">.0</span><span class=\"hljs-number\">.0</span> mime-support vim-common vim-runtime\r\nSuggested packages:\r\n gpm ctags vim-doc vim-scripts\r\nThe following NEW packages will be installed:\r\n <span class=\"hljs-type\">file</span> libexpat1 libffi6 libgpm2 libmagic1 libpython2<span class=\"hljs-number\">.7</span> libpython2<span class=\"hljs-number\">.7</span>-minimal libpython2<span class=\"hljs-number\">.7</span>-stdlib libsqlite3-<span class=\"hljs-number\">0</span> libssl1<span class=\"hljs-number\">.0</span><span class=\"hljs-number\">.0</span> mime-support vim vim-common vim-runtime\r\n<span class=\"hljs-number\">0</span> upgraded, <span class=\"hljs-number\">14</span> newly installed, <span class=\"hljs-number\">0</span> <span class=\"hljs-keyword\">to</span> remove <span class=\"hljs-keyword\">and</span> <span class=\"hljs-number\">0</span> <span class=\"hljs-keyword\">not</span> upgraded.\r\nNeed <span class=\"hljs-keyword\">to</span> <span class=\"hljs-keyword\">get</span> <span class=\"hljs-number\">10.7</span> MB <span class=\"hljs-keyword\">of</span> archives.\r\nAfter this operation, <span class=\"hljs-number\">50.7</span> MB <span class=\"hljs-keyword\">of</span> additional disk <span class=\"hljs-constant\">space</span> will be used.\r\nDo you want <span class=\"hljs-keyword\">to</span> <span class=\"hljs-keyword\">continue</span>? [Y/n]</code></pre><p>看到我沒有用sudo,是由於原本就已是超級用戶(root)狀態了。</p><p>同理按照我本身的需求,我安裝了gcc和gdb</p><h4></h4><p id=\"想退出容器很簡單\"><span><strong>+ 想退出容器?很簡單!</strong></span></p><p>若是使用exit,命令退出,則容器的狀態處於Exit,而不是後臺運行。若是想讓容器一直運行,而不是中止,能夠使用快捷鍵 <strong><span>ctrl+p ctrl+q</span></strong> 退出,此時容器的狀態爲Up。</p><p>查看當前正在運行的容器:</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span><strong><span>docker ps</span></strong>\r\n<span class=\"hljs-constant\">CONTAINER</span> <span class=\"hljs-constant\">ID</span> <span class=\"hljs-constant\">IMAGE</span> <span class=\"hljs-constant\">COMMAND</span> <span class=\"hljs-constant\">CREATED</span> <span class=\"hljs-constant\">STATUS</span> <span class=\"hljs-constant\">PORTS</span> <span class=\"hljs-constant\">NAMES</span>\r\naa97ba3292ce chug/ubuntu14.<span class=\"hljs-number\">04</span>x64 <span class=\"hljs-string\">\"/bin/bash\"</span> <span class=\"hljs-number\">7</span> minutes ago <span class=\"hljs-constant\">Up</span> <span class=\"hljs-number\">7</span> minutes relaxed_hoover</code></pre><p> </p><p>看到當前有一個ID爲aa97ba3292ce的容器(Copyright © <a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://blog.csdn.net/s_gy_zetrov\" target=\"_blank\" rel=\"noopener noreferrer\">http://blog.csdn.net/s_gy_zetrov</a>. All Rights Reserved)</p><p>啓動、中止、重啓容器aa97ba3292ce的命令:</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span><strong><span>docker start aa97ba3292ce</span></strong>\r\n~<span class=\"hljs-variable\">$ </span><span><strong>docker stop aa97ba3292ce</strong></span>\r\n~<span class=\"hljs-variable\">$ </span><span><strong>docker restart aa97ba3292ce</strong></span></code></pre><p> </p><p><strong><span>後臺啓動一個容器後,若是想進入到這個容器,能夠使用attach命令</span></strong>:</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span><strong><span>docker attach aa97ba3292ce</span></strong></code></pre><h4></h4><h4></h4><p id=\"軟件裝完想保存環境commit幫你\"><span><strong>+ 軟件裝完,想保存環境?commit幫你!</strong></span></p><p>將容器轉化爲一個鏡像,即執行commit操做,完成後可以使用<strong><span><code>docker images</code></span></strong>查看</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">root<span class=\"hljs-variable\">@aa97ba3292ce</span><span class=\"hljs-symbol\">:/</span><span class=\"hljs-comment\">#exit //先退出容器</span>\r\n~<span class=\"hljs-variable\">$ </span><strong><span>docker commit -m <span class=\"hljs-string\">\"ubuntu with vim\"</span> -a <span class=\"hljs-string\">\"sgy\"</span> aa97ba3292ce sgy/<span class=\"hljs-symbol\">ubuntu:</span>vim</span></strong>\r\n~<span class=\"hljs-variable\">$ </span>docker images\r\n<span class=\"hljs-constant\">REPOSITORY</span> <span class=\"hljs-constant\">TAG</span> <span class=\"hljs-constant\">IMAGE</span> <span class=\"hljs-constant\">ID</span> <span class=\"hljs-constant\">CREATED</span> <span class=\"hljs-constant\">SIZE</span>\r\nsgy/ubuntu vim <span class=\"hljs-number\">52166</span>e4475ed <span class=\"hljs-number\">5</span> seconds ago <span class=\"hljs-number\">358.1</span> <span class=\"hljs-constant\">MB</span>\r\nchug/ubuntu14.<span class=\"hljs-number\">04</span>x64 latest <span class=\"hljs-number\">05</span>84b3d2cf6d <span class=\"hljs-number\">9</span> days ago <span class=\"hljs-number\">196.5</span> <span class=\"hljs-constant\">MB</span></code></pre><p> </p><p>其中,-m指定說明信息;-a指定用戶信息;aa97ba3292ce表明容器的id;sgy/ubuntu:vim指定目標鏡像的用戶名、倉庫名和 tag 信息。我這裏都是爲了博客瞎編的用戶名,我本身的用戶名也不是sgy,你運行命令的時候使用本身註冊Docker時的用戶名。</p><p>此時Docker中就有了咱們新建的鏡像sgy/ubuntu:vim,此鏡像和原有的ubuntu鏡像區別在於多了個vim工具。此時咱們利用新鏡像建立的容器,自己就自帶vim了。</p><p>啓動新建立的鏡像,能夠看到vim已經自帶了。</p><pre class=\"prettyprint\"><code class=\"hljs r has-numbering\">~$ <strong><span>docker run -it sgy/ubuntu:vim /bin/bash</span></strong>\r\nroot@520afc596c51:/<span class=\"hljs-comment\"># vim --version</span>\r\nVIM - Vi IMproved <span class=\"hljs-number\">7.4</span> (<span class=\"hljs-number\">2013</span> Aug <span class=\"hljs-number\">10</span>, compiled Apr <span class=\"hljs-number\">4</span> <span class=\"hljs-number\">2017</span> <span class=\"hljs-number\">18</span>:<span class=\"hljs-number\">14</span>:<span class=\"hljs-number\">54</span>)\r\n<span class=\"hljs-keyword\">...</span>\r\n//omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)\r\n<span class=\"hljs-keyword\">...</span></code></pre><p>利用exit退出容器。此時Docker引擎中就有了兩個容器,可以使用<code>docker ps -a</code>查看。</p><h4></h4><h4>+ 想要刪除容器或者鏡像?用這個!</h4><p>若是想刪除容器或者鏡像,能夠使用rm命令,注意:<span><strong>刪除鏡像前必須先刪除以此鏡像爲基礎的容器(哪怕是已經中止的容器),不然沒法刪除該鏡像,會報錯<code>Failed to remove image (e4415b714b62): Error response from daemon: conflict: unable to delete e4415b714b62 (cannot be forced) - image has dependent child images</code>相似這種</strong></span>。</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span><strong><span>docker rm container_id</span></strong>\r\n~<span class=\"hljs-variable\">$ </span><span><strong>docker rmi image_id</strong></span></code></pre><p> </p><p>有的時候儘管刪除了所有容器,鏡像仍是沒法刪除,這時點擊mac頂欄中的docker logo,選擇restart,而後再試一次rmi,應該就沒問題了。(Copyright © <a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://blog.csdn.net/s_gy_zetrov\" target=\"_blank\" rel=\"noopener noreferrer\">http://blog.csdn.net/s_gy_zetrov</a>. All Rights Reserved)</p><h4 id=\"附上一張高大上的docker命令圖\">+ 附上一張高大上的Docker命令圖</h4><p><img title=\"\" data-original=\"https://img-blog.csdn.net/20171005132826220\" src=\"https://media.liuyanzhao.com/wp-content/themes/begin/img/blank.gif\" alt=\"docker4.png\"></p><h4></h4><p id=\"一次配置處處使用那就push到hub上吧\"><span><strong>+ 一次配置,處處使用?那就push到hub上吧!</strong></span></p><p>由於以前已經在Docker.app中登錄了Docker帳號,因此如今直接</p><pre class=\"prettyprint\"><code class=\"hljs ruby has-numbering\">~<span class=\"hljs-variable\">$ </span><strong><span>docker push sgy/<span class=\"hljs-symbol\">ubuntu:</span>vim</span></strong></code></pre><p>就能夠了!</p><p>下次到了機房,在ubuntu系統中安裝Docker,配置好加速器,啓動Docker,<strong><span><code>docker login</code></span></strong>登錄本身的帳號,而後直接<code>~$ <span><strong>docker pull sgy/ubuntu:vim</strong></span></code>就能夠把你push到hub的已經配置好的環境的鏡像給扒下來。作完實驗,再push上去就ok了!</p><h2></h2><h2>Docker中安裝gcc、gdb時遇到的問題</h2><p id=\"add-apt-repository-command-not-found\"><span><strong>+ add-apt-repository: command not found</strong></span></p><p>14.04系統解決辦法:</p><pre class=\"prettyprint\"><code class=\"hljs lasso has-numbering\">apt<span class=\"hljs-attribute\">-get</span> install software<span class=\"hljs-attribute\">-properties</span><span class=\"hljs-attribute\">-common</span></code></pre><p> </p><p>older版本的系統:</p><pre class=\"prettyprint\"><code class=\"hljs lasso has-numbering\">apt<span class=\"hljs-attribute\">-get</span> install python<span class=\"hljs-attribute\">-software</span><span class=\"hljs-attribute\">-properties</span></code></pre><h4></h4><p id=\"docker中使用gdb沒法進入斷點沒法調試\"><strong><span>+ Docker中使用gdb沒法進入斷點,沒法調試</span></strong></p><p>加上<code>--privileged</code>參數</p><pre class=\"prettyprint\"><code class=\"hljs applescript has-numbering\">~$ docker <span class=\"hljs-command\">run</span> -<span class=\"hljs-keyword\">it</span> <span class=\"hljs-comment\">--privileged sgy/ubuntu:vim /bin/bash</span></code></pre>', '7', '0', '0', '1', '1', '1', '2019-04-25 21:42:58', '2018-11-25 21:05:05', '原文地址:https://blog.csdn.net/S_gy_Zetrov/article/details/78161154寫在前面這篇博客適合誰?對於Docker並不瞭解,只是有一點模糊的感受,以爲Docker能夠當成虛擬機用之類的只是下載了Docker軟件,對於怎麼配置,怎麼玩,第一步幹什麼,'); INSERT INTO `article` VALUES ('33', '1', 'MySQL經常使用命令語句', '<p><strong>經常使用的語句</strong></p><p>查詢 select * from bbs where id=1;</p><p>增長 insert into bbs (name,data_year) values (\"jack\",\"1993-10-01\");</p><p>修改 update bbs set name=\"tom\",sex=1,age=18 where name=\"jack\";</p><p>刪除 delete form bbs where id=2;</p><p>字符串替換: UPDATE `category` SET guid = REPLACE ( guid, \'articles\', \'article\' );</p><p> </p><p><strong>更多</strong></p><p>1.進入數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"wp_keywordlink_affiliate\">mysql</span> -u root -p</li><li><span class=\"wp_keywordlink_affiliate\">mysql</span> -h localhost -u root -p database_name</li></ol></div><p>2.列出數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"wp_keywordlink_affiliate\">show</span> databases;</li></ol></div><p>3.選擇數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">use databases_name;</li></ol></div><p>4.列出數據表:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"wp_keywordlink_affiliate\">show</span> tables;</li></ol></div><p>5.顯示錶格列的屬性:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"wp_keywordlink_affiliate\">show</span> columns <span class=\"keyword\">from</span> table_name;</li><li>describe table_name;</li></ol></div><p>6.導出整個數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"wp_keywordlink_affiliate\">mysql</span>dump -u user_name -p database_name > /tmp/file_name</li></ol></div><p>例如:my<span class=\"wp_keywordlink_affiliate\">sql</span>dump -u root -p test_db > d:/test_db.<span class=\"wp_keywordlink_affiliate\">sql</span></p><p>7.導出一個表:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">my<span class=\"wp_keywordlink_affiliate\">sql</span>dump -u user_name -p database_name table_name > /tmp/file_name</li></ol></div><p>例如:mysqldump -u root -p test_db table1 > d:/table1.sql</p><p>8.導出一個數據庫結構:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">mysqldump -u user_name -p -d <span class=\"comment\">--add--table database_name > file_name</span></li></ol></div><p>例如:mysqldump -u root -p -d --add-<span class=\"wp_keywordlink_affiliate\">drop</span>-table test_db > test_db.sql</p><p>9.導入數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">source file_name;</li><li>或</li><li class=\"alt\">mysql -u user_name -p database_name < file_name</li></ol></div><p>例如:</p><p>source /tmp/bbs.sql;</p><p>source d:/bbs.sql;</p><p>mysql -u root -p bbs < \"d:/bbs.sql\"</p><p>mysql -u root -p bbs < \"/tmp/bbs.sql\"</p><p>10.將文本文件導入數據表中(excel與之相同)</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">load</span> data infile <span class=\"string\">\"tables.txt\"</span> <span class=\"keyword\">into</span> <span class=\"keyword\">table</span> table_name;</li></ol></div><p>例如:</p><p>load data infile \"/tmp/bbs.txt\" into table bbs;</p><p>load data infile \"/tmp/bbs.xls\" into table bbs;</p><p>load data infile \"d:/bbs.txt\" into table bbs;</p><p>load data infile \"d:/bbs.xls\" into table bbs;</p><p>11.將數據表導出爲文本文件(excel與之相同)</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\"><span class=\"wp_keywordlink_affiliate\">select</span></span> * <span class=\"keyword\">into</span> outfile <span class=\"string\">\"path_file_name\"</span> <span class=\"keyword\">from</span> table_name;</li></ol></div><p>例如:</p><p><span class=\"wp_keywordlink_affiliate\">select</span> * into outfile \"/tmp/bbs.txt\" from bbs;</p><p>select * into outfile \"/tmp/bbs.xls\" from bbs where id=1;</p><p>select * into outfile \"d:/bbs.txt\" from bbs;</p><p>select * into outfile \"d:/bbs.xls\" from bbs where id=1;</p><p>12.建立數據庫時先判斷數據庫是否存在:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">database</span> if <span class=\"op\">not</span> exists database_name;</li></ol></div><p>例如:create database if not exists bbs</p><p>13.建立數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">database</span> database_name;</li></ol></div><p>例如:create database bbs;</p><p>14.刪除數據庫:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">drop</span> <span class=\"keyword\">database</span> database_name;</li></ol></div><p>例如:drop database bbs;</p><p>15.建立數據表:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">mysql> <span class=\"keyword\">create</span> <span class=\"keyword\">table</span> <table_name> ( <<span class=\"keyword\">column</span> 1 <span class=\"keyword\">name</span>> <col. 1 type> <col. 1 details>,<<span class=\"keyword\">column</span> 2 <span class=\"keyword\">name</span>> <col. 2 type> <col. 2 details>, ...);</col. 2 details></col. 2 type></col. 1 details></col. 1 type></table_name></li></ol></div><p>例如:create table (id int not null auto_increment primary key,name char(16) not null default \"jack\",date_year date not null);</p><p><span>16.刪除數據表中數據:</span></p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">delete</span> <span class=\"keyword\">from</span> table_name;</li></ol></div><p>例如:</p><p>delete from bbs;</p><p>delete from bbs where id=2;</p><p>17.刪除數據庫中的數據表:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">drop</span> <span class=\"keyword\">table</span> table_name;</li></ol></div><p>例如:</p><p>drop table test_db;</p><p>rm -f database_name/table_name.* (linux下)</p><p>例如:</p><p>rm -rf bbs/accp.*</p><p><span>18.向數據庫中添加數據:</span></p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\"><span class=\"wp_keywordlink_affiliate\">insert</span></span> <span class=\"keyword\">into</span> table_name <span class=\"keyword\">set</span> column_name1=value1,column_name2=value2;</li></ol></div><p>例如:<span class=\"wp_keywordlink_affiliate\">insert</span> into bbs set name=\"jack\",date_year=\"1993-10-01\";</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\"><span class=\"wp_keywordlink_affiliate\">insert</span></span> <span class=\"keyword\">into</span> table_name <span class=\"keyword\">values</span> (column1,column2,...);</li></ol></div><p>例如:insert into bbs (\"2\",\"jack\",\"1993-10-02\")</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">insert</span> <span class=\"keyword\">into</span> table_name (column_name1,column_name2,...) <span class=\"keyword\">values</span> (value1,value2);</li></ol></div><p>例如:insert into bbs (name,data_year) values (\"jack\",\"1993-10-01\");</p><p><span>19.查詢數據表中的數據:</span></p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> * <span class=\"keyword\">from</span> table_name;</li></ol></div><p>例如:select * from bbs where id=1;</p><p><span>20.修改數據表中的數據:</span></p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">update</span> table_name <span class=\"keyword\">set</span> col_name=new_value <span class=\"keyword\">where</span> id=1;</li></ol></div><p>例如:update bbs set name=\"tom\",age=18 where name=\"jack\";</p><p>21.增長一個字段:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name <span class=\"keyword\">add</span> <span class=\"keyword\">column</span> field_name datatype <span class=\"op\">not</span> <span class=\"op\">null</span> <span class=\"keyword\">default</span> <span class=\"string\">\"1\"</span>;</li></ol></div><p>例如:alter table bbs add column tel char(16) not null;</p><p>22.增長多個字段:(column可省略不寫)</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name <span class=\"keyword\">add</span> <span class=\"keyword\">column</span> filed_name1 datatype,<span class=\"keyword\">add</span> <span class=\"keyword\">column</span> filed_name2 datatype;</li></ol></div><p>例如:alter table bbs add column tel char(16) not null,add column address text;</p><p>23.刪除一個字段:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name <span class=\"keyword\">drop</span> field_name;</li></ol></div><p>例如:alter table bbs drop tel;</p><p>24.修改字段的數據類型:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name <span class=\"keyword\">modify</span> id <span class=\"keyword\">int</span> unsigned;//修改列id的類型爲<span class=\"keyword\">int</span> unsigned</li><li><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name change id sid <span class=\"keyword\">int</span> unsigned;//修改列id的名字爲sid,並且把屬性修改成<span class=\"keyword\">int</span> unsigned</li></ol></div><p>25.修改一個字段的默認值:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name <span class=\"keyword\">modify</span> column_name datatype <span class=\"op\">not</span> <span class=\"op\">null</span> <span class=\"keyword\">default</span> <span class=\"string\">\"\"</span>;</li></ol></div><p>例如:alter table test_db modify name char(16) default not null \"yourname\";</p><p>26.對錶從新命名:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table_name rename <span class=\"keyword\">as</span> new_table_name;</li></ol></div><p>例如:alter table bbs rename as bbs_table;</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">rename <span class=\"keyword\">table</span> old_table_name <span class=\"keyword\">to</span> new_table_name;</li></ol></div><p>例如:rename table test_db to accp;</p><p>27.從已經有的表中複製表的結構:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">table</span> table2 <span class=\"keyword\">select</span> * <span class=\"keyword\">from</span> table1 <span class=\"keyword\">where</span> 1<>1;</li></ol></div><p>例如:create table test_db select * from accp where 1<>1;</p><p>28.查詢時間:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> now();</li></ol></div><p>29.查詢當前用戶:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> <span class=\"func\">user</span>();</li></ol></div><p>30.查詢數據庫版本:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> version();</li></ol></div><p>31.建立索引:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table1 <span class=\"keyword\">add</span> <span class=\"keyword\">index</span> ind_id(id);</li><li><span class=\"keyword\">create</span> <span class=\"keyword\">index</span> ind_id <span class=\"keyword\">on</span> table1(id);</li><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">unique</span> <span class=\"keyword\">index</span> ind_id <span class=\"keyword\">on</span> table1(id);//創建惟一性索引</li></ol></div><p>32.刪除索引:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">drop</span> <span class=\"keyword\">index</span> idx_id <span class=\"keyword\">on</span> table1;</li><li><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> table1 <span class=\"keyword\">drop</span> <span class=\"keyword\">index</span> ind_id;</li></ol></div><p>33.聯合字符或者多個列(將id與\":\"和列name和\"=\"鏈接)</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> concat(id,\':\',<span class=\"keyword\">name</span>,\'=\') <span class=\"keyword\">from</span> <span class=\"keyword\">table</span>;</li></ol></div><p>34.limit(選出10到20條)</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">select</span> * <span class=\"keyword\">from</span> bbs <span class=\"keyword\">order</span> <span class=\"keyword\">by</span> id limit 9,10;</li></ol></div><p>(從查詢結果中列出第幾到幾條的記錄)</p><p>35.增長一個管理員帳號:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\"><span class=\"wp_keywordlink_affiliate\">grant</span></span> <span class=\"op\">all</span> <span class=\"keyword\">on</span> *.* <span class=\"keyword\">to</span> <span class=\"func\">user</span>@localhost identified <span class=\"keyword\">by</span> <span class=\"string\">\"password\"</span>;</li></ol></div><p>36.建立表是先判斷表是否存在</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">table</span> if <span class=\"op\">not</span> exists students(……);</li></ol></div><p>37.複製表:</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\">create</span> <span class=\"keyword\">table</span> table2 <span class=\"keyword\">select</span> * <span class=\"keyword\">from</span> table1;</li></ol></div><p>例如:create table test_db select * from accp;</p><p>38.授於用戶遠程訪問mysql的權限</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\"><span class=\"keyword\"><span class=\"wp_keywordlink_affiliate\">grant</span></span> <span class=\"op\">all</span> <span class=\"keyword\">privileges</span> <span class=\"keyword\">on</span> *.* <span class=\"keyword\">to</span> <span class=\"string\">\"root\"</span>@<span class=\"string\">\"%\"</span> identified <span class=\"keyword\">by</span> <span class=\"string\">\"password\"</span> <span class=\"keyword\">with</span> <span class=\"keyword\">grant</span> <span class=\"keyword\">option</span>;</li></ol></div><p>或者是修改mysql數據庫中的user表中的host字段</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">use mysql;</li><li><span class=\"keyword\">select</span> <span class=\"func\">user</span>,host <span class=\"keyword\">from</span> <span class=\"func\">user</span>;</li><li class=\"alt\"><span class=\"keyword\">update</span> <span class=\"func\">user</span> <span class=\"keyword\">set</span> host=<span class=\"string\">\"%\"</span> <span class=\"keyword\">where</span> <span class=\"func\">user</span>=<span class=\"string\">\"user_name\"</span>;</li></ol></div><p>39.查看當前狀態</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">show status;</li></ol></div><p>40.查看當前鏈接的用戶</p><div class=\"dp-highlighter\"><ol class=\"dp-sql\"><li class=\"alt\">show processlist;</li></ol></div><p>(若是是root用戶,則查看所有的線程,獲得的用戶鏈接數同show status;裏的 Threads_connected值是相同的)</p><p>參考:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.92csz.com/56/992.html\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.92csz.com/56/992.html</a></p><p>本文地址:<a href=\"https://liuyanzhao.com/5306.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://liuyanzhao.com/5306.html</a></p>', '12', '0', '0', '1', '1', '1', '2019-04-25 21:42:41', '2018-11-25 21:06:52', '經常使用的語句查詢 select * from bbs where id=1;增長 insert into bbs (name,data_year) values (\"jack\",\"1993-10-01\");修改 update bbs set name=\"tom\",sex=1,age=18 where '); INSERT INTO `article` VALUES ('34', '1', '測試數據', '1', '1', '1', '1', '1', '1', '1', '2019-04-25 22:32:23', '2019-04-25 22:32:23', '測試數據');
category表:表中存放分類的基礎信息html
-- ---------------------------- -- Table structure for category -- ---------------------------- DROP TABLE IF EXISTS `category`; CREATE TABLE `category` ( `category_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `category_pid` int(11) DEFAULT NULL, `category_name` varchar(50) DEFAULT NULL, `category_description` varchar(255) DEFAULT NULL, `category_order` int(11) unsigned DEFAULT '1', `category_icon` varchar(20) DEFAULT NULL, PRIMARY KEY (`category_id`), UNIQUE KEY `category_name` (`category_name`) ) ENGINE=InnoDB AUTO_INCREMENT=100000007 DEFAULT CHARSET=utf8;
表中的數據以下:java
-- ---------------------------- -- Records of category -- ---------------------------- INSERT INTO `category` VALUES ('1', '0', 'Java', 'Java語言', '1', 'fa fa-coffee'); INSERT INTO `category` VALUES ('2', '1', 'Java基礎', '', '1', ''); INSERT INTO `category` VALUES ('3', '1', 'Core Java', '', '1', ''); INSERT INTO `category` VALUES ('4', '1', '多線程併發編程', '', '1', ''); INSERT INTO `category` VALUES ('5', '1', 'Sockets和IO', '', '1', ''); INSERT INTO `category` VALUES ('6', '1', '設計模式和反射', '', '1', ''); INSERT INTO `category` VALUES ('7', '1', 'JVM', '', '1', ''); INSERT INTO `category` VALUES ('8', '1', 'JavaWeb', '', '1', ''); INSERT INTO `category` VALUES ('9', '1', 'Java框架', '', '1', ''); INSERT INTO `category` VALUES ('10', '0', '計算機科學', '', '1', 'fa fa-cubes'); INSERT INTO `category` VALUES ('11', '10', '數據結構和算法', '', '1', ''); INSERT INTO `category` VALUES ('12', '10', '操做系統', '', '1', ''); INSERT INTO `category` VALUES ('13', '10', '數據庫', '', '1', ''); INSERT INTO `category` VALUES ('14', '10', '計算機網絡', '', '1', ''); INSERT INTO `category` VALUES ('15', '0', '其餘技術', '', '1', 'fa-snowflake-o fa'); INSERT INTO `category` VALUES ('16', '15', '消息服務', '', '1', ''); INSERT INTO `category` VALUES ('17', '15', '緩存服務', '', '1', ''); INSERT INTO `category` VALUES ('19', '100000000', 'Hello', '1111', '1', '11'); INSERT INTO `category` VALUES ('100000003', '15', '微服務', '', null, ''); INSERT INTO `category` VALUES ('100000004', '15', '搜索引擎', '', null, ''); INSERT INTO `category` VALUES ('100000005', '15', '權限框架', '', null, ''); INSERT INTO `category` VALUES ('100000006', '15', '開發利器', '', null, '');
Article類:article表對應的實體對象node
package wbl_ssm_blog.entity; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; /** * @author liuyanzhao */ @Data public class Article implements Serializable{ private static final long serialVersionUID = 5207865247400761539L; private Integer articleId; public Integer articleUserId; private String articleTitle; private Integer articleViewCount; private Integer articleCommentCount; private Integer articleLikeCount; private Date articleCreateTime; private Date articleUpdateTime; private Integer articleIsComment; private Integer articleStatus; private Integer articleOrder; private String articleContent; private String articleSummary; private User user; private List<Tag> tagList; private List<Category> categoryList; }
1、開啓駝峯命名適配:python
咱們發現,數據庫字段的名稱使用駝峯命名規則,即user_name這種命名,而mybatis對應的java實體類使用userName這種命名方式,沒法完成映射。因此,須要在mybatis-config配置文件中開啓駝峯命名自動匹配。mysql
<settings> <!--容許 JDBC 支持自動生成主鍵--> <setting name="useGeneratedKeys" value="false"/> <!--是否開啓自動駝峯命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的相似映射。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
這樣配置以後就能把數據庫中的user_name和實體類中的userName映射上了。linux
二.查詢參數的傳遞git
1.單個簡單類型的查詢參數,能夠在ArticleMapper.xml中使用value來獲取ArticleMapper.java中傳遞的參數。也能夠使用@Param這種方法。
/** * 我本身編寫的一個類 用來測試mybatis語句的寫法 * * @return */ List<Article> findArticleBySome(int articleViewCount);
<!-- 測試 @Param語法 這種狀況下不須要設置parameterType這個參數--> <!-- 數據庫字段使用駝峯命名article_user_id 實體的使用userName命名 mybatis-config.xml中配置了駝峯匹配原則 --> <select id="findArticleBySome" resultType="Article"> select * from <include refid="tb"/> where article_view_count > #{value} </select>
2.@Param的使用
在不少時候,咱們須要傳入多個查詢參數,那mybatis怎麼獲取多個查詢參數呢?在Article.mapper文件中,咱們使用@Param(別名)爲參數設置別名,在ArticleMapper.xml使用#{別名}來獲取參數。
/** * 我本身編寫的一個類 用來測試mybatis語句的寫法 * @param articleTitle 當查詢須要多個參數的時候 就使用@Param語法 或者傳入一個對象進去1 * @return */ List<Article> findArticleBySome(@Param("articleTitle") String articleTitle,@Param("articleViewCount") Integer articleViewCount);
!-- 測試 @Param語法 這種狀況下不須要設置parameterType這個參數--> <!-- 數據庫字段使用駝峯命名article_user_id 實體的使用userName命名 mybatis-config.xml中配置了駝峯匹配原則 --> <select id="findArticleBySome" resultType="Article"> select * from <include refid="tb"/> where article_title like '%${articleTitle}%' and article_view_count > #{articleViewCount} </select>
3.使用對象的方式傳遞參數。在ArticleMapper.java的查詢方法中,傳入一個對象,在ArticleMapper.xml中,使用對象的屬性來獲取參數。
/** * 須要傳入多個參數時 新建一個查詢對象 把查詢參數賦值給這個查詢對象 而後在sql語句中直接獲取查詢參數的值 * @param article * @return */ List<Article> findArticleBySome01(Article article);
<!--測試使用對象的形式爲查詢語句賦值--> <select id="findArticleBySome01" parameterType="Article" resultType="Article"> select <include refid="Base_Column_List"/> from <include refid="tb"/> where article_title like '%${articleTitle}%' and article_view_count > #{articleViewCount} </select>
4.查詢時傳入HashMap類型的參數。在查詢時,咱們會把查詢條件拼成一個HashMap傳到mybatis中。在mybatis中能夠直接使用HashMap的key能夠來獲取對應value的值。
/** * 根據查詢條件查找文章列表 * @param criteria * @return */ List<Article> findAll(HashMap<String,Object> criteria);
@Test public void findAll() { HashMap<String,Object> cateria = new HashMap<String,Object>(); cateria.put("status",1); cateria.put("userId",1); // cateria.put("keywords","操做"); // cateria.put("categoryId",1); cateria.put("tagId",1); List<Article> articleList = articleMapper.findAll(cateria); System.out.println(); // order by `article`.`article_order` DESC ,`article`.`article_id` DESC }
<!--這裏根據查詢條件對文章進行查詢--> <select id="findAll" resultType="Article"> select article.* from <include refid="tb"/> <where> <!--取HashMap裏面的東西時 直接取key就行--> <if test="status != null">article.article_status = #{status} AND </if> <!--mybatis作模糊查詢時 使用concat方法拼接%keywords%--> <if test="keywords != null">article.article_title like concat(concat('%',#{keywords}),'%') AND </if> <!--這裏忘了加AND差點被噁心死--> <if test="userId != null">article.article_user_id = #{userId} AND </if> <!--分類--> <if test="categoryId != null"> article.article_id in ( select article_category_ref.article_id from article_category_ref where article_category_ref.category_id = #{category_id} ) AND </if> <!--標籤--> <if test="tagId != null"> article.article_id in ( select article_tag_ref.article_id from article_tag_ref where article_tag_ref.tag_id = #{tagId} ) AND </if> </where> 1 = 1 order by article.article_order DESC ,article.article_id DESC </select>
3、添加數據。
在添加數據時,若是須要把插入數據的主鍵返回,咱們要設置useGeneratedKeys="true" 同時設置 keyProperty="articleId"。useGeneratedKeys="true"表示要獲取插入記錄的主鍵,keyProperty="articleId"表示把返回的主鍵賦值給articleId這個屬性。
/** * 添加文章 * @param article * @return */ Integer insert(Article article);
@Test public void insert() { Article article = new Article(); article.setArticleViewCount(10); article.setArticleTitle("你好,這是測試文章的標題"); article.setArticleCommentCount(20); article.setArticleContent("你好,這是測試文章的內容"); article.setArticleCreateTime(new Date()); article.setArticleUpdateTime(new Date()); article.setArticleIsComment(1); article.setArticleLikeCount(20); article.setArticleOrder(1); article.setArticleStatus(1); article.setArticleSummary("你好,這是測試文章的總結"); article.setArticleUserId(1); int result = articleMapper.insert(article); System.out.println(article.getArticleId()); }
<!--這裏要注意兩個問題 第一個是獲取插入的數據的主鍵 第二個是要在數據後面添加jdbcType 這樣能夠在插入空數據的時候自動轉爲空字符串--> <insert id="insert" parameterType="Article" useGeneratedKeys="true" keyProperty="articleId"> insert into <include refid="tb"/> (article_user_id, article_title, article_content,article_summary, article_view_count, article_comment_count, article_like_count, article_create_time,article_update_time, article_is_comment, article_status, article_order) values ( #{articleUserId,jdbcType=INTEGER },#{articleTitle,jdbcType=VARCHAR},#{articleContent,jdbcType=VARCHAR}, #{articleSummary,jdbcType=VARCHAR},#{articleViewCount,jdbcType=INTEGER},#{articleCommentCount,jdbcType=INTEGER}, #{articleLikeCount,jdbcType=INTEGER },#{articleCreateTime,jdbcType=TIMESTAMP },#{articleUpdateTime,jdbcType=TIMESTAMP}, #{articleIsComment,jdbcType=LONGVARCHAR},#{articleStatus,jdbcType=INTEGER },#{articleOrder,jdbcType=INTEGER } ) </insert>
mybatis在插入數據後會返回一個數,這個數表示受影響的行數,一般是1.在執行SQL時MyBatis會自動經過對象中的屬性給SQL中參數賦值,它會自動將Java類型轉換成數據庫的類型。而一旦傳入的是null 程序就沒法準確判斷這個類型應該是什麼(是Integer?是VARCHAR?仍是別的?),就有可能將類型轉換錯誤,從而報錯。加入jdbcType正是爲了解決這樣的報錯,須要針對這些可能爲空的字段,手動指定其轉換時用到的類型。
在添加了jdbcType的狀況下,咱們向數據庫中插入一條空記錄,運行成功。
數據庫中多了一條空記錄
若是咱們不加jdbcType呢?插入依然成功,並無像網上面說的那樣會報錯。這是個問題,待會兒解決一下。
4、刪除數據。
刪除數據時,mybatis會返回被刪除數據的行數。
/** * 根據articleId刪除文章 * @param articleId * @return 影響函數 是被刪除的記錄條數 */ Integer deleteById(@Param(value = "articleId") Integer articleId);
<!-- mybatis刪除數據時 會返回被刪除的行數 --> <delete id="deleteById" parameterType="Integer"> delete from <include refid="tb"/> where article_id = #{articleId} </delete>
5、更新數據
/** * 更新文章 * @param article * @return */ Integer update(Article article);
<!--<if>標籤前面要加<set>標籤 更新的字段後面要加jdbcType--> <update id="update" parameterType="Article"> update <include refid="tb"/> <set> <!--if的test條件裏面取對象的值 不用帶#{} 直接拿對象的屬性值就能夠--> <if test="articleUserId != null and articleUserId != '' ">article_user_id = #{articleUserId,jdbcType=INTEGER },</if> <if test="articleTitle != null and articleTitle != '' ">article_title = #{articleTitle,jdbcType=VARCHAR},</if> <if test="articleContent != null and articleContent != '' ">article_content = #{articleContent,jdbcType=VARCHAR},</if> <if test="articleSummary != null and articleSummary != '' ">article_summary = #{articleSummary,jdbcType=VARCHAR},</if> <if test="articleViewCount != null and articleViewCount != '' ">article_view_count = #{articleViewCount,jdbcType=INTEGER},</if> <if test="articleCommentCount != null and articleCommentCount != '' ">article_comment_count = #{articleCommentCount,jdbcType=INTEGER},</if> <if test="articleLikeCount != null and articleLikeCount != '' ">article_like_count = #{articleLikeCount,jdbcType=INTEGER },</if> <if test="articleCreateTime != null and articleCreateTime != '' ">article_create_time = #{articleCreateTime,jdbcType=TIMESTAMP },</if> <if test="articleUpdateTime != null and articleUpdateTime != '' ">article_update_time = #{articleUpdateTime,jdbcType=TIMESTAMP},</if> <if test="articleIsComment != null and articleIsComment != '' ">article_is_comment = #{articleIsComment,jdbcType=LONGVARCHAR},</if> <if test="articleStatus != null and articleStatus != '' ">article_status = #{articleStatus,jdbcType=INTEGER },</if> <if test="articleOrder != null and articleOrder != '' ">article_order = #{articleOrder,jdbcType=INTEGER },</if> </set> where article_id = #{articleId,jdbcType = INTEGER} </update>
6、其餘知識點
1.使用count()、max()、sum()等方法時,方法名和括號之間不能留空格。
<!--統計全部已經啓用點文章數量--> <select id="countArticle" parameterType="Integer" resultType="Integer"> select count(*) from <include refid="tb"/> where article_status = #{status} </select>
2.mybatis中的`>`要用 `>`來代替,`<`要用`<`來代替。
<!-- 獲取下一篇文章--> <select id="getAfterArticle" parameterType="Integer" resultType="Article"> select <include refid="Base_Column_List"/> from <include refid="tb"/> where article_status = 1 and article_id > #{id} order by article_id ASC limit 1 </select>
<!--獲取上一篇文章 這裏竟然不能寫< 要寫<--> <!-- Mybatis中的sql語句中的「<」浩和「>」號要用轉義字符「<」和」>「,不然會報錯! --> <select id="getPreArticle" parameterType="Integer" resultType="Article"> select <include refid="Base_Column_List"/> from <include refid="tb"/> where article_id < #{id} and article_status = 1 order by article_id DESC limit 1 </select>
3.foreach標籤的使用。
<!--獲取多個分類的文章--> <select id="findArticleByCategoryIds" resultType="Article"> select * from article,article_category_ref <where> article_category_ref.article_id = article.article_id and article_category_ref.category_id in <foreach collection="ids" item="id" open="(" separator="," close=")" > #{id} </foreach> and article.article_status = 1 </where> limit #{limit} </select>