<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                有了開發規范及后臺的數據支持,我們前臺的對接就更加簡單了。 上一節中,我們已經新建了klassServer, 本節的數據增加,我們同樣寫在這個文件中. # services/klass.js ``` // 新增數據 var save = function(name, teacherId, callback) { server.http({ method: 'POST', url: 'klass.Save.json', data : { name: name, teacherId: teacherId } }, function(response) { callback(response); }); } // Public API here return { // 獲取全部教師信息 paginate: function(name, page, pageSize, callback) { return paginate(name, page, pageSize, callback); }, save: save }; ``` ## 單元測試 ``` 'use strict'; describe('Service: klass', function() { // load the service's module beforeEach(module('webAppApp')); // instantiate service var klass, $httpBackend, config; beforeEach(inject(function(_klass_, _$httpBackend_, _config_) { klass = _klass_; config = _config_; // 引用項目配置 $httpBackend = _$httpBackend_; // 定義請求 URL var url = config.apiRootPath + '/Klass.json'; // 定義返回數據, 僅定義正確的返回碼。 var data = {code:200}; // 進行模似數據請求配置.當請求方法為post,資源名為url時, 返回data數據. $httpBackend.when('POST', url).respond(data); // 定義請求 URL url = config.apiRootPath + '/klass.Save.json'; // 定義返回數據, 僅定義正確的返回碼。 // 進行模似數據請求配置.當請求方法為post,資源名為url時, 返回data數據. $httpBackend.when('POST', url).respond(data); })); it('檢測語法是否出現錯誤', function() { // 調用方法 klass.paginate('', 1, 2, function() { console.log('klass paginate passed'); }); // 調用保存 klass.save('name', 3, function(){ console.log('klass save 通過'); }); // 模擬數據請求 $httpBackend.flush(); }); }); ``` ## 控制臺信息 ``` LOG: 'klass paginate passed' PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.069 secsLOG: Object{data: Object{code: 200}, status: 200, headers: function (name) { ... }, config: Object{method: 'POST', transformRequest: [...], transformResponse: [...], paramSerializer: function ngParamSerializer(params) { ... }, jsonpCallbackParam: 'callback', url: 'http://127.0.0.1:8080/javaee/klass.Save.json', data: Object{name: ..., teacherId: ...}, header: Object{contentType: ...}, headers: Object{Accept: ..., Content-Type: ...}}, statusText: ''} PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.069 secsLOG: 'klass save 通過' PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.069 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 11 of 14 SUCCESS (0 secs / 0.082 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 12 of 14 SUCCESS (0 secs / 0.086 secsLOG: Object{data: Object{code: 200, teachers: []}, status: 200, headers: function (name) { ... }, config: Object{method: 'GET', transformRequest: [...], transformResponse: [...], paramSerializer: function ngParamSerializer(params) { ... }, jsonpCallbackParam: 'callback', url: 'http://127.0.0.1:8080/javaee/Teacher_all.json', header: Object{contentType: ...}, headers: Object{Accept: ...}}, statusText: ''} ``` 我們發現,控制臺打印了大量的數據返回信息。為了單元測試中,減少打印資源請求信息給我們帶來的干擾。我們對代碼進行如下重構,以達到凈化控制臺的目的。 1. 設置:僅在開發模式下,在控制臺打印資源請求信息。 services/server.js ``` $http(param).then(function successCallback(response) { // 開發者模式下,打印資源請求結果 if (config.isDebug === true) { console.log(response); } data = response.data; ``` 2.在單元測試時,關閉開發模式 ``` beforeEach(inject(function(_klass_, _$httpBackend_, _config_) { klass = _klass_; config = _config_; // 引用項目配置 config.isDebug = false; // 關閉開發模式 $httpBackend = _$httpBackend_; ``` 此時,再進行單元測試時,我們發現控制臺干凈多了。 ``` 09 02 2017 11:45:08.727:INFO [launcher]: Starting browser PhantomJS 09 02 2017 11:45:09.435:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket Oxpj8Xe-i4QI1QPnAAAA with id 77693093 PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.131 secsLOG: 'klass paginate passed' PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.131 secsLOG: 'klass save 通過' PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 10 of 14 SUCCESS (0 secs / 0.131 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 11 of 14 SUCCESS (0 secs / 0.147 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 12 of 14 SUCCESS (0 secs / 0.153 secsLOG: [] PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 12 of 14 SUCCESS (0 secs / 0.153 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 13 of 14 SUCCESS (0 secs / 0.158 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 14 of 14 SUCCESS (0 secs / 0.161 secsPhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 14 of 14 SUCCESS (0.028 secs / 0.161 secs) Done, without errors. ``` ## CM對接 M層開發測試完畢后,我們繼續回到C層,使其成功與M層進行對接。 ``` 'use strict'; /** * @ngdoc function * @name webAppApp.controller:KlassAddCtrl * @description * # KlassAddCtrl * Controller of the webAppApp */ angular.module('webAppApp') .controller('KlassAddCtrl', function($scope, config, teacher, klass) { $scope.name = ''; // 名稱 // 教師列表 $scope.teachers = []; // 選中的教師 $scope.teacher = 0; $scope.isDebug = config.isDebug; $scope.isError = false; // 是否發生錯誤 $scope.errors = {}; // 錯誤信息 $scope.message = ''; // 提示信息 // 數據提交 var submit = function() { klass.save($scope.name, $scope.teacher, function(response){ if (!angular.equals({}, response.errors)) { // 發生錯誤 $scope.errors = response.errors; $scope.isError = true; // 發生錯誤 $scope.message = ''; // 清空消息 } else { // 添加成功 $scope.message = '添加成功'; $scope.isError = false; } }); }; // 獲取教師列表 var getTeachers = function() { teacher.all(function(response){ $scope.teachers = response; // 獲取到的所有教師 $scope.teacher = $scope.teachers[0].id; // 初始化選中的教師 }); }; // 初始化 var int = function () { getTeachers(); }; int(); $scope.submit = submit; }); ``` 上述代碼,為了顯示成功與錯誤的信息,我們增加了isError, errors, message 三個字段。并且重新寫了submit()方法。并根據返回信息,來定制前臺的顯示。 ### 完善V層 在V層中,增加成功與錯誤的信息。 ``` <div class="row"> <div class="col-md-12"> <div ng-show="message" class="alert alert-success" role="alert">{{message}}</div> <div ng-show="isError" class="alert alert-danger" role="alert">{{errors}}</div> </div> </div> <div class="row"> <div class="col-md-12"> <form ng-submit="submit()"> <label>名稱: <input type="text" ng-model="name"> </label> <label>輔導員: <select ng-model="teacher"> <option ng-repeat="teacher in teachers" ng-value="teacher.id">{{teacher.name}}</option> </select> <button type="submit">submit</button> </form> </div> </div> <div class="debug" ng-show="isDebug"> {{name}} <br /> {{teachers}} <br /> {{teacher}} </div> ``` ## 測試 我們進行數據模擬添加。 1. 姓名為空 ![https://box.kancloud.cn/6425424320f6fb631a336d77a21d100c_1000x294.png](https://box.kancloud.cn/6425424320f6fb631a336d77a21d100c_1000x294.png) 2. 姓名為一位字符串 ![https://box.kancloud.cn/ffb9e4f7d5027029209543cb848c5d4e_994x282.png](https://box.kancloud.cn/ffb9e4f7d5027029209543cb848c5d4e_994x282.png) 沒錯,正如你看到的,并沒有出現我們想看到的"名稱必須介于2-8之間"的提示。這是哪出了問題呢? 下面,我們一步步的排查問題。 排查問題前,我們需要非常明確的清楚數據的傳輸流。 前臺 -> 后臺 -> 前臺 具體是這樣: V -> C -> M -> 后臺 -> M -> C -> V 我們先找到控制臺的網絡選項卡,來查看前臺傳給后臺的數據是否出現了問題。 ![https://box.kancloud.cn/933bcc61db39debc61d1c431fed58c14_952x231.gif](https://box.kancloud.cn/933bcc61db39debc61d1c431fed58c14_952x231.gif) 通過觀察網絡,我們發現,數據成功的發送給了后臺。然后得到了非我們預期的結果。但我們在上一小節中,明明的使用postman對后臺進行過測試,怎么現在發送過去數據就得到了和使用postman不一樣的結果呢? 問題的根本在于:使用postman發送的數據,與使用anguarjs發送的數據雖然相同,但是`文件頭`定義卻有區別。 我們再詳細查看一下文件頭: angularjs: ![https://box.kancloud.cn/24a8fdcc8a83d518dd28bbd4df8a73dd_822x348.png](https://box.kancloud.cn/24a8fdcc8a83d518dd28bbd4df8a73dd_822x348.png) postman: ![https://box.kancloud.cn/ec10b6ca8f8dbb2d9da0a044bfc5a587_969x232.gif](https://box.kancloud.cn/ec10b6ca8f8dbb2d9da0a044bfc5a587_969x232.gif) 沒錯,無論是選擇`form-data`還是`x-www-form-urlencoded`,它們的`Content-Type:`都以angularjs的`application/json`發送的不一樣。 事實上,后臺的服務端在接收到數據后,也是先去判斷用戶發送的`Content-Type`,從而確定用戶發送的數據類型。 > content-type延伸閱讀: [https://segmentfault.com/a/1190000003002851](https://segmentfault.com/a/1190000003002851) 找到了問題的關鍵后,讓我們在進行數據請求時,重新對postman進行設置: ![https://box.kancloud.cn/2bb78ed023ab2e9260b49b0803e260c9_969x232.gif](https://box.kancloud.cn/2bb78ed023ab2e9260b49b0803e260c9_969x232.gif) 當我們進行如上設置時,最終`Content-Type`的值,便以angularjs發送請求的值完全相同了。 <hr /> 其實angularjs和postman一樣,在進行數據發送時,也是可以設置`Content-Type`值的。只是在前后臺分離的設計中,我們更愿意使用`application/json`,以表示發送的數據為JSON字符串。 > 官方文檔: [https://docs.angularjs.org/api/ng/service/$http](https://docs.angularjs.org/api/ng/service/$http) ![https://box.kancloud.cn/1e6f8b40126003253093c216b09c1049_1362x788.png](https://box.kancloud.cn/1e6f8b40126003253093c216b09c1049_1362x788.png) <hr /> 看來問題出現了后臺的測試上,本來應該使用`application/json`,我們卻使用了其它的方式。 # 修正后臺 我們將postman進行正確的設置后,發現也出現了如前臺集成測試的錯誤。 ![https://box.kancloud.cn/63a6ecc52188fd5f7e60064a177dd48e_886x517.gif](https://box.kancloud.cn/63a6ecc52188fd5f7e60064a177dd48e_886x517.gif) 無論,我們輸入任何的內容,都會提示我們『名稱不能為空』 這是由于:我們在接收數據時,使用struts-json插件進行了處理;但在進行數據驗證時,卻仍然使用的是struts的默認驗證機制。這導致了將發送的`Content-Type`為`application/json`時, struts-json對數據進行攔截,最終使得struts在進行驗證時,沒有驗證到任何的數據。為了解決這個問題,我們需要增加另一個攔截器,將struts-json攔截后的數據,轉發至struts的驗證器,從而達到字段的驗證的目的。 為此,我們對struts.xml進行更改: 修改前 : ``` <!-- 配置攔截器,使傳入的json數據能夠成功的通過setXXX()方法來傳值 --> <interceptor-ref name="defaultStack" /> <interceptor-ref name="json"> <param name="enableSMD">true</param> </interceptor-ref> ``` 修改后: ``` <!-- 配置攔截器,使傳入的json數據能夠成功的通過setXXX()方法來傳值 --> <interceptor-ref name="json"> <param name="enableSMD">true</param> </interceptor-ref> <!-- 增加jsonValidationWorkflowStack攔截器,用于JSON字段驗證 --> <interceptor-ref name="jsonValidationWorkflowStack" /> ``` 我們刪除產生沖突的默認攔截器`defaultStack`在`json`攔截器下,增加`jsonValidationWorkflowStack`攔截器。配置好后,保存struts.xml文件,并重啟server以使struts立即生效. 此時,我們再進行請求,驗證很順利的生效了。現在,我們在進行前臺的測試,數據也被成功的返回了。 ![https://box.kancloud.cn/63aa13c53c5e8ffc8f8c2bc6a06fe50b_723x139.gif](https://box.kancloud.cn/63aa13c53c5e8ffc8f8c2bc6a06fe50b_723x139.gif) > git checkout -f step12.3.3 <hr /> 記不太清是什么時候引入的log4j2這個日志記錄的工具了。由于引它的引用,我們控制臺上會生成很多條日志記錄,如果前期你并不想看到它們,可以對log4j2.xml做如下配置: ``` <?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <!-- 設置日志級別為error --> <Logger name="com.opensymphony.xwork2" level="error"/> <Logger name="org.apache.struts2" level="error"/> <Root level="warn"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration> ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看