WWW.AVAV123.COM House Loan Mortgage Loans

Yancing Houseloanmortgageloans K 2 Mortgage Szh 1 House Loan Mortgage Loans 动态调用动态语言,第 2 Szh 分: 在运行时寻找、执行和修改脚本

Yancing Houseloanmortgageloans K 2 Mortgage Szh 1 House Loan Mortgage Loans


Yancing Mortgage searchsearch Yancing Houseloanmortgageloans ssearcha Mortgage c Yancing H Houseloanmortgageloans u Mortgage e1osearchnsearcho Mortgage t Mortgage asearche Houseloanmortgageloans o Yancing n Houseloanmortgageloans S Mortgage e Houseloanmortgageloans r Houseloanmortgageloans h%E5%81%B7%E6%91%B8%E7%9B%B4%E7%94%B7%E5%B8%85y Houseloanmortgageloans zsearch searchssearcha Yancing csearchM Mortgage e Szh rh Houseloanmortgageloans searcho Szh tg%E5%90%95%E5%8A%A0%E5%B9%B3+%E6%B1%9F%E4%B8%8A%E9%9D%92g Yancing 9 Houseloanmortgageloans asearchc Mortgage ngsearchg Szh Sh M Szh rsearchg Yancing g Houseloanmortgageloans Szh %B6%AF%CF%F2%D4%D3%D6%BE%D5%C5%CE%B0%B9%FA%CD%F5%C1%A2%BE%FCorsearchg Mortgage g Yancing Szh irsearchune

为了测试 ScriptMortgageQualifier 类,将使用测试数据表示四个贷款人、贷款人打算购买的一项资产和一笔抵押贷款。我们将用一个贷款人、资产和贷款运行所有三个脚本,检查贷款人是否满足脚本所代表的抵押产品的业务规则。

清单 2 给出 ScriptMortgageQualifierRunner 程序的部分代码,我们将用这个程序创建测试对象、在一个目录中寻找脚本文件并通过 清单 1 中的 ScriptMortgageQualifier 类运行它们。为了节省篇幅,这里没有给出这个程序的 createGoodBorrower()createAverageBorrower()createInvestorBorrower()createRiskyBorrower()createProperty()createLoan() helper 方法。这些方法的作用仅仅是创建实体对象并设置测试所需的值。在 下载 一节中可以获得所有方法的完整源代码。


清单 2. ScriptMortgageQualifierRunner 程序
 
// Imports and some helper methods not shown.
public class ScriptMortgageQualifierRunner {}
 String dirName;
 if (args.length == 0) {} else {}

 scriptDirectory = new File(dirName);
 if (!scriptDirectory.exists() || !scriptDirectory.isDirectory()) {}

 run();
 }

 /**
 * Determines mortgage loan-qualification status for four test borrowers by
 * processing all script files in the given directory. Each script will determine
 * whether the given borrower is qualified for a particular mortgage type
 */
 public static void run() {}
 }

 /**
 * Reads all script files in the scriptDirectory and runs them with this borrower's
 * information to see if he/she qualifies for each mortgage product.
 */
 private static void runQualifications(
 ScriptMortgageQualifier mortgageQualifier,
 Borrower borrower,
 Loan loan,
 Property property
 ) {} catch (FileNotFoundException fnfe) {} catch (IllegalArgumentException e) {} catch (ScriptException e) {}

 if (result == null) continue; // Must have hit exception.

 // Print results.
 System.out.println(
 "* Mortgage product: " + result.getProductName() +
 ", Qualified? " + result.isQualified() +
 "\n* Interest rate: " + result.getInterestRate() +
 "\n* Message: " + result.getMessage()
 );
 System.out.println();
 }
 }

 /** Returns files with a '.' other than as the first or last character. */
 private static File[] getScriptFiles(File directory) {} else {}
 }
 });
 }

 private static void waitOneMinute() {} catch (InterruptedException e) {}
 }
}

ScriptMortgageQualifierRunner 中的 main() 方法搜索命令行上提供的脚本文件目录,如果这个目录存在,就用目录的 File 对象设置一个静态变量,并调用 run() 方法执行进一步的处理。

run() 方法对 清单 1 中的 ScriptMortgageQualifier 类进行实例化,然后用一个无限循环调用内部方法 runQualifications(),测试四个贷款人/贷款场景。这个无限循环模拟连续的抵押申请处理。这个循环让我们可以在脚本目录中添加或修改脚本文件(抵押贷款产品),这些修改会动态地生效,不需要停止应用程序。因为这个应用程序的业务逻辑放在外部脚本中,所以可以在运行时动态地修改业务逻辑。

