React.js 和 Spring Data REST:第三部分 - 条件操作
| 要查看此代码的更新,请访问我们的 React.js 与 Spring Data REST 教程。 |
在上一节中,您了解了如何启用 Spring Data REST 的超媒体控件,让 UI 通过分页导航,并根据更改页面大小动态调整。您添加了创建和删除员工以及调整页面的功能。但是,没有一个解决方案能够完全考虑其他用户对您当前正在编辑的同一数据进行的更新。
您可以随时从该存储库获取代码并跟随学习。本节基于上一节的应用,并添加了一些额外内容。
是 PUT 还是不 PUT,这是个问题
当您获取资源时,存在它可能因他人更新而过时的风险。为了解决这个问题,Spring Data REST 集成了两项技术:资源版本控制和 ETags。
通过后端资源版本控制和前端使用 ETags,可以有条件地 PUT 更改。换句话说,您可以检测资源是否已更改,并阻止 PUT(或 PATCH)覆盖他人的更新。让我们来看看。
版本化 REST 资源
为了支持资源版本控制,请为需要此类保护的域对象定义一个版本属性。
@Data @Entity public class Employee {private @Id @GeneratedValue Long id; private String firstName; private String lastName; private String description; private @Version @JsonIgnore Long version; private Employee() {} public Employee(String firstName, String lastName, String description) { this.firstName = firstName; this.lastName = lastName; this.description = description; }
}
-
version 字段用
javax.persistence.Version进行注解。它会导致在每次插入和更新行时自动存储和更新值。
在获取单个资源(非集合资源)时,Spring Data REST 将自动添加一个ETag 响应头,其值为该字段。
获取单个资源及其头部
在上一节中,您使用了集合资源来收集数据并填充 UI 的 HTML 表。在 Spring Data REST 中,_embedded 数据集被视为数据的预览。虽然对于快速查看数据很有用,但要获取 ETag 等头部信息,您需要单独获取每个资源。
在此版本中,loadFromServer 已更新为获取集合,然后使用 URI 来检索每个单独的资源。
loadFromServer: function (pageSize) {
follow(client, root, [
{rel: 'employees', params: {size: pageSize}}]
).then(employeeCollection => {
return client({
method: 'GET',
path: employeeCollection.entity._links.profile.href,
headers: {'Accept': 'application/schema+json'}
}).then(schema => {
this.schema = schema.entity;
this.links = employeeCollection.entity._links;
return employeeCollection;
});
}).then(employeeCollection => {
return employeeCollection.entity._embedded.employees.map(employee =>
client({
method: 'GET',
path: employee._links.self.href
})
);
}).then(employeePromises => {
return when.all(employeePromises);
}).done(employees => {
this.setState({
employees: employees,
attributes: Object.keys(this.schema.properties),
pageSize: pageSize,
links: this.links
});
});
},
follow()函数访问 employees 集合资源。then(employeeCollection ⇒ …)子句创建了一个调用来获取 JSON Schema 数据。它有一个子 then 子句来将元数据和导航链接存储在<App/>组件中。- 请注意,此嵌入式 Promise 返回 employeeCollection。这样,集合就可以传递到下一个调用,同时让您获取元数据。
- 第二个
then(employeeCollection ⇒ …)子句将员工集合转换为一个 GET Promise 数组,以获取每个单独的资源。这是您为每个员工获取 ETag 头部所需的内容。 then(employeePromises ⇒ …)子句获取 GET Promise 数组,并使用when.all()将它们合并成一个 Promise,在所有 GET Promise 都解决时解析。-
loadFromServer通过done(employees ⇒ …)结束,其中 UI 状态使用此数据混合进行更新。
此链也在其他地方实现。例如,用于跳转到不同页面的 onNavigate() 已更新为获取单个资源。由于它与上面所示的几乎相同,因此在本节中省略了。
更新现有资源
在本节中,您将添加一个 UpdateDialog React 组件来编辑现有的员工记录。
var UpdateDialog = React.createClass({
handleSubmit: function (e) {
e.preventDefault();
var updatedEmployee = {};
this.props.attributes.forEach(attribute => {
updatedEmployee[attribute] = React.findDOMNode(this.refs[attribute]).value.trim…
