当学完本教程时,您会发现对于此应用程序,您只需提供要检查的文本,调用 Web 服务上的操作以及呈现结果。IDE 会生成联系 Web 服务以及发送文本所需的全部代码。其余的操作则由拼写检查器 Web 服务来完成,它将标识拼错的单词并提供建议的替代项列表。
本教程中使用的拼写检查器 Web 服务是由 CDYNE 公司提供的。CDYNE 旨在开发、销售并支持一整套数据增强、数据质量和数据分析 Web 服务以及商业智能集成。拼写检查器 Web 服务是 CDYNE 提供的一个 Web 服务。请注意,基于一个或多个 Web 服务的应用程序的功能大小取决于这些 Web 服务的可用性和可靠性。但是,CDYNE 在常见问题解答中指出,它有一个 100% 可用性目标,并且在发生自然灾害、恐怖行为或其他灾难性事件时,Web 服务流量会传输到其辅助数据中心。CDYNE 在编写本教程以及开发 NetBeans 方面给予了大力支持,NetBeans 要在此特别向其表示感谢。
使用拼写检查器 Web 服务
要通过网络使用名为 "consuming" 的 Web 服务,需要创建一个 Web 服务客户端。NetBeans IDE 提供了一个用于创建 Web 服务客户端的客户端创建工具,即,“Web 服务客户端”向导,可以使用该向导生成用于查找 Web 服务的代码。此外,IDE 还提供了用于对所创建的 Web 服务客户端进行开发的工具,即“项目”窗口中包含节点的工作区域。这些工具是标准 NetBeans IDE 安装的一部分,可以直接使用,无需安装任何插件。
您可以通过多种方法来实现 Web 服务客户端。Web 服务的 WSDL 文件限制了您可以向该 Web 服务发送的信息类型,以及您从该 Web 服务接收的信息类型。但是,WSDL 文件不限制您对其所需信息进行传递的方式,以及用户界面所包含的内容。您接下来要生成的客户端实现包含一个 JSP 页和一个 Servlet,前者可使用户输入要检查的文本,后者可将这些文本传递至 Web 服务,然后生成一个包含结果的报告。
对 JSP 页进行编码
JSP 页将包含一个文本区域和一个按钮,前者可供用户输入文本,后者用于将该文本发送至 Web 服务。
try {
//Get the TextArea from the JSP page String TextArea1 = request.getParameter("TextArea1"); //Initialize WS operation arguments
java.lang.String bodyText = TextArea1;
//Process result
com.cdyne.ws.DocumentSummary doc = checkTextBodyV2(bodyText);
String allcontent = doc.getBody();
//From the retrieved document summary,
//identify the number of wrongly spelled words:
int no_of_mistakes = doc.getMisspelledWordCount();
//From the retrieved document summary,
//identify the array of wrongly spelled words:
List allwrongwords = doc.getMisspelledWord();
out.println("<html>");
out.println("<head>");
//Display the report's name as a title in the browser's titlebar:
out.println("<title>Spell Checker Report</title>");
out.println("</head>");
out.println("<body>");
//Display the report's name as a header within the body of the report:
out.println("<h2><font color='red'>Spell Checker Report</font></h2>");
//Display all the content (correct as well as incorrectly spelled) between quotation marks:
out.println("<hr><b>Your text:</b> \"" + allcontent + "\"" + "<p>");
//For every array of wrong words (one array per wrong word),
//identify the wrong word, the number of suggestions, and
//the array of suggestions. Then display the wrong word and the number of suggestions and
//then, for the array of suggestions belonging to the current wrong word, display each
//suggestion:
for (int i = 0; i < allwrongwords.size(); i++) {
String onewrongword = ((Words) allwrongwords.get(i)).getWord();
int onewordsuggestioncount = ((Words) allwrongwords.get(i)).getSuggestionCount();
List allsuggestions = ((Words) allwrongwords.get(i)).getSuggestions();
out.println("<hr><p><b>Wrong word:</b><font color='red'> " + onewrongword + "</font>");
out.println("<p><b>" + onewordsuggestioncount + " suggestions:</b><br>");
for (int k = 0; k < allsuggestions.size(); k++) {
String onesuggestion = (String) allsuggestions.get(k);
out.println(onesuggestion);
}
}
//Display a line after each array of wrong words:
out.println("<hr>");
//Summarize by providing the number of errors and display them:
out.println("<font color='red'><b>Summary:</b> " + no_of_mistakes + " mistakes (");
for (int i = 0; i < allwrongwords.size(); i++) {
String onewrongword = ((Words) allwrongwords.get(i)).getWord();
out.println(onewrongword);
}
out.println(").");
out.println("</font>");
out.println("</body>");
out.println("</html>");
} catch (Exception ex) {
out.println("exception" + ex);
} finally {
out.close();
}
您会看到许多错误线和警告图标,指示未找到的类。要在粘贴代码之后修复导入,请按 Ctrl-Shift-I 组合键,或在任意位置单击鼠标右键,然后在打开的上下文菜单中选择“修复导入”。(您可以选择要导入的 List 类。此处将接受缺省的 java.util.List。)以下是已导入类的完整列表:
IDE 使用 Ant 生成脚本来生成和运行应用程序。此生成脚本是由 IDE 基于您在创建项目时所输入的选项来生成的。您可以在项目的“项目属性”对话框(在“项目”窗口中右键单击项目节点,然后选择“属性”)中调整这些选项。
右键单击项目节点,然后选择“运行”。稍后,应用程序将部署并显示上一部分所编码的 JSP 页。
输入一些文本,确保其中的某些文本存在拼写错误:
单击 "Spell Check",然后查看结果:
异步 Web 服务客户端
缺省情况下,NetBeans IDE 创建的 JAX-WS 客户端是同步的。同步客户端会调用对服务的请求,然后在等待响应时暂停其处理。但是,在某些情况下,您希望客户端继续一些其他处理而不是等待响应。例如,在某些情况下,服务可能需要大量时间来处理请求。继续处理而不等待服务响应的 Web 服务客户端称为“异步”。
异步客户端会通过“轮询”或“回调”方法使用 Web 服务。在“轮询”方法中,将调用一个 Web 服务方法并反复请求结果。轮询是一种阻止操作,因为它会阻止调用线程,所以这就是不在 GUI 应用程序中使用它的原因。在“回调”方法中,您在 Web 服务方法调用期间传递回调处理程序。当结果有效时,将调用该处理程序的 handleResponse() 方法。这种方法适用于 GUI 应用程序,因为您不必等待响应。例如,从 GUI 事件处理程序发出调用并立即返回控制权,这样可以使用户界面随时保持响应。轮询方法的缺点是,即使在捕获响应后使用响应,也必须对其进行轮询来查明已将其捕获。
在 NetBeans IDE 中,通过勾选 Web 服务引用的编辑 Web 服务属性 GUI 中的框,将异步客户端的支持添加到 Web 服务客户端应用程序中。除了具有轮询 Web 服务或传递回调处理程序并等待结果的方法外,开发该客户端的所有其他方面都与同步客户端相同。
public void callAsynchCallback(String text) {
com.cdyne.ws.Check service = new com.cdyne.ws.Check();
com.cdyne.ws.CheckSoap port = service.getCheckSoap();
// initialize WS operation arguments here
java.lang.String bodyText = text;
javax.xml.ws.AsyncHandler<com.cdyne.ws.CheckTextBodyV2Response> asyncHandler = new javax.xml.ws.AsyncHandler<com.cdyne.ws.CheckTextBodyV2Response>() {
public void handleResponse(final javax.xml.ws.Response<com.cdyne.ws.CheckTextBodyV2Response> response) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// Create a DocumentSummary object containing the response.
// Note that getDocumentSummary() is called from the Response object
// unlike the synchronous client, where it is called directly from
// com.cdyne.ws.CheckTextBody
com.cdyne.ws.DocumentSummary doc = response.get().getDocumentSummary();
//From the retrieved DocumentSummary,
//identify and display the number of wrongly spelled words:
final int no_of_mistakes = doc.getMisspelledWordCount();
String number_of_mistakes = Integer.toString(no_of_mistakes);
tfNumberMistakes.setText(number_of_mistakes);
// Check to see if there are any mistakes
if (no_of_mistakes > 0) {
//From the retrieved document summary,
//identify the array of wrongly spelled words, if any:
final List<com.cdyne.ws.Words> allwrongwords = doc.getMisspelledWord();
//Get the first wrong word
String firstwrongword = allwrongwords.get(0).getWord();
//Build a string of all wrong words separated by commas, then display this in tfWrongWords
StringBuilder wrongwordsbuilder = new StringBuilder(firstwrongword);
for (int i = 1; i < allwrongwords.size(); i++) {
String onewrongword = allwrongwords.get(i).getWord();
wrongwordsbuilder.append(", ");
wrongwordsbuilder.append(onewrongword);
}
String wrongwords = wrongwordsbuilder.toString();
tfWrongWords.setText(wrongwords);
//Display the first wrong word
tfWrongWord1.setText(firstwrongword);
//See how many suggestions there are for the wrong word
int onewordsuggestioncount = allwrongwords.get(0).getSuggestionCount();
//Check to see if there are any suggestions.
if (onewordsuggestioncount > 0) {
//Make a list of all suggestions for correcting the first wrong word, and build them into a String.
//Display the string of concactenated suggestions in the tfSuggestions1 text field
List<String> allsuggestions = ((com.cdyne.ws.Words) allwrongwords.get(0)).getSuggestions();
String firstsuggestion = allsuggestions.get(0);
StringBuilder suggestionbuilder = new StringBuilder(firstsuggestion);
for (int i = 1; i < onewordsuggestioncount; i++) {
String onesuggestion = allsuggestions.get(i);
suggestionbuilder.append(", ");
suggestionbuilder.append(onesuggestion);
}
String onewordsuggestions = suggestionbuilder.toString();
tfSuggestions1.setText(onewordsuggestions);
} else {
// No suggestions for this mistake
tfSuggestions1.setText("No suggestions");
}
btNextWrongWord.setEnabled(true);
// See if the ActionListener for getting the next wrong word and suggestions
// has already been defined. Unregister it if it has, so only one action listener
// will be registered at one time.
if (nextWord != null) {
btNextWrongWord.removeActionListener(nextWord);
}
// Define the ActionListener (already instantiated as a private field)
nextWord = new ActionListener() {
//Initialize a variable to track the index of the allwrongwords list
int wordnumber = 1;
public void actionPerformed(ActionEvent e) {
if (wordnumber < no_of_mistakes) {
// get wrong word in index position wordnumber in allwrongwords
String onewrongword = allwrongwords.get(wordnumber).getWord();
//next part is same as code for first wrong word
tfWrongWord1.setText(onewrongword);
int onewordsuggestioncount = allwrongwords.get(wordnumber).getSuggestionCount();
if (onewordsuggestioncount > 0) {
List<String> allsuggestions = allwrongwords.get(wordnumber).getSuggestions();
String firstsuggestion = allsuggestions.get(0);
StringBuilder suggestionbuilder = new StringBuilder(firstsuggestion);
for (int j = 1; j < onewordsuggestioncount; j++) {
String onesuggestion = allsuggestions.get(j);
suggestionbuilder.append(", ");
suggestionbuilder.append(onesuggestion);
}
String onewordsuggestions = suggestionbuilder.toString();
tfSuggestions1.setText(onewordsuggestions);
} else {
tfSuggestions1.setText("No suggestions");
}
// increase i by 1
wordnumber++;
} else {
// No more wrong words! Disable next word button
// Enable Check button
btNextWrongWord.setEnabled(false);
btCheck.setEnabled(true);
}
}
};
// Register the ActionListener
btNextWrongWord.addActionListener(nextWord);
} else {
// The text has no mistakes
// Enable Check button
tfWrongWords.setText("No wrong words");
tfSuggestions1.setText("No suggestions");
tfWrongWord1.setText("--");
btCheck.setEnabled(true);
}
} catch (Exception ex) {
ex.printStackTrace();
}
// Clear the progress bar
pbProgress.setIndeterminate(false);
pbProgress.setString("");
}
});
}
};
java.util.concurrent.Future result = port.checkTextBodyV2Async(bodyText, asyncHandler);
while (!result.isDone()) {
try {
//Display a message that the application is waiting for a response from the server
tfWrongWords.setText("Waiting...");
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(MainForm.class.getName()).log(Level.SEVERE, null, ex);
}
}
}