对于脚本目录中的每个脚本文件,runQualifications() helper 方法分别调用 ScriptMortgageQualifer.qualifyMortgage 一次。每个调用前面有一系列打印语句,它们输出脚本文件和贷款人的相关信息;调用之后,用打印语句显示结果,即贷款人是否符合抵押产品的要求。脚本代码使用共享的 MortgageQualificationResult Java 对象返回其结果,检查这个对象的属性就可以判断贷款人是否合格。

本文的源代码 ZIP 文件包含三个用 Groovy、JavaScript 和 Ruby 编写的脚本文件示例。它们分别代表一种标准的 30 年期固定利率抵押贷款产品。脚本中的代码判断贷款人是否符合这种抵押类型的要求,然后通过调用脚本引擎 put() 方法中提供的共享全局变量 result 来返回结果。全局变量 resultMortgageQualificationResult 类的实例(部分代码见清单 3)。


清单 3. MortgageQualificationResult 类
 
public class MortgageQualificationResult {}

脚本设置 result 的属性,从而指出贷款人是否符合抵押贷款的要求以及应该采用的利率。脚本可以通过 messageproductName 属性指出导致贷款人不合格的原因和返回相关的产品名称。


脚本文件

在给出 ScriptMortgageQualifierRunner 的输出之前,我们先看看这个程序运行的 Groovy、JavaScript 和 Ruby 脚本文件。Groovy 脚本中的业务逻辑定义了一种条件相当宽松的抵押产品,同时由于金融风险比较高,因此利率比较高。JavaScript 脚本代表一种政府担保的抵押贷款,这种贷款要求贷款人必须满足最大收入和其他限制。Ruby 脚本定义的抵押产品业务规则要求贷款人有良好的信用记录,这些人要支付足够的首付款,这种抵押贷款的利率比较低。

清单 4 给出 Groovy 脚本,即使您不了解 Groovy,也应该能够看懂这个脚本。


清单 4. Groovy 抵押脚本
 
/*
  This Groovy script defines the "Groovy Mortgage" product.
  This product is relaxed in its requirements of borrowers.
  There is a higher interest rate to make up for the looser standard.
  All borrowers will be approved if their credit history is good, they can
  make a down payment of at least 5%, and they either earn more than
  $2,000/month or have a net worth (assets minus liabilities) of $25,000.
*/

// Our product name.
result.productName = 'Groovy Mortgage'

// Check for the minimum income and net worth
def netWorth = borrower.totalAssets - borrower.totalLiabilities
if (borrower.monthlyIncome < 2000 && netWorth < 25000) {}" +
  ' requires a net worth of at least $25,000.'
}

def downPaymentPercent = loan.downPayment / property.salesPrice * 100
if (downPaymentPercent < 5) {}% is insufficient." +
 ' 5% minimum required.'
}
if (borrower.creditScore < 600) {}

// Everyone else qualifies. Find interest rate based on down payment percent.
result.qualified = true
result.message = 'Groovy! You qualify.'

switch (downPaymentPercent) {}

请注意全局变量 resultborrowerloanproperty,脚本使用这些变量访问和设置共享 Java 对象中的值。这些变量名是通过调用 ScriptEngine.put() 方法设置的。

还要注意 result.productName = 'Groovy Mortgage' 这样的 Groovy 语句。这个语句似乎是直接设置 MortgageQualificationResult 对象的字符串属性 productName,但是,清单 3 清楚地说明它是一个私有的实例变量。这并不 表示 Java 脚本编程 API 允许违反封装规则,而是说明通过使用 Java 脚本编程 API,Groovy 和大多数其他脚本语言解释器可以很好地操作共享的 Java 对象。如果一个 Groovy 语句尝试设置或读取 Java 对象的私有属性值,Groovy 就会寻找并使用 JavaBean 风格的公共 settergetter 方法。例如,语句 result.productName = 'Groovy Mortgage' 会自动转换为适当的 Java 语句:result.setProductName("Groovy Mortgage")。这个 Java setter 语句也是有效的 Groovy 代码,可以在脚本中使用,但是直接使用属性赋值语句更符合 Groovy 的风格。

现在看看清单 5 中的 JavaScript 抵押产品脚本。这个 JavaScript 脚本代表一种政府担保的贷款,政府支持这种贷款是为了提高公民的住宅拥有率。所以,业务规则要求这是贷款人购买的第一套住宅,而且贷款人打算在此居住,而不是出租获利。


清单 5. JavaScript 抵押脚本
 
/**
 * This script defines the "JavaScript FirstTime Mortgage" product.
 * It is a government-sponsored mortgage intended for low-income, first-time
 * home buyers without a lot of assets who intend to live in the home.
 * Bankruptcies and bad (but not terrible!) credit are OK.
 */
result.productName = 'JavaScript FirstTime Mortgage'

if (!borrower.intendsToOccupy) {}
if (!borrower.firstTimeBuyer) {}
if (borrower.monthlyIncome > 4000) {}
if (borrower.creditScore < 500) {}

// Qualifies. Determine interest rate based on loan amount and credit score.
result.qualified = true
result.message = 'Congratulations, you qualify.'

if (loan.loanAmount > 450000) {} else if (borrower.creditScore < 550) {} else if (borrower.creditScore < 600) {} else if (borrower.creditScore < 700) {} else {}

注意,JavaScript 代码不能像 Groovy 脚本那样使用 Java scriptExit.withMessage() 方法在一个语句中设置不合格消息并退出脚本。这是因为 Rhino JavaScript 解释器并不把抛出的 Java 异常在 ScriptException 堆栈跟踪中作为嵌入的 “错误原因” 向上传递。因此,在堆栈跟踪中更难找到 Java 代码抛出的脚本异常消息。所以 清单 5 中的 JavaScript 代码需要单独设置结果消息,然后再调用 scriptExit.noMessage() 来产生异常,从而终止脚本处理。

第三个抵押产品脚本是用 Ruby 编写的,见清单 6。这种抵押产品要求贷款人具有良好的信用记录,他们可以支付百分之二十的首付款。


清单 6. Ruby 抵押脚本
 
# This Ruby script defines the "Ruby Mortgage" product.
# It is intended for premium borrowers with its low interest rate
# and 20% down payment requirement.

# Our product name
$result.product_name = 'Ruby Mortgage'

# Borrowers with credit unworthiness do not qualify.
if $borrower.credit_score < 700
 $scriptExit.with_message "Credit score of #{}" +
 " is lower than 700 minimum"
end

$scriptExit.with_message 'No bankruptcies allowed' if $borrower.hasDeclaredBankruptcy

# Check other negatives
down_payment_percent = $loan.down_payment / $property.sales_price * 100
if down_payment_percent < 20
 $scriptExit.with_message 'Down payment must be at least 20% of sale price.'
end

# Borrower qualifies. Determine interest rate of loan
$result.message = "Qualified!"
$result.qualified = true

# Give the best interest rate to the best credit risks.
if $borrower.credit_score > 750 || down_payment_percent > 25
 $result.interestRate = 0.06
elsif $borrower.credit_score > 700 && $borrower.totalAssets > 100000
 $result.interestRate = 0.062
else
 $result.interestRate = 0.065
end

在 JRuby 1.0 中不要忘记 $ 符号

在 Ruby 脚本中访问共享的 Java 对象时,一定要记住 Ruby 的全局变量语法。如果省略了全局变量前面的 $ 符号,那么 JRuby 1.0 和当前的 JRuby 1.0.1 二进制版本会抛出一个 RaiseException,而且不提供错误的相关信息。JRuby 源代码存储库中已经纠正了这个 bug,所以在以后的二进制版本中应该不会出现这个问题。

如清单 6 所示,在 Ruby 脚本中,需要在变量名前面加上 $ 符号,这样才能访问放在脚本引擎范围内的共享 Java 对象。这是 Ruby 的全局变量语法。脚本引擎以全局变量的形式向脚本共享 Java 对象,所以必须使用 Ruby 的全局变量语法。

还要注意,在调用共享的 Java 对象时,JRuby 会自动地将 Ruby 式代码转换为 Java 式代码。例如,如果 JRuby 发现代码按照 Ruby 命名约定(即以下划线分隔单词)调用 Java 对象上的方法,比如 $result.product_name = 'Ruby Mortgage',那么 JRuby 会寻找不带下划线的大小写混合式方法名。因此,Ruby 式方法名 product_name= 会正确地转换为 Java 调用 result.setProductName("Ruby Mortgage")


程序输出

现在用这三个抵押产品脚本文件运行 bYancing Houseloanmortgageloans K 2 Mortgage Szh 1 House Loan Mortgage Loans 动态调用动态语言,第 2 Szh 分: 在运行时寻找、执行和修改脚本x e Fapturbo vYancing Houseloanmortgageloans K 2 Mortgage Szh 1 House Loan Mortgage Loans 动态调用动态语言,第 2 Szh 分: 在运行时寻找、执行和修改脚本y q Wwwavav123