1
0
mirror of https://github.com/apachecn/modern-java-zh.git synced 2025-06-07 10:01:05 +00:00
This commit is contained in:
wizardforcel 2016-07-22 17:07:54 +08:00
parent af0baf706e
commit c1701ec2e4

109
ch10.md Normal file
View File

@ -0,0 +1,109 @@
# 在 Nashron 中使用 Backbone.js
> 原文:[Using Backbone.js with Nashorn](http://winterbe.com/posts/2014/04/07/using-backbonejs-with-nashorn/)
> 译者:[飞龙](https://github.com/wizardforcel)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
这个例子展示了如何在Java8的Nashron JavaScript引擎中使用Backbone.js模型。Nashron在2014年三月首次作为Java SE 8 的一部分发布并通过以原生方式在JVM上运行脚本扩展了Java的功能。对于Java Web开发者Nashron尤其实用因为它可以在Java服务器上复用现有的客户端代码。传统的[Node.js](http://nodejs.org/)具有明显优势但是Nashorn也能够缩短JVM的差距。
当你在HTML5前端使用现代的JavaScript MVC框架例如[Backbone.js](http://backbonejs.org/)时越来越多的代码从服务器后端移动到Web前端。这个方法可以极大提升用户体验因为在使用视图的业务逻辑时节省了服务器的很多往返通信。
Backbone允许你定义模型类它们可以用于绑定视图例如HTML表单。当用户和UI交互时Backbone会跟踪模型的升级反之亦然。它也能通过和服务器同步模型来帮助你例如调用服务端REST处理器的适当方法。所以你最终会在前端实现业务逻辑将你的服务器模型用于处理持久化数据。
在服务端复用Backbone模型十分容易用Nashron完成就像下面的例子所展示的那样。在我们开始之前确保你通过阅读我的[Nashorn教程](ch3.md)熟悉了在Nashron引擎中编程JavaScript。
## Java 模型
首先我们在Java中定义实体类`Product`。这个类可用于数据库的CURD操作增删改查。要记住这个类是个纯粹的Java Bean不实现任何业务逻辑因为我们想让前端正确执行UI的业务逻辑。
```java
class Product {
String name;
double price;
int stock;
double valueOfGoods;
}
```
## Backbone 模型
现在我们定义Backbone模型作为Java Bean的对应。Backbone模型`Product`使用和Java Bean相同的数据结构因为它是我们希望在Java服务器上持久存储的数据。
Backbone模型也实现了业务逻辑`getValueOfGoods`方法通过将`stock``price`相乘计算所有产品的总值。每次`stock``price`的变动都会使`valueOfGoods`重新计算。
```js
var Product = Backbone.Model.extend({
defaults: {
name: '',
stock: 0,
price: 0.0,
valueOfGoods: 0.0
},
initialize: function() {
this.on('change:stock change:price', function() {
var stock = this.get('stock');
var price = this.get('price');
var valueOfGoods = this.getValueOfGoods(stock, price);
this.set('valueOfGoods', valueOfGoods);
});
},
getValueOfGoods: function(stock, price) {
return stock * price;
}
});
```
由于Backbone模型不使用任何Nashron语言扩展我们可以在客户端浏览器和服务端Java安全地使用同一份代码。
要记住我特意选择了十分简单的函数来演示我的意图。真实的业务逻辑应该会更复杂。
## 将二者放在一起
下一个目标是在Nashron中例如在Java服务器上复用Backbone模型。我们希望完成下面的行为把所有属性从Java Bean上绑定到Backbone模型上计算`valueOfGoods`属性最后将结果传回Java。
首先我们创建一个新的脚本它仅仅由Nashron执行所以我们这里可以安全地使用Nashron的扩展。
```js
load('http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js');
load('http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js');
load('product-backbone-model.js');
var calculate = function(javaProduct) {
var model = new Product();
model.set('name', javaProduct.name);
model.set('price', javaProduct.price);
model.set('stock', javaProduct.stock);
return model.attributes;
};
```
这个脚本首先加载了相关的外部脚本[Underscore](http://underscorejs.org/) 和 [Backbone](http://backbonejs.org/)Underscore是Backbone的必备条件以及我们前面的`Product`Backbone模型。
函数`calcute`接受`Product`Java Bean将其所有属性绑定到新创建的Backbone`Product`之后返回模型的所有属性给调用者。通过在Backbone模型上设置`stock``price`属性,`ValueOfGoods`属性由于注册在模型`initialize`构造函数中的事件处理器,会自动计算出来。
最后我们在Java中调用`calculate`函数。
```java
Product product = new Product();
product.setName("Rubber");
product.setPrice(1.99);
product.setStock(1337);
ScriptObjectMirror result = (ScriptObjectMirror)
invocable.invokeFunction("calculate", product);
System.out.println(result.get("name") + ": " + result.get("valueOfGoods"));
// Rubber: 2660.63
```
我们创建了新的`Product`Java Bean并且将它传递到JavaScript函数中。结果触发了`getValueOfGoods`方法,所以我们可以从返回的对象中读取`valueOfGoods`属性的值。
## 总结
在Nashron中复用现存的JavaScript库十分简单。Backbone适用于构建复杂的HTML5前端。在我看来Nashron和JVM现在是Node.js的优秀备选方案因为你可以在Nashron的代码库中充分利用Java的整个生态系统例如JDK的全部API以及所有可用的库和工具。要记住你在使用Nashron时并不限制于Java -- 想想 Scala、Groovy、Clojure和`jjs`上的纯JavaScript。
这篇文章中可运行的代码托管在[Github](https://github.com/winterbe/java8-tutorial)上(请见[这个文件](https://github.com/winterbe/java8-tutorial/blob/master/res/nashorn6.js))。请随意[fork我的仓库](https://github.com/winterbe/java8-tutorial/fork),或者在[Twitter](https://twitter.com/winterbe_)上向我反馈。