我们假设前台与后台定完规范后就开始独立开发,那么此时我们需要考虑的仅仅是下述接口信息:
```
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`格式。
点击绿色的启动按钮,发起数据请求:
![](https://img.kancloud.cn/60/44/6044bae0ab7b7c3277e9ce88a36dc9a2_757x367.png)
由于我们在后台返回的数据为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度**。
此时,我们再切换至程序控制台:
![](https://img.kancloud.cn/1a/ef/1aef81a4db4c47372f54dbf0c9e6b586_706x238.png)
查看控制台信息:
![](https://img.kancloud.cn/31/79/317931c034a863cdccf61847fda58254_878x141.png)
# 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的教师数据:
![](https://img.kancloud.cn/af/45/af4541204fbeab754b9e60833a384a54_681x59.png)
# 对接测试
![](https://img.kancloud.cn/ab/9c/ab9c7c53f221513bc4ac693a51ec22b3_666x483.gif)
## 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
- 总结
- 开发规范
- 备用