重要说明:Java EE 6 项目需要使用 Tomcat 7.x、GlassFish Server 3.x 或 Oracle WebLogic Server 12c。
下面显示了您将创建的客户端的外观,其中的所有数据都是从 Web 服务接收到的:
当学完本教程时,您会发现对于此应用程序,您只需提供要检查的文本,调用 Web 服务上的操作以及呈现结果。IDE 会生成联系 Web 服务以及发送文本所需的全部代码。其余的操作则由拼写检查器 Web 服务来完成,它将标识拼错的单词并提供建议的替代项列表。
本教程中使用的拼写检查器 Web 服务是由 CDYNE 公司提供的。CDYNE 旨在开发、销售并支持一整套数据增强、数据质量和数据分析 Web 服务以及商业智能集成。拼写检查器 Web 服务是 CDYNE 提供的一个 Web 服务。请注意,基于一个或多个 Web 服务的应用程序的功能大小取决于这些 Web 服务的可用性和可靠性。但是,CDYNE 在常见问题解答中指出,它有一个 100% 可用性目标,并且在发生自然灾害、恐怖行为或其他灾难性事件时,Web 服务流量会传输到其辅助数据中心。CDYNE 在编写本教程以及开发 NetBeans 方面给予了大力支持,NetBeans 要在此特别向其表示感谢。
使用拼写检查器 Web 服务
要通过网络使用名为 "consuming" 的 Web 服务,需要创建一个 Web 服务客户端。为了便于创建 Web 服务客户端,NetBeans IDE 提供了一个客户端创建工具,即“Web 服务客户端”向导,利用该向导可以生成用于查找 Web 服务的代码。此外,IDE 还提供了用于对所创建的 Web 服务客户端进行开发的工具,即 "Projects"(项目)窗口中包含节点的工作区域。这些工具包含在 NetBeans IDE 安装的 EE 包中。这些工具为即用型,无需任何插件。
创建客户端
在此部分,您将利用向导生成基于 Web 服务 WSDL 文件的 Java 对象。
选择 "File"(文件)> "New Project"(新建项目)(在 Windows 和 Linux 中为 Ctrl-Shift-N 组合键,在 MacOS 上为 ⌘-Shift-N 组合键)。在 "Categories"(类别)下,选择 "Java Web"。在 "Projects"(项目)下选择 "Web Application"(Web 应用程序)。单击 "Next"(下一步)。将项目命名为 SpellCheckService,然后确保将相应的服务器指定为目标服务器。(有关详细信息,请参考“入门指南”一节。)将其他所有选项保留为缺省设置,然后单击 "Finish"(完成)。
在 "Projects"(项目)窗口中,右键单击 "SpellCheckService" 项目节点,然后选择 "New"(新建)> "Other"(其他)。在 "New File"(新建文件)向导中,选择 "Web Services"(Web 服务)> "Web Service Client"(Web 服务客户端)。在“Web 服务客户端”向导中,指定 Web 服务的 URL:
您可以通过多种方法来实现 Web 服务客户端。Web 服务的 WSDL 文件限制了您可以向该 Web 服务发送的信息类型,以及您从该 Web 服务接收的信息类型。但是,WSDL 文件不限制您对其所需信息进行传递的方式,以及用户界面所包含的内容。您接下来要生成的客户端实现包含一个 JSP 页和一个 Servlet,前者可使用户输入要检查的文本,后者可将这些文本传递至 Web 服务,然后生成一个包含结果的报告。
对 JSP 页进行编码
JSP 页将包含一个文本区域和一个按钮,前者可供用户输入文本,后者用于将该文本发送至 Web 服务。
右键单击上一步所创建的空白区域,然后选择 "Insert Code"(插入代码)> "Call Web Service Operation"(调用 Web 服务操作)。在 "Select Operation to Invoke"(选择要调用的操作)对话框中,单击 checkSoap.CheckTextBodyV2 操作,如下所示:
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 组合键(在 Mac 上按 ⌘-Shift-I 组合键),或在任意位置单击鼠标右键,然后在打开的上下文菜单中选择 "Fix Imports"(修复导入)。(您可以选择要导入的 List 类。此处将接受缺省的 java.util.List。)以下是已导入类的完整列表:
IDE 使用 Ant 生成脚本来生成和运行应用程序。此生成脚本是由 IDE 基于您在创建项目时所输入的选项来生成的。您可以在项目的 "Project Properties"(项目属性)对话框(在 "Projects"(项目)窗口中右键单击项目节点,然后选择 "Properties"(属性))中调整这些选项。
缺省情况下,NetBeans IDE 创建的 JAX-WS 客户端是同步的。同步客户端会调用对服务的请求,然后在等待响应时暂停其处理。但是,在某些情况下,您希望客户端继续一些其他处理而不是等待响应。例如,在某些情况下,服务可能需要大量时间来处理请求。继续处理而不等待服务响应的 Web 服务客户端称为“异步”。
异步客户端会通过“轮询”或“回调”方法使用 Web 服务。在“轮询”方法中,将调用一个 Web 服务方法并反复请求结果。“轮询”是一种阻止操作,因为它会阻止调用线程,所以这就是不在 GUI 应用程序中使用它的原因。在“回调”方法中,您在 Web 服务方法调用期间传递回调处理程序。当结果有效时,将调用该处理程序的 handleResponse() 方法。这种方法适用于 GUI 应用程序,因为您不必等待响应。例如,从 GUI 事件处理程序发出调用并立即返回控制权,这样可以使用户界面随时保持响应。轮询方法的缺点是,即使在捕获响应后使用响应,也必须对其进行轮询来查明已将其捕获。
在 NetBeans IDE 中,通过勾选 Web 服务引用的编辑 Web 服务属性 GUI 中的框,将异步客户端的支持添加到 Web 服务客户端应用程序中。除了具有轮询 Web 服务或传递回调处理程序并等待结果的方法外,开发该客户端的所有其他方面都与同步客户端相同。
public void callAsyncCallback(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);
}
}
}
按 Ctrl-Shift-I 组合键(在 Mac 上按 ⌘-Shift-I 组合键)并修复导入。这样会添加以下 import 语句: