我們假設前臺與后臺定完規范后就開始獨立開發,那么此時我們需要考慮的僅僅是下述接口信息:
```
PUT /Teacher/{id}
```
| Type | Name | Description | Schema |
| ---- | ---- | ---- | ---- |
| Path | id | 更新的教師ID | Long |
| Body | teacher | 更新教師數據 | Teacher |
# 定義請求路徑、接收請求主體
TeacherController
```
@PutMapping("{id}") ?
@CrossOrigin("*")
public void update(@PathVariable Long id, @RequestBody Teacher newTeacher) {
System.out.println(id); ?
System.out.println(newTeacher.toString()); ?
}
```
* ? 接收PUT請求。
* ? 使用系統內置的方法打印數據到控制臺。
## `HTTP Request`測試
我們可以打開`REST Client`,然后點擊`Convert request to new format`生成一個新的`HTTP Request`,也可以在`IDEA`中使用快捷鍵`??N(macos)`或`Ctrl+Shift+Alt+Insert (windows)`來新建一個`HTTP Request`。并在該請求文件中輸入以下信息:
> linux版本的快捷鍵請查閱[https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html?keymap=primary\_default\_for\_windows#create-an-http-request-scratch-file](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html?keymap=primary_default_for_windows#create-an-http-request-scratch-file)
```
PUT http://localhost:8080/Teacher/1 ?
Content-Type: application/json ?
?
{ ?
"name": "張三更新",
"username": "newzhangsan",
"sex": false,
"email": "newzhangsan@yunzhiclub.com"
}
```
* ? 聲明請求的地址及方法
* ? 告訴后臺我發送主體數據的類型為`json`(json只是后臺接收數據的一種,我們在向后臺發送主體數據時必須告訴后臺數據的類型。這是由于數據傳輸的本質是二進制,后臺是沒有辦法通過二進制數據來區域我們傳入的數據類型的)
* ? 此處空一行,來表示:此行以下的內容為主體內容。
* ? 發送給后臺的`json`字符串,該字符串必須使用嚴格的`json`格式。
點擊綠色的啟動按鈕,發起數據請求:

由于我們在后臺返回的數據為void,即未返回任何數據,所以返回的結果的響應數據為空,結果如下:
```
PUT http://localhost:8080/Teacher/1 ?
?
HTTP/1.1 200 ?
Content-Length: 0 ?
Date: Fri, 25 Oct 2019 01:00:06 GMT ?
?
<Response body is empty> ?
Response code: 200; Time: 50ms; Content length: 0 bytes ?
```
* ? 請求地址
* ? 使用的協議為HTTP/1.1,返回的狀態碼為:200 (200代碼請求正常)。
* ? 返回的內容長度為0
* ? 處理時間 (GMT時間,在該值上加8即北京時間)
* ? 空行,分隔返回的信息。
* ? 告知用戶返回主體的確是沒有內容。如果不標記,那么后臺如果返回10個空格符(換行符等)給我們,我們也會認為為空。
* ? 總結:響應狀態200;花費時間50ms;內容長度:0字節。
> GMT格林時間:我國為東8時區,也稱為GMT+8。大體原因是這樣:地球24小時自轉一圈,經度不同的地區看到太陽升起的時間是不一樣的。由于地球自轉的方向是自西向東(這就是為什么太陽從東邊升起的原因),所以相隔的地區永遠都是位于東側的先看到日出。相隔的越遠看到日出的時差就越大,所以我們也是可以使用看到日出的時間差來描述兩地間的距離的。格林呢在我們西邊,看到日出的時候比我們晚8個小時,所以如果以北京時間為標準時間的話,那么格林時間就是BJ-8。而相反的,以格林為標準時間的話,我們就是GMT+8。其實只所以以格林為標準時間,是由于我們將其所在的經度標記為0度,格林以東就是東經,格林以西就是西經。而東經180度與西經180度都是地球的半個圈,所以東經180度就等于西經180度。而地球轉360度需要24個小時,那么轉180就需要12個小時。這么推算,轉**120**度就是需要8個小時。然后我們的時候是GMT+8,說明比格林早看到日期,那么就必然位于格式**東**邊。所以北京的經度應該是**東經120度**。
此時,我們再切換至程序控制臺:

查看控制臺信息:

# JDBCTemplate.update
前面的章節中我們使用了`JDBCTemplate.execute()`來完成了數據的插入操作,`JDBCTemplate.execute()`實質上是執行了一條不需要返回值的`sql`語句。原則上當前也是可以完成數據的更新操作的。官方文檔如是說:
> You can use the`execute(..)`method to run any arbitrary SQL. Consequently, the method is often used for DDL statements. It is heavily overloaded with variants that take callback interfaces, binding variable arrays, and so on.
也就是說在進行一般的數據操作時,官方文檔并不推薦我們直接`JDBCTemplate.execute()`。官方文檔還說:
> You can use the`update(..)`method to perform insert, update, and delete operations. Parameter values are usually provided as variable arguments or, alternatively, as an object array.
也就是說在執行數據的`插入` 、`更新`、`刪除`操作時,我們應該使用`update()`方法。
```
/**
* 使用傳入的數據更新某個教師的數據
*
* @param id 教師ID
* @param newTeacher 更新教師
*/
@PutMapping("{id}")
@CrossOrigin("*")
public void update(@PathVariable Long id, @RequestBody Teacher newTeacher) {
String sql = String.format(
"update `teacher` set `name` = '%s' , `username` = '%s' , `email` = '%s' , `sex` = %s where `id` = %s",
newTeacher.getName(), newTeacher.getUsername(), newTeacher.getEmail(), newTeacher.getSex().toString(), id
);
this.jdbcTemplate.update(sql); ?
}
```
* ? 使用update方法來完成數據的更新操作。
## 測試
重新啟動項目,重新運行`HTTP Request`測試后,我們打開數據查看`id`為1的教師數據:

# 對接測試

## BUG修復
有個小BUG就是男女不太統一,修改為男性,查看的時候是女性;修改為女性,查看的時候卻是男姓。這是由于查看與修改的規范不同造成的。我們規定:0(false)男性,1(true)為女性。
依此:對應修改兩個V層文件:
teacher-add.component.html、teacher-edit.component.html
```html
<label> <input type="radio" name="sex" [value]="false" [(ngModel)]="sex"> 男</label>
<label> <input type="radio" name="sex" [value]="true" [(ngModel)]="sex"> 女</label>
```
# 參考文檔
| 名稱 | 鏈接 | 預計學習時長(分) |
| --- | --- | --- |
| mysql update語法介紹 | [https://www.runoob.com/mysql/mysql-update-query.html](https://www.runoob.com/mysql/mysql-update-query.html) | 10 |
| 格林尼治標準時間 |[https://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E5%B0%BC%E6%B2%BB%E6%A8%99%E6%BA%96%E6%99%82%E9%96%93](https://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E5%B0%BC%E6%B2%BB%E6%A8%99%E6%BA%96%E6%99%82%E9%96%93) | 2 |
| http狀態碼 | [https://www.runoob.com/http/http-status-codes.html](https://www.runoob.com/http/http-status-codes.html) | 5 |
| JdbcTemplate update | [https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/data-access.html#jdbc-JdbcTemplate-examples-update](https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/data-access.html#jdbc-JdbcTemplate-examples-update) | 5 |
| 源碼地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.5](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.5) | - |
- 序言
- 第一章:Hello World
- 第一節:Angular準備工作
- 1 Node.js
- 2 npm
- 3 WebStorm
- 第二節:Hello Angular
- 第三節:Spring Boot準備工作
- 1 JDK
- 2 MAVEN
- 3 IDEA
- 第四節:Hello Spring Boot
- 1 Spring Initializr
- 2 Hello Spring Boot!
- 3 maven國內源配置
- 4 package與import
- 第五節:Hello Spring Boot + Angular
- 1 依賴注入【前】
- 2 HttpClient獲取數據【前】
- 3 數據綁定【前】
- 4 回調函數【選學】
- 第二章 教師管理
- 第一節 數據庫初始化
- 第二節 CRUD之R查數據
- 1 原型初始化【前】
- 2 連接數據庫【后】
- 3 使用JDBC讀取數據【后】
- 4 前后臺對接
- 5 ng-if【前】
- 6 日期管道【前】
- 第三節 CRUD之C增數據
- 1 新建組件并映射路由【前】
- 2 模板驅動表單【前】
- 3 httpClient post請求【前】
- 4 保存數據【后】
- 5 組件間調用【前】
- 第四節 CRUD之U改數據
- 1 路由參數【前】
- 2 請求映射【后】
- 3 前后臺對接【前】
- 4 更新數據【前】
- 5 更新某個教師【后】
- 6 路由器鏈接【前】
- 7 觀察者模式【前】
- 第五節 CRUD之D刪數據
- 1 綁定到用戶輸入事件【前】
- 2 刪除某個教師【后】
- 第六節 代碼重構
- 1 文件夾化【前】
- 2 優化交互體驗【前】
- 3 相對與絕對地址【前】
- 第三章 班級管理
- 第一節 JPA初始化數據表
- 第二節 班級列表
- 1 新建模塊【前】
- 2 初識單元測試【前】
- 3 初始化原型【前】
- 4 面向對象【前】
- 5 測試HTTP請求【前】
- 6 測試INPUT【前】
- 7 測試BUTTON【前】
- 8 @RequestParam【后】
- 9 Repository【后】
- 10 前后臺對接【前】
- 第三節 新增班級
- 1 初始化【前】
- 2 響應式表單【前】
- 3 測試POST請求【前】
- 4 JPA插入數據【后】
- 5 單元測試【后】
- 6 惰性加載【前】
- 7 對接【前】
- 第四節 編輯班級
- 1 FormGroup【前】
- 2 x、[x]、{{x}}與(x)【前】
- 3 模擬路由服務【前】
- 4 測試間諜spy【前】
- 5 使用JPA更新數據【后】
- 6 分層開發【后】
- 7 前后臺對接
- 8 深入imports【前】
- 9 深入exports【前】
- 第五節 選擇教師組件
- 1 初始化【前】
- 2 動態數據綁定【前】
- 3 初識泛型
- 4 @Output()【前】
- 5 @Input()【前】
- 6 再識單元測試【前】
- 7 其它問題
- 第六節 刪除班級
- 1 TDD【前】
- 2 TDD【后】
- 3 前后臺對接
- 第四章 學生管理
- 第一節 引入Bootstrap【前】
- 第二節 NAV導航組件【前】
- 1 初始化
- 2 Bootstrap格式化
- 3 RouterLinkActive
- 第三節 footer組件【前】
- 第四節 歡迎界面【前】
- 第五節 新增學生
- 1 初始化【前】
- 2 選擇班級組件【前】
- 3 復用選擇組件【前】
- 4 完善功能【前】
- 5 MVC【前】
- 6 非NULL校驗【后】
- 7 唯一性校驗【后】
- 8 @PrePersist【后】
- 9 CM層開發【后】
- 10 集成測試
- 第六節 學生列表
- 1 分頁【后】
- 2 HashMap與LinkedHashMap
- 3 初識綜合查詢【后】
- 4 綜合查詢進階【后】
- 5 小試綜合查詢【后】
- 6 初始化【前】
- 7 M層【前】
- 8 單元測試與分頁【前】
- 9 單選與多選【前】
- 10 集成測試
- 第七節 編輯學生
- 1 初始化【前】
- 2 嵌套組件測試【前】
- 3 功能開發【前】
- 4 JsonPath【后】
- 5 spyOn【后】
- 6 集成測試
- 7 @Input 異步傳值【前】
- 8 值傳遞與引入傳遞
- 9 @PreUpdate【后】
- 10 表單驗證【前】
- 第八節 刪除學生
- 1 CSS選擇器【前】
- 2 confirm【前】
- 3 功能開發與測試【后】
- 4 集成測試
- 5 定制提示框【前】
- 6 引入圖標庫【前】
- 第九節 集成測試
- 第五章 登錄與注銷
- 第一節:普通登錄
- 1 原型【前】
- 2 功能設計【前】
- 3 功能設計【后】
- 4 應用登錄組件【前】
- 5 注銷【前】
- 6 保留登錄狀態【前】
- 第二節:你是誰
- 1 過濾器【后】
- 2 令牌機制【后】
- 3 裝飾器模式【后】
- 4 攔截器【前】
- 5 RxJS操作符【前】
- 6 用戶登錄與注銷【后】
- 7 個人中心【前】
- 8 攔截器【后】
- 9 集成測試
- 10 單例模式
- 第六章 課程管理
- 第一節 新增課程
- 1 初始化【前】
- 2 嵌套組件測試【前】
- 3 async管道【前】
- 4 優雅的測試【前】
- 5 功能開發【前】
- 6 實體監聽器【后】
- 7 @ManyToMany【后】
- 8 集成測試【前】
- 9 異步驗證器【前】
- 10 詳解CORS【前】
- 第二節 課程列表
- 第三節 果斷
- 1 初始化【前】
- 2 分頁組件【前】
- 2 分頁組件【前】
- 3 綜合查詢【前】
- 4 綜合查詢【后】
- 4 綜合查詢【后】
- 第節 班級列表
- 第節 教師列表
- 第節 編輯課程
- TODO返回機制【前】
- 4 彈出框組件【前】
- 5 多路由出口【前】
- 第節 刪除課程
- 第七章 權限管理
- 第一節 AOP
- 總結
- 開發規范
- 備用