n Cant ssearch; Post n Have s For ;
n Post M Mortagefindamortgage r Cant a Taxpayers ef Post na For Masearch
Post t Washington e Retrial rc Pay e Blagojevichs R For tsearchisearchl
r0h Retrial Cant a Blagojevichs For sG-taste%20%C2%FE%BB%AD%20%D4%DA%CF%DF;searchnsearchs
; Post [ Costs a Taxpayers a Have searchrG-taste%20%C2%FE%BB%AD%20%D4%DA%CF%DFcsearchs Pay in1 Have i Cant esearch searcha
a
csearchisearcht
isearchs Costs T Shows m Taxpayers Mosearcht May a Taxpayers ejsearch
[java] Borrower: Investor Borrower
[java] Credit score: 720
[java] Sales price: 300000.0
[java] Down payment: 30000.0
[java] * Mortgage product: JavaScript FirstTime Mortgage, Qualified? false
[java] * Interest rate: 0.0
[java] * Message: This mortgage is not intended for investors.
[java] Processing file: RubyPrimeMortgage.rb
[java] Borrower: Investor Borrower
[java] Credit score: 720
[java] Sales price: 300000.0
[java] Down payment: 30000.0
[java] * Mortgage product: Ruby Mortgage, Qualified? false
[java] * Interest rate: 0.0
[java] * Message: Down payment must be at least 20% of sale price.
[java] Processing file: GroovyMortgage.groovy
[java] Borrower: Risk E. Borrower
[java] Credit score: 520
[java] Sales price: 300000.0
[java] Down payment: 10000.0
[java] * Mortgage product: Groovy Mortgage, Qualified? false
[java] * Interest rate: 0.0
[java] * Message: Down payment of 3.33% is insufficient. 5% minimum required.
[java] Processing file: JavaScriptFirstTimeMortgage.js
[java] Borrower: Risk E. Borrower
[java] Credit score: 520
[java] Sales price: 300000.0
[java] Down payment: 10000.0
[java] * Mortgage product: JavaScript FirstTime Mortgage, Qualified? true
[java] * Interest rate: 0.08
[java] * Message: Congratulations, you qualify.
[java] Processing file: RubyPrimeMortgage.rb
[java] Borrower: Risk E. Borrower
[java] Credit score: 520
[java] Sales price: 300000.0
[java] Down payment: 10000.0
[java] * Mortgage product: Ruby Mortgage, Qualified? false
[java] * Interest rate: 0.0
[java] * Message: Credit score of 520 is lower than 700 minimum
[java] Sleeping for one minute before reprocessing files.
[java] Use Ctrl-C to exit...
这个输出共有 12 个部分,这是因为程序将四个贷款人示例提交给三个脚本,检查这 12 种组合中贷款人是否符合抵押产品的要求。为了演示本文解释的技术,这个程序会等待一分钟,然后重复处理抵押脚本。在这段停顿期间,可以编辑脚本文件来修改业务规则,还可以在脚本目录中添加新的脚本文件来表示新的抵押产品。在每次重复运行时,程序会扫描脚本目录并处理它找到的所有脚本文件。
例如,假设您希望提高贷款所需的最低信用分数。在一分钟的停顿期间,可以编辑 src/main/scripts/mortgage-products 目录中的 JavaScriptFirstTimeMortgage.js 脚本(见 清单 5),将第 23 行上的业务规则由 if (borrower.creditScore < 500) { 改为 if (borrower.creditScore < 550) {。在下次运行规则时,Risk E. Borrower 就不再符合 JavaScript FirstTime Mortgage 的要求。这个贷款人的信用分数是 520,这个分数低于目前的条件。错误消息现在是 “Your credit score of 520 does not meet the 500 requirement”,但是同样可以在程序运行时纠正这个错误的消息。
回页首
避免动态脚本风险
在运行时修改程序的功能是非常强大的,同样也可能导致风险。可以在正在运行的应用程序中添加新的功能和新的业务规则,而无需停止并重新启动应用程序。同样,也很容易引入新的 bug,甚至是严重的 bug。
但是,动态地修改正在运行的应用程序并不比修改停止运行的应用程序更危险。静态技术仅仅意味着必须重新启动应用程序,然后才能发现那些新的错误。良好的软件开发实践表明,对生产性应用程序的任何修改(无论是动态的,还是静态的)都应该先接受测试,然后才能引入生产环境中。Java 脚本编程 API 并未改变这一规则。
外部脚本文件可以在开发期间进行常规的单元测试。可以使用 JUnit 或其他测试工具和模拟 Java 对象来测试脚本,确保脚本在运行时不会出现错误并产生所期望的结果。将应用程序逻辑放在外部非 Java 脚本文件中并不意味着无法测试这些脚本。
如果您当过 Web CGI 脚本程序员,那么一定知道必须注意传递给 ScriptEngine 的 eval() 方法的东西。脚本引擎会立即执行传递给 eval 方法的代码。因此,绝不要把来自不可信来源的字符串或 Reader 对象传递给脚本引擎。
例如,假设我们使用脚本编程 API 远程监视一个 Web 应用程序。我们让脚本引擎能够访问关键的 Java 对象,这些对象提供 Web 应用程序的状态信息。还创建一个简单的 Web 页面,这个页面接受任意脚本表达式,它将这些表达式传递给脚本引擎进行计算并在 Web 页面上显示输出。这样就可以对正在运行的 Java 对象进行查询并执行对象上的方法,从而帮助判断应用程序的状态。
但是,在这种情况下,能够访问这个 Web 页面的任何人都可以执行任意脚本语句,可以访问任意共享 Java 对象。编程时的失误、错误的配置和安全漏洞会把机密信息泄露给未授权用户,或者让应用程序遭遇拒绝服务攻击(例如,攻击者可以执行与 System.exit 或 /bin/rm -fr / 等效的脚本语句)。与任何强大的工具一样,Java 脚本编程 API 要求您保持谨慎,注意安全。
回页首
进一步开拓的方向
本文主要关注让 Java 应用程序能够在运行时动态地读取并执行外部脚本,以及让脚本能够访问显式提供给它们的 Java 对象。Java 脚本编程 API 还提供了其他特性。例如:
可以使用脚本语言实现一个 Java 接口,然后像使用任何其他 Java 接口引用一样从 Java 代码调用脚本代码。
可以在脚本中实例化并使用 Java 对象,还可以让 Java 应用程序能够访问这些对象。
可以在装载动态脚本时进行预编译,这可以让以后的执行过程更快。
可以设置脚本使用的输入流和输出流,这样就很容易将文件用作脚本的控制台输入源,以及将脚本的控制台输出转发到文件或其他流。
可以设置位置参数,脚本可以将这些参数用作命令行参数。
Java 脚本编程 API 定义了脚本引擎可以选择实现的一些功能,所以并非所有脚本引擎都提供这些功能。在 参考资料 中可以找到关于这些特性和其他特性的读物和在线参考资料。
。 转自:blog/129928