目標1:運用AngularJS前端框架的經常使用指令 目標2:完成品牌管理的列表功能 目標3:完成品牌管理的分頁列表功能 目標4:完成品牌管理的增長功能 目標5:完成品牌管理的修改功能 目標6:完成品牌管理的刪除功能 目標7:完成品牌管理的條件查詢功能 目標N:通用Mappercss
AngularJS 誕生於2009年,由Misko Hevery 等人建立,後爲Google所收購。是一款優秀的前端JS框架,已經被用於Google的多款產品當中。AngularJS有着諸多特性,最爲核心的是:MVC、模塊化、自動化雙向數據綁定、依賴注入等等。 html
Angular遵循軟件工程的MVC模式,並鼓勵展示,數據,和邏輯組件之間的鬆耦合.經過依賴注入(dependency injection),Angular爲客戶端的Web應用帶來了傳統服務端的服務,例如獨立於視圖的控制。 所以,後端減小了許多負擔,產生了更輕的Web應用。 Model:數據,其實就是angular變量($scope.XX);前端
View: 數據的呈現,Html+Directive(指令);java
Controller:操做數據,就是function,數據的增刪改查;mysql
AngularJS是創建在這樣的信念上的:即聲明式編程應該用於構建用戶界面以及編寫軟件構建,而指令式編程很是適合來表示業務邏輯。框架採用並擴展了傳統HTML,經過雙向的數據綁定來適應動態內容,雙向的數據綁定容許模型和視圖之間的自動同步。所以,AngularJS使得對DOM的操做再也不重要並提高了可測試性。 git
依賴注入(Dependency Injection,簡稱DI)是一種設計模式, 指某個對象依賴的其餘對象無需手工建立,只須要「吼一嗓子」,則此對象在建立時,其依賴的對象由框架來自動建立並注入進來,其實就是最少知識法則;模塊中全部的service和provider兩類對象,均可以根據形參名稱實現DI.angularjs
高內聚低耦合法則github
1)官方提供的模塊 ng、ngRoute、ngAnimateweb
2)用戶自定義的模塊 angular.module(‘模塊名’,[ ])spring
<title>入門小Demo-1</title> <script src="angular.min.js"></script> {{100+100}}
執行結果以下: 表達式的寫法是{{表達式 }} 表達式能夠是變量或是運算式 > > ng-app 指令 做用是告訴子元素如下的指令是歸angularJs的,angularJs會識別的 > ng-app 指令定義了AngularJS 應用程序的 根元素。 > ng-app 指令在網頁加載完畢時會自動引導(自動初始化)應用程序。
<title>入門小Demo-1 雙向綁定</title> <script src="angular.min.js"></script> 請輸入你的姓名:<input ng-model="myname"> <br> {{myname}},你好
運行效果以下: > ng-model 指令用於綁定變量,這樣用戶在文本框輸入的內容會綁定到變量上,而表達式能夠實時地輸出變量。
> 咱們若是但願有些變量具備初始值,可使用ng-init指令來對變量初始化:
<title>入門小Demo-3 初始化</title> <script src="angular.min.js"></script> 請輸入你的姓名:<input ng-model="myname"> <br> {{myname}},你好
<title>入門小Demo-3 初始化</title> <script src="angular.min.js"></script> <script> var app=angular.module('myApp',[]); //定義了一個叫myApp的模塊 //定義控制器 app.controller('myController',function($scope){ $scope.add=function(){ return parseInt($scope.x)+parseInt($scope.y); } }); </script> x:<input ng-model="x"> y:<input ng-model="y"> 運算結果:{{add()}}
運行結果以下: ng-controller用於指定所使用的控制器。
> 理解 $scope: > > $scope 的使用貫穿整個 AngularJS App 應用,它與數據模型相關聯,同時也是表達式執行的上下文.有了$scope就在視圖和控制器之間創建了一個通道,基於做用域視圖在修改數據時會馬上更新 $scope,一樣的$scope 發生改變時也會馬上從新渲染視圖.
<title>入門小Demo-5 事件指令</title> <script src="angular.min.js"></script> <script> var app=angular.module('myApp',[]); //定義了一個叫myApp的模塊 //定義控制器 app.controller('myController',function($scope){ $scope.add=function(){ $scope.z= parseInt($scope.x)+parseInt($scope.y); } }); </script> x:<input ng-model="x"> y:<input ng-model="y"> <button ng-click="add()">運算</button> 結果:{{z}}
運行結果: ng-click 是最經常使用的單擊事件指令,再點擊時觸發控制器的某個方法
<title>入門小Demo-6 循環數據</title> <script src="angular.min.js"></script> <script> var app=angular.module('myApp',[]); //定義了一個叫myApp的模塊 //定義控制器 app.controller('myController',function($scope){ $scope.list= [100,192,203,434 ];//定義數組 }); </script> <table> <tbody><tr ng-repeat="x in list"> <td>{{x}}</td> </tr> </tbody></table>
這裏的ng-repeat指令用於循環數組變量。
運行結果以下:
<title>入門小Demo-7 循環對象數組</title> <script src="angular.min.js"></script> <script> var app=angular.module('myApp',[]); //定義了一個叫myApp的模塊 //定義控制器 app.controller('myController',function($scope){ $scope.list= [ {name:'張三',shuxue:100,yuwen:93}, {name:'李四',shuxue:88,yuwen:87}, {name:'王五',shuxue:77,yuwen:56} ];//定義數組 }); </script> <table> <tbody><tr> <td>姓名</td> <td>數學</td> <td>語文</td> </tr> <tr ng-repeat="entity in list"> <td>{{entity.name}}</td> <td>{{entity.shuxue}}</td> <td>{{entity.yuwen}}</td> </tr> </tbody></table>
運行結果以下:
咱們的數據通常都是從後端獲取的,那麼如何獲取數據呢?咱們通常使用內置服務$http來實現。注意:如下代碼須要在tomcat中運行。
<title>入門小Demo-8 內置服務</title> <meta charset="utf-8"> <script src="angular.min.js"></script> <script> var app=angular.module('myApp',[]); //定義了一個叫myApp的模塊 //定義控制器 app.controller('myController',function($scope,$http){ $scope.findAll=function(){ $http.get('data.json').success( function(response){ $scope.list=response; } ); } }); </script> <table> <tbody><tr> <td>姓名</td> <td>數學</td> <td>語文</td> </tr> <tr ng-repeat="entity in list"> <td>{{entity.name}}</td> <td>{{entity.shuxue}}</td> <td>{{entity.yuwen}}</td> </tr> </tbody></table>
創建文件 data.json
[ {"name":"張三","shuxue":100,"yuwen":93}, {"name":"李四","shuxue":88,"yuwen":87}, {"name":"王五","shuxue":77,"yuwen":56}, {"name":"趙六","shuxue":67,"yuwen":86} ]
通用 Mapper 提供了一些通用的方法,這些通用方法是以接口的形式提供的,它主要簡化了咱們工做中常作的單表操做問題,讓MyBatis由面向過程轉換成了面向對象的操做方式,固然,MyBatis編寫SQL面向過程操做和通用Mapper面向對象操做能夠共存。
爲了方便測試,咱們在parent工程中引入log日誌包,版本以下:
<slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version>
包引入以下:
<!-- log start --> <dependency> <groupid>log4j</groupid> <artifactid>log4j</artifactid> <version>${log4j.version}</version> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-api</artifactid> <version>${slf4j.version}</version> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-log4j12</artifactid> <version>${slf4j.version}</version> </dependency> <!-- log end -->
log4j.properties
log4j.rootLogger=DEBUG,Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.logger.org.apache=DEBUG
使用通用通用Mapper首先須要引入依賴包。
<!--通用Mapper--> <dependency> <groupid>tk.mybatis</groupid> <artifactid>mapper</artifactid> </dependency>
替換MyBatis集成Spring的包掃描bean,修改pinyougou-mapper項目中spring-mybatis.xml
替換前:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:basePackage="com.pinyougou.mapper" p:sqlSessionFactoryBeanName="sqlSessionFactoryBean" />
替換後:
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer" p:basepackage="com.pinyougou.mapper" p:sqlsessionfactorybeanname="sqlSessionFactoryBean"> <!--通用接口--> <property name="properties"> <value> mappers=tk.mybatis.mapper.common.Mapper </value> </property> </bean>
在pinyougou-sellergoods-service編寫測試類
package com.pinyougou; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MapperTest { private ApplicationContext act; @Before public void init(){ act = new ClassPathXmlApplicationContext("classpath:spring/spring.xml"); } @Test public void testSpring(){ String[] names = act.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
測試結果
addressMapper areasMapper brandMapper citiesMapper contentCategoryMapper contentMapper freightTemplateMapper goodsDescMapper goodsMapper itemCatMapper itemMapper orderItemMapper orderMapper payLogMapper provincesMapper seckillGoodsMapper seckillOrderMapper sellerMapper specificationMapper specificationOptionMapper typeTemplateMapper userMapper
這裏能夠看到每一個接口都產生了一個代理對象,而且注入到Spring容器中,而每一個接口都繼承了Mapper 接口,因此初步能夠判定,繼承通用Mapper成功,接着咱們來使用通用Mapper實現增刪改查。
/*** * 增長數據 * 不忽略空值 */ @Test public void testInsert(){ Brand brand = new Brand(); brand.setName("深圳黑馬訓練營"); //brand.setFirstChar("C"); int acount = brandMapper.insert(brand); System.out.println(acount); }
日誌:
當Brand的id、firstChar爲空的時候,SQL語句仍然執行了插入操做。
==> Preparing: INSERT INTO tb_brand ( id,name,first_char ) VALUES( ?,?,? ) ==> Parameters: null, 深圳黑馬訓練營(String), null
/*** * 增長數據 * 忽略空值 */ @Test public void testInsertSelective(){ Brand brand = new Brand(); brand.setName("傳智播客-黑馬訓練營"); //brand.setFirstChar("C"); int acount = brandMapper.insertSelective(brand); System.out.println(acount); }
日誌:
當Brand的id、firstChar爲空的時候,SQL語句沒有執行了插入操做。
==> Preparing: INSERT INTO tb_brand ( name ) VALUES( ? ) ==> Parameters: 傳智播客-黑馬訓練營(String)
/** * 需改操做 * 不忽略空值 */ @Test public void testUpdateByPrimaryKey(){ Brand brand = new Brand(); brand.setId(25L); //brand.setName("深圳黑馬訓練營"); brand.setFirstChar("S"); //根據主鍵修改數據 int mcount = brandMapper.updateByPrimaryKey(brand); System.out.println(mcount); }
日誌:
當name爲空的時候,SQL語句仍然執行修改。
==> Preparing: UPDATE tb_brand SET name = ?,first_char = ? WHERE id = ? ==> Parameters: null, S(String), 25(Long)
/** * 需改操做 * 忽略空值 */ @Test public void testUpdateByPrimaryKeySelective(){ Brand brand = new Brand(); brand.setId(25L); brand.setName("深圳黑馬訓練營"); //brand.setFirstChar("S"); //根據主鍵修改數據 int mcount = brandMapper.updateByPrimaryKeySelective(brand); System.out.println(mcount); }
日誌:
當name爲空的時候,SQL語句不執行修改。
1 2 3 sql ==> Preparing: UPDATE tb_brand SET name = ? WHERE id = ? ==> Parameters: 深圳黑馬訓練營(String), 25(Long)
/** * 構造條件執行修改 * 不忽略空值 */ @Test public void testUpdateByExample(){ //firstChar=S Brand brand = new Brand(); brand.setName("深圳市黑馬訓練營"); //建立Example對象 Example example = new Example(Brand.class); //Criteria 用來構造約束條件 Example.Criteria criteria = example.createCriteria(); //第一個參數是Brand對應的屬性,第二個參數是屬性約束值 至關於 where firstChar=S criteria.andEqualTo("firstChar","S"); //條件修改數據 int mcount = brandMapper.updateByExample(brand,example); System.out.println(mcount); }
日誌:
criteria.andEqualTo(「firstChar」,「S」); 轉換成了這裏的SQL語句 where(first_char=?),這裏firstChart爲空,但SQL語句仍然執行了修改。
1 2 ==> Preparing: UPDATE tb_brand SET name = ?,first_char = ? WHERE ( first_char = ? ) ==> Parameters: 深圳市黑馬訓練營(String), null, S(String)
/** * 構造條件執行修改 * 忽略空值 */ @Test public void testUpdateByExampleSelective(){ //firstChar=S Brand brand = new Brand(); brand.setFirstChar("S"); //建立Example對象 Example example = new Example(Brand.class); //Criteria 用來構造約束條件 Example.Criteria criteria = example.createCriteria(); //第一個參數是Brand對應的屬性,第二個參數是屬性約束值 至關於 where name='深圳市黑馬訓練營' criteria.andEqualTo("name","深圳市黑馬訓練營"); //條件修改數據 int mcount = brandMapper.updateByExampleSelective(brand,example); System.out.println(mcount); }
日誌:
這裏name爲空,SQL語句並無作出修改操做。
==> Preparing: UPDATE tb_brand SET first_char = ? WHERE ( name = ? ) ==> Parameters: S(String), 深圳市黑馬訓練營(String)
/*** * 根據主鍵查詢 */ @Test public void testSelectByPrimaryKey(){ long id = 25L; Brand brand = brandMapper.selectByPrimaryKey(id); System.out.println(brand); }
日誌:
==> Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? ==> Parameters: 25(Long) Brand{id=25, name='深圳市黑馬訓練營', firstChar='S'}
/*** * 查詢單個記錄 */ @Test public void testSelectOne(){ Brand brand = new Brand(); brand.setId(25L); brand.setName("深圳市黑馬訓練營"); Brand brand1 = brandMapper.selectOne(brand); System.out.println(brand1); }
日誌:
==> Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? AND name = ? ==> Parameters: 25(Long), 深圳市黑馬訓練營(String) Brand{id=25, name='深圳市黑馬訓練營', firstChar='S'}
注意:
這裏須要注意一下,複合該條件的數據,數據庫裏必須<=1條,若是大於了1條數據,則會報錯
TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
/*** * 根據條件執行查詢 */ @Test public void testExample(){ Example example = new Example(Brand.class); Example.Criteria criteria = example.createCriteria(); //id IN(1,2,5,6) List<long> ids = new ArrayList<long>(); ids.add(1L); ids.add(2L); ids.add(5L); ids.add(6L); //第二個參數是個集合對象便可,注意集合對象這裏對應的類型雖然是Object,不過要和你數據庫對應的類型保持一致 criteria.andIn("id",ids); //執行查詢 List<brand> brands = brandMapper.selectByExample(example); for (Brand brand : brands) { System.out.println(brand); } }
日誌:
==> Preparing: SELECT id,name,first_char FROM tb_brand WHERE ( id in ( ? , ? , ? , ? ) ) ==> Parameters: 1(Long), 2(Long), 5(Long), 6(Long) Brand{id=1, name='聯想', firstChar='L'} Brand{id=2, name='華爲', firstChar='H'} Brand{id=5, name='OPPO', firstChar='O'} Brand{id=6, name='深圳市黑馬訓練營', firstChar='S'}
/*** * 根據條件查詢 * 入參:JavaBean */ @Test public void testSelect(){ Brand brand = new Brand(); brand.setId(25L); brand.setName("深圳市黑馬訓練營"); //把brand做爲查詢條件,這裏會忽略空值 List<brand> brands = brandMapper.select(brand); for (Brand bd : brands) { System.out.println(bd); } }
日誌:
==> Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? AND name = ? ==> Parameters: 25(Long), 深圳市黑馬訓練營(String) Brand{id=25, name='深圳市黑馬訓練營', firstChar='S'}
/*** * 查詢全部 */ @Test public void testSelectAll(){ //執行查詢 List<brand> brands = brandMapper.selectAll(); for (Brand brand : brands) { System.out.println(brand); } }
日誌:
==> Preparing: SELECT id,name,first_char FROM tb_brand ==> Parameters: Brand{id=1, name='聯想', firstChar='L'} Brand{id=2, name='華爲', firstChar='H'} Brand{id=3, name='深圳市黑馬訓練營', firstChar='S'} ...........................................
/*** * 統計查詢-總記錄數 */ @Test public void testSelectCount(){ //查詢總記錄數 int count = brandMapper.selectCount(null); System.out.println(count); }
日誌:
==> Preparing: SELECT COUNT(id) FROM tb_brand ==> Parameters: 25
/*** * 根據ID刪除 */ @Test public void testDeleteByPrimaryKey(){ long id = 25; int dcount = brandMapper.deleteByPrimaryKey(id); System.out.println(dcount); }
日誌:
==> Preparing: DELETE FROM tb_brand WHERE id = ? ==> Parameters: 25(Long)
/*** * 條件刪除 */ @Test public void testDeleteByExample(){ Example example = new Example(Brand.class); Example.Criteria criteria = example.createCriteria(); //where id between 23 and 28 criteria.andBetween("id",23L,28L); //根據條件刪除 int dcount = brandMapper.deleteByExample(example); System.out.println(dcount); }
日誌:
==> Preparing: DELETE FROM tb_brand WHERE ( id between ? and ? ) ==> Parameters: 23(Long), 28(Long)
/*** * 條件刪除 * 入參:javaBean */ @Test public void testDelete(){ Brand brand = new Brand(); brand.setName("阿凡達"); //根據條件刪除 int dcount = brandMapper.delete(brand); System.out.println(dcount); }
日誌:
==> Preparing: DELETE FROM tb_brand WHERE name = ? ==> Parameters: 阿凡達(String)
在作項目的時候,分頁屬於很常見的,但一般都有繁瑣的封裝。這裏提供了一個通用分頁插件pagehelper,能知足咱們工做中的基本需求。
首先須要引入對應的依賴
<!--分頁工具包--> <dependency> <groupid>com.github.pagehelper</groupid> <artifactid>pagehelper</artifactid> </dependency>
而後須要配置一個mybatis攔截器,在pinyougou-mapper項目的mybatis.xml中加入以下插件代碼
<plugins> <!-- com.github.pagehelper爲PageInterceptor類所在包名 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="reasonable" value="true" /> </plugin> </plugins>
上述配置也能夠不配置在mybatis.xml中,也能夠配置在spring-mybatis.xml的SqlSessionFactoryBean中,代碼以下:
<!-- SqlSessionFactoryBean --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis/mybatis.xml" /> <property name="typeAliasesPackage" value="com.pinyougou.model" /> <property name="mapperLocations"> <list> <value>classpath:com/pinyougou/mapper/*Mapper.xml</value> </list> </property> <property name="dataSource" ref="dataSource" /> <!--分頁插件配置--> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <!--配置分頁屬性--> <property name="properties"> <props> <!--指定數據庫方言--> <prop key="helperDialect">mysql</prop> <!--合理化分頁操做--> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean>
PageInfo類既包含咱們工做中的分頁信息,也包含分頁查詢的集合對象,因此很實用,以下代碼:
public class PageInfo<t> implements Serializable { private static final long serialVersionUID = 1L; //當前頁 private int pageNum; //每頁的數量 private int pageSize; //當前頁的數量 private int size; //當前頁面第一個元素在數據庫中的行號 private int startRow; //當前頁面最後一個元素在數據庫中的行號 private int endRow; //總記錄數 private long total; //總頁數 private int pages; //結果集 private List<t> list; //前一頁 private int prePage; //下一頁 private int nextPage; //是否爲第一頁 private boolean isFirstPage = false; //是否爲最後一頁 private boolean isLastPage = false; //是否有前一頁 private boolean hasPreviousPage = false; //是否有下一頁 private boolean hasNextPage = false; //導航頁碼數 private int navigatePages; //全部導航頁號 private int[] navigatepageNums; //導航條上的第一頁 private int navigateFirstPage; //導航條上的最後一頁 private int navigateLastPage; //........略 }
分頁插件的使用很簡單,配置好了後,直接調用PageHelper的靜態方法startPage便可實現分頁,其餘查詢正常寫就好了,注意一點,調用startPage的方法必須寫在執行查詢selectAll()前面,不然分頁無效。
/** * 分頁測試 */ @Test public void testPage(){ //page 當前頁 size 每頁顯示多少條 int page = 1,size=10; //分頁處理,只須要調用PageHelper.startPage靜態方法便可。S PageHelper.startPage(page,size); //查詢 List<brand> brands = brandMapper.selectAll(); //獲取分頁信息,注意這裏傳入了brands集合對象 PageInfo<brand> pageInfo = new PageInfo<brand>(brands); System.out.println(pageInfo); }
日誌:
==> Preparing: SELECT count(0) FROM tb_brand ==> Parameters: ------------------------------------------------------------------------------------------------------------------------------------------------ ==> Preparing: SELECT id,name,first_char FROM tb_brand LIMIT ? ==> Parameters: 10(Integer) ------------------------------------------------------------------------------------------------------------------------------------------------ PageInfo{pageNum=1, pageSize=10, size=10, startRow=1, endRow=10, total=22, pages=3, list=Page{count=true, pageNum=1, pageSize=10, startRow=0, endRow=10, total=22, pages=3, reasonable=true, pageSizeZero=false}, prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=8, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}
品牌分頁實現,記得再pinyougou-sellergoods-interface中引入分頁包
<!--分頁工具包--> <dependency> <groupid>com.github.pagehelper</groupid> <artifactid>pagehelper</artifactid> </dependency>
實現品牌列表的查詢(不用分頁和條件查詢)效果以下:
將「資源/靜態原型/運營商管理後臺」下的頁面資源拷貝到pinyougou-manager-web下
其中plugins文件夾中包括了angularJS 、bootstrap、JQuery等經常使用前端庫,咱們將在項目中用到
修改brand.html ,引入JS
<script src="/plugins/angularjs/angular.min.js"></script>
指定模塊和控制器
ng-app 指令中定義的就是模塊的名稱
ng-controller 指令用於爲你的應用添加控制器。
在控制器中,你能夠編寫代碼,製做函數和變量,並使用 scope 對象來訪問。
<script> /****** * 一、引入angularjs * 二、發送請求 * 三、顯示數據 *****/ //定義一個模塊 var app = angular.module("pinyougou",[]); /***** * 定義一個controller * 發送HTTP請求從後臺獲取數據 ****/ app.controller("brandController",function($scope,$http){ //建立一個方法 //獲取全部的品牌信息 $scope.getPage=function(page,size){ //發送請求獲取數據 $http.post("/brand/list.shtml?page="+page+"&size="+size).success(function(response){ //集合數據 $scope.list = response.list; }); } }); </script>
<input type="checkbox" ng-model="id"> {{entity.id}} {{entity.name}} {{entity.firstChar}} <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>
4.3.5 初始化調用
在品牌管理下方放置分頁欄,實現分頁功能
在pinyougou-sellergoods-interface的BrandService.java 增長方法定義
/*** * 分頁返回列表 * @param pageNum * @param pageSize * @return */ public PageInfo<brand> getAll(int pageNum, int pageSize);
在pinyougou-sellergoods-service的BrandServiceImpl.java中實現該方法y:
public PageInfo<brand> getAll(int pageNum, int pageSize) { //執行分頁 PageHelper.startPage(pageNum,pageSize); //List<brand> all = brandMapper.getAllBrand(); List<brand> all = brandMapper.selectAll(); PageInfo<brand> pageInfo = new PageInfo<brand>(all); return pageInfo; }
PageHelper爲MyBatis分頁插件
在pinyougou-manager-web工程的BrandController.java新增方法
/*** * 分頁查詢數據 * 獲取JSON數據 * @return */ @RequestMapping(value = "/list") public PageInfo<brand> list(@RequestParam(value = "page", required = false, defaultValue = "1") int page, @RequestParam(value = "size", required = false, defaultValue = "10") int size) { return brandService.getAll(page, size); }
在brand.html引入分頁組件
<!--分頁相關引入--> <link rel="stylesheet" href="/plugins/angularjs/pagination.css"> <script src="/plugins/angularjs/pagination.js"></script>
構建app模塊時引入pagination模塊
//定義一個模塊 var app = angular.module("pinyougou",["pagination"]); //引入分頁模塊
頁面的表格下放置分頁組件
<!--分頁--> <tm-pagination conf="paginationConf"></tm-pagination>
在brandController中添加以下代碼
/*** * 分頁控件配置 * currentPage:當前頁 * totalItems:共有多少條記錄 * itemsPerPage:每頁顯示多少條 * perPageOptions:每頁多少條選項條 * onChange:參數發生變化時執行 * */ $scope.paginationConf = { currentPage: 1, totalItems: 10, itemsPerPage: 10, perPageOptions: [10, 20, 30, 40, 50], onChange: function(){ $scope.reloadList();//從新加載 } }; //從新加載 $scope.reloadList=function(){ $scope.getPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage); }
在頁面的body元素上去掉ng-init指令的調用
<script> /****** * 步驟分析: * 一、引入angularjs * 二、發送請求 * 三、顯示數據 *****/ //定義一個模塊 var app = angular.module("pinyougou",["pagination"]); /***** * 定義一個controller * 發送HTTP請求從後臺獲取數據 ****/ app.controller("brandController",function($scope,$http){ /*** * 分頁控件配置 * currentPage:當前頁 * totalItems:共有多少條記錄 * itemsPerPage:每頁顯示多少條 * perPageOptions:每頁多少條選項條 * onChange:參數發生變化時執行 * */ $scope.paginationConf = { currentPage: 1, totalItems: 10, itemsPerPage: 10, perPageOptions: [10, 20, 30, 40, 50], onChange: function(){ $scope.reloadList();//從新加載 } }; //建立一個方法 //獲取全部的品牌信息 $scope.getPage=function(page,size){ //發送請求獲取數據 $http.post("/brand/list.shtml?page="+page+"&size="+size).success(function(response){ //集合數據 $scope.list = response.list; //分頁數據 $scope.paginationConf.totalItems=response.total; }); } //從新加載 $scope.reloadList=function(){ $scope.getPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage); } }); </script>
實現品牌增長功能
在pinyougou-manager-web的BrandController中增長add方法,同時相應JSON數據。
/*** * 增長品牌數據 * @param brand * 響應數據:success * true:成功 false:失敗 * message * 響應的消息 * */ @RequestMapping(value = "/add",method = RequestMethod.POST) public Map<string,object> add(@RequestBody Brand brand){ //存放響應消息 Map<string,object> dataMap = new HashMap<string,object>(); try { //執行增長 int acount = brandService.add(brand); if(acount>0){ //增長成功 dataMap.put("success",true); dataMap.put("message","增長品牌成功"); } } catch (Exception e) { e.printStackTrace(); dataMap.put("success",false); dataMap.put("message","增長品牌失敗"); } return dataMap; }
在pinyougou-sellergoods-interface的BrandService.java新增方法定義
/*** * 增長品牌信息 * @param brand * @return */ int add(Brand brand);
在com.pinyougou.sellergoods.service.impl的BrandServiceImpl.java實現該方法
@Override public int add(Brand brand) { return brandMapper.insertSelective(brand); }
//添加品牌方法 $scope.save = function(){ //發送Http請求,執行增長 $http.post("/brand/add.shtml",$scope.entity).success(function(response){ //判斷執行狀態 if(response.success){ //從新加載新的數據 $scope.reloadList(); }else{ //打印錯誤消息 alert(response.message); } }); }
綁定表單元素,咱們用ng-model指令,綁定按鈕的單擊事件咱們用ng-click
<!-- 編輯窗口 --> <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h3 id="myModalLabel">品牌編輯</h3> </div> <div class="modal-body"> <table class="table table-bordered table-striped" width="800px"> <tbody><tr> <td>品牌名稱</td> <td><input ng-model="entity.name" class="form-control" placeholder="品牌名稱"> </td> </tr> <tr> <td>首字母</td> <td><input ng-model="entity.firstChar" class="form-control" placeholder="首字母"> </td> </tr> </tbody></table> </div> <div class="modal-footer"> <button ng-click="save()" class="btn btn-success" data-dismiss="modal" aria-hidden="true">保存</button> <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">關閉</button> </div> </div> </div> </div>
爲了每次打開窗口沒有遺留上次的數據,咱們能夠修改新建按鈕,對entity變量進行清空操做
<button ng-click="entity={}" type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal"><i class="fa fa-file-o"></i> 新建</button>
效果
響應消息體咱們寫的是一個Map,每次須要用到的時候,都要重複建立這個Map對象,並重復給指定的key賦值,存在大量重複代碼,並且每次key容易書寫錯,因此咱們能夠考慮封裝成一個實體Bean,名字叫Result,每次直接new Result()便可。
因爲Result可能會在不少項目中都會用到,因此咱們能夠考慮把它放到pinyougou-common項目中,在pinyougou-common中建立Result類
package com.pinyougou.http; import java.io.Serializable; public class Result implements Serializable { private boolean success; private String message; public Result(boolean success, String message) { this.success = success; this.message = message; } public Result(boolean success) { this.success = success; } public Result(String message) { this.message = message; } public Result() { } //get.. set.. toString.. }
不管是哪一個項目都直接或者間接依賴了pinyougou-pojo,因此可讓pojo依賴pinyougou-common,maven有依賴的傳遞性,則全部項目都會依賴pinyougou-common,而pinyougou-common主要用來寫一些經常使用的工具包,因此任何項目依賴他都合情合理。
在pinyougou-pojo的pom.xml中加入依賴
<!--依賴pinyougou-common--> <dependency> <artifactid>pinyougou-common</artifactid> <groupid>com.pinyougou</groupid> <version>1.0-SNAPSHOT</version> </dependency>
修改pinyougou-manager-web中的BrandController的add方法:
/*** * 增長品牌數據 * @param brand * 響應數據:success * true:成功 false:失敗 * message * 響應的消息 * */ @RequestMapping(value = "/add",method = RequestMethod.POST) public Result add(@RequestBody Brand brand){ try { //執行增長 int acount = brandService.add(brand); if(acount>0){ //增長成功 return new Result(true,"增長品牌成功"); } } catch (Exception e) { e.printStackTrace(); } return new Result(false,"增長品牌失敗"); }
點擊列表的修改按鈕,彈出窗口,修改數據後點「保存」執行保存操做,大概分爲2個步驟。
第一:根據ID查詢出品牌數據,展現出來。
第二:根據用戶修改保存數據。
在pinyougou-manager-web的BrandController中分別加入根據id查詢和修改品牌的方法
/*** * 修改品牌信息 * @param brand * @return */ @RequestMapping(value = "/update",method = RequestMethod.POST) public Result modify(@RequestBody Brand brand){ try { //根據ID修改品牌信息 int mcount = brandService.updateBrandById(brand); if(mcount>0){ return new Result(true,"品牌修改爲功"); } } catch (Exception e) { e.printStackTrace(); } return new Result(false,"品牌修改失敗"); } /*** * 根據ID查詢品牌信息 * @param id * @return */ @RequestMapping(value = "/{id}",method = RequestMethod.GET) public Brand getById(@PathVariable(value = "id")long id){ //根據ID查詢品牌信息 Brand brand = brandService.getOneById(id); return brand; }
在pinyougou-sellergoods-interface的BrandService.java新增方法定義
/*** * 根據ID查詢品牌信息 * @param id * @return */ Brand getOneById(long id); /*** * 根據ID修改品牌信息 * @param brand * @return */ int updateBrandById(Brand brand);
在pinyougou-sellergoods-service的BrandServiceImpl.java新增方法實現
@Override public Brand getOneById(long id) { return brandMapper.selectByPrimaryKey(id); } @Override public int updateBrandById(Brand brand) { return brandMapper.updateByPrimaryKeySelective(brand); }
增長JS代碼;
//根據ID查詢品牌信息 $scope.getById=function(id){ $http.get("/brand/"+id+".shtml").success(function(response){ //將後臺的數據綁定到前臺 $scope.entity=response; }); }
修改列表中的「修改」按鈕,調用此方法執行查詢實體的操做
<button ng-click="getById(entity.id)" type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button>
修改JS的save方法
//添加或者修改品牌方法 $scope.save = function(){ //發送Http請求,執行增長 var url="/brand/add.shtml"; if($scope.entity.id!=null){ //執行修改數據 url="/brand/update.shtml"; } //執行操做 $http.post(url,$scope.entity).success(function(response){ //判斷執行狀態 if(response.success){ //從新加載新的數據 $scope.reloadList(); }else{ //打印錯誤消息 alert(response.message); } }); }
點擊列表前的複選框,點擊刪除按鈕,刪除選中的品牌。
在BrandController中加入刪除方法
/*** * 根據ID批量刪除 * @param ids * @return */ @RequestMapping(value = "/delete") public Result delete(@RequestBody List<long> ids){ try { //根據ID刪除數據 int dcount = brandService.deleteByIds(ids); if(dcount>0){ return new Result(true,"品牌刪除成功"); } } catch (Exception e) { e.printStackTrace(); } return new Result(false,"品牌刪除失敗"); }
在pinyougou-sellergoods-interface的BrandService.java接口定義方法
/*** * 根據ID批量刪除品牌信息 * @param ids * @return */ int deleteByIds(List<long> ids);
在pinyougou-sellergoods-service的BrandServiceImpl.java實現該方法
@Override public int deleteByIds(List<long> ids) { //建立Example,來構建根據ID刪除數據 Example example = new Example(Brand.class); Example.Criteria criteria = example.createCriteria(); //所需的SQL語句相似 delete from tb_brand where id in(1,2,5,6) criteria.andIn("id",ids); return brandMapper.deleteByExample(example); }
主要思路:咱們須要定義一個用於存儲選中ID的數組,當咱們點擊複選框後判斷是選擇仍是取消選擇,若是是選擇就加到數組中,若是是取消選擇就從數組中移除。在點擊刪除按鈕時須要用到這個存儲了ID的數組。
這裏咱們補充一下JS的關於數組操做的知識
數組的push方法:向數組中添加元素
數組的splice方法:從數組的指定位置移除指定個數的元素 ,參數1爲位置 ,參數2位移除的個數
複選框的checked屬性:用於判斷是否被選中:
//定義一個變量,用於存儲要刪除的品牌ID $scope.selectids=[]; //判斷當前點擊是否要刪除對應品牌 $scope.updateSelection=function($event,id){ //判斷當前操做是不是選中複選框 if($event.target.checked){ //若是選中複選框,則將該id增長到數組中去 $scope.selectids.push(id); }else{ //取消刪除,則從數組中移除該id var idx = $scope.selectids.indexOf(id); //獲取id對應的下標 $scope.selectids.splice(idx, 1);//刪除對應下標的數據,1表示刪除的數量 } } //批量刪除 $scope.delete=function(){ $http.post("/brand/delete.shtml",$scope.selectids).success(function(response){ //判斷刪除狀態 if(response.success){ $scope.reloadList(); }else{ alert(response.message); } }); }
修改列表的複選框
<input type="checkbox" ng-click="updateSelection($event,entity.id)">
修改刪除按鈕
<button ng-click="delete()" type="button" class="btn btn-default" title="刪除"><i class="fa fa-trash-o"></i> 刪除</button>
實現品牌條件查詢功能,輸入品牌名稱、首字母后查詢,並分頁。
修改BrandController裏面的list方法
/*** * 分頁查詢數據 * 獲取JSON數據 * @return */ @RequestMapping(value = "/list") public PageInfo<brand> list(@RequestBody Brand brand,@RequestParam(value = "page", required = false, defaultValue = "1") int page, @RequestParam(value = "size", required = false, defaultValue = "10") int size) { return brandService.getAll(brand,page, size); }
在pinyougou-sellergoods-interface工程的BrandService.java方法增長方法定義
/*** * 分頁返回列表 * @param pageNum * @param pageSize * @return */ public PageInfo<brand> getAll(Brand brand,int pageNum, int pageSize);
在pinyougou-sellergoods-service工程BrandServiceImpl.java實現該方法
public PageInfo<brand> getAll(Brand brand,int pageNum, int pageSize) { //執行分頁 PageHelper.startPage(pageNum,pageSize); //條件查詢 Example example = new Example(Brand.class); Example.Criteria criteria = example.createCriteria(); if(brand!=null){ //名字模糊搜索 if(StringUtils.isNotBlank(brand.getName())){ criteria.andLike("name","%"+brand.getName()+"%"); } //首字母搜索 if(StringUtils.isNotBlank(brand.getFirstChar())){ criteria.andEqualTo("firstChar",brand.getFirstChar()); } } //執行查詢 List<brand> all = brandMapper.selectByExample(example); PageInfo<brand> pageInfo = new PageInfo<brand>(all); //====================================================================== //List<brand> all = brandMapper.getAllBrand(); /*List<brand> all = brandMapper.selectAll(); PageInfo<brand> pageInfo = new PageInfo<brand>(all);*/ return pageInfo; }
修改pinyougou-manager-web的brand.html
增長搜索代碼塊,並綁定一個搜索對象。同時增長點擊事件,調用搜索方法。
<div class="has-feedback"> 品牌名稱:<input ng-model="searchEntity.name"> 品牌首字母:<input ng-model="searchEntity.firstChar"> <button ng-click="getPage(1,10)" class="btn btn-default">查詢</button> </div>
定義一個搜索對象,和搜索條件那裏保持一致,並修改原來搜索方法。
//條件查詢對象定義 $scope.searchEntity={}; //獲取全部的品牌信息 $scope.getPage=function(page,size){ //發送請求獲取數據 $http.post("/brand/list.shtml?page="+page+"&size="+size,$scope.searchEntity).success(function(response){ //集合數據 $scope.list = response.list; //分頁數據 $scope.paginationConf.totalItems=response.total; }); }
次日須要的資料文件</brand></brand></brand></brand></brand></brand></brand></brand></brand></brand></long></long></long></string,object></string,object></string,object></brand></brand></brand></brand></brand></brand></brand></brand></brand></brand></t></t></brand></brand></brand></long></long>