第 3 章 用 JBoss EAP 开发应用程序
3.1. 概述
本指南提供了使用 Red Hat JBoss Developer Studio 和 JBoss EAP 7 quickstart 例程开发应用程序的信息。
Red Hat JBoss Developer Studio 是一个基于 Eclipse 的集成开发环境(IDE),它集成了 JBoss 应用程序开发插件。JBoss Developer Studio 可以使用 JBoss 专有的向导并帮助您部署应用程序至 JBoss EAP 服务器。JBoss EAP 7 提供了许多 Quickstarts 例程来帮助用户使用不同的 Java EE 7 技术编写应用程序。
3.2. 设置开发环境
我们推荐您使用 JBoss Developer Studio 11.0 或采用 JBoss EAP 7.1 的更新版本。
下载和安装 JBoss Developer Studio。
相关的说明,请参考《JBoss Developer Studio 安装指南》中的使用安装程序安装 JBoss Developer Studio Stand-alone。
在 JBoss Developer Studio 中设置 JBoss EAP 服务器。
相关的说明,请参考《JBoss Developer Studio 工具入门指南》中的使用运行时检测从 IDE 内部设置 JBoss EAP。
3.3. 使用 Quickstart 例程
JBoss EAP 里包含的 Quickstart 例程是 Maven 项目。
3.3.1. 关于 Maven
Maven 是一个在 Java 开发中创建、构建和管理软件项目的分布式自动构建工具。Maven 使用标准的配置文件(Project Object Model 或称为 POM)来定义项目和管理构建过程。POM 使用 XML 文件描述了模块和组件的依赖关系、构建顺序和结果项目软件包的目标及输出。这确保了项目以正确和统一的方式进行构建。
Maven 是通过资料库实现这一点的。Maven 资料库保存 Java 库、插件和其他的构建构件。默认的公共资料库是 Maven 2 Central Repository,但资料库可以是机构私有和内部的,在开发团队间共享公用的构件。资料库也可来自第三方。更多信息请参考 Apache Maven 项目和 Introduction to Repositories 。
JBoss EAP 附带的 Maven 资料库包含了 Java EE 开发人员构建 JBoss EAP 应用程序所常用的内容。
关于在 JBoss EAP 里使用 Maven 的更多信息,请参考《JBoss EAP 开发指南》中的在 JBoss EAP 里使用 Maven。
3.3.2. 在 Quickstarts 里使用 Maven
构建和部署应用程序到 JBoss EAP 7 的构件和依赖关系存放在公用资料库。从 JBoss EAP 7 开始,构建 quickstarts 不再需要配置 settings.xml 来使用这些资料库。现在是通过 Quickstart 项目的 POM 文件来配置 Maven 资料库。这种方式让 Quickstart 更易于使用,然而,我们通常不建议将其用于产品项目,因为这会拖慢构建过程。
Red Hat JBoss Developer Studio 包含了 Maven,所以不需要单独下载和安装。我们推荐您使用 JBoss Developer Studio version 11.0 或更新的版本。
如果您计划用 Maven 命令行来构建和部署应用程序,您必须先从 Apache Maven 项目下载 Maven 并根据 Maven 文档里的说明安装它。
3.3.3. 下载和运行 Quickstarts
3.3.3.1. 下载 Quickstarts
JBoss EAP 带有详尽的 quickstart 示例代码以帮助用户开始用不同的 Java EE 7 技术编写应用程序。您可以从 Red Hat 客户门户网站下载 Quickstarts 例程。
- 登录 Red Hat 客户门户。
- 点击 Downloads。
- 在 Product Downloads 列表里,点击 Red Hat JBoss Enterprise Application Platform。
- 从 Version 下拉菜单里选择 7.1。
- 在表里找到 Red Hat JBoss Enterprise Application Platform 7.1.0 Quickstarts 条目并点击 Download。
- 将 ZIP 保存到想要的位置。
- 解压 ZIP 归档文件。
3.3.3.2. 在 Red Hat JBoss Developer Studio 里运行 Quickstarts
在下载了 Quickstarts 例程后,它们可以导入到 JBoss Developer Studio 并部署至 JBoss EAP。
将 Quickstarts 导入至 JBoss Developer Studio
每个 Quickstart 都附带一个 POM(Project Object Model)文件,它包含这个 Quickstart 的项目和配置信息。用这个 POM 文件,您可以轻松地将 Quickstart 导入到 Red Hat JBoss Developer Studio 里。
在导入到 Red Hat JBoss Developer Studio 时,如果您的 Quickstart 项目文件夹位于 IDE 工作区里,IDE 会生成一个无效的项目名及 WAR 归档名。在开始导入之前,请确定您的 Quickstart 项目文件夹在 IDE 工作区之外。
- 启动 JBoss Developer Studio。
- 选择 File → Import。
选择 Maven → Existing Maven Projects,然后点击 Next。
图 3.1. 导入现有的 Maven 项目

浏览要操作的 Quickstart 目录(例如
helloworldquickstart),然后点击 OK。 Projects 列表框将用所选的 Quickstart 项目的pom.xml文件填充。图 3.2. 选择 Maven 项目

- 点击 Finish。
运行 helloworld Quickstart
运行 helloworld quickstart 是检验 JBoss EAP 服务器是否配置和运行正常的简易方法。
- 如果您还没有定义服务器,请添加 JBoss EAP 服务器至 JBoss Developer Studio。请参考《JBoss Developer Studio 工具入门指南》中的使用运行时检测从 IDE 内部设置 JBoss EAP。
右击 Project Explorer 标签页里的 helloworld 项目并选择 Run As → Run on Server。
图 3.3. Run As - Run on Server

从服务器列表选择 JBoss EAP 7.1 服务器并点击 Next。
图 3.4. 在服务器上运行

helloworld quickstart 已经列出在服务器进行配置。点击 Finish 部署这个 quickstart。
图 3.5. 修改服务器上配置的资源

检验结果。
-
在 Server 标签页里,JBoss EAP 7.1 服务器的状态已改为
Started。 Console 标签页显示了详述 JBoss EAP 服务器启动和
helloworldquickstart 部署的信息。WFLYUT0021: Registered web context: /helloworld WFLYSRV0010: Deployed "helloworld.war" (runtime-name : "helloworld.war")
-
helloworld应用程序可通过 http://localhost:8080/helloworld 访问,它会显示文本Hello World!。
-
在 Server 标签页里,JBoss EAP 7.1 服务器的状态已改为
有关 helloworld quickstart 的更多信息,请参考探讨 helloworld Quickstart 例程。
运行 bean-validation Quickstart
某些 Quickstarts 例程,如 bean-validation,不会提供用户界面层而是用 Arquillian 测试来演示功能。
-
导入
bean-validationquickstart 至 JBoss Developer Studio。 - 在 Servers 标签页,右击服务器并选择 Start 以启动 JBoss EAP 服务器。如果您没有看到 Servers 标签页或还没有定义服务器,请添加 JBoss EAP 服务器至 JBoss Developer Studio。请参考《JBoss Developer Studio 工具入门指南》中的使用运行时检测从 IDE 内部设置 JBoss EAP。
-
右击 Project Explorer 标签页里的
bean-validation项目并选择 Run As → Maven Build。 在 Goals 字段输入下列内容并点击 Run。
clean verify -Parq-remote
图 3.6. 编辑配置

检验结果。
Console 标签页显示了
bean-validationArquillian 测试的结果:------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.jboss.as.quickstarts.bean_validation.test.MemberValidationTest Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.189 sec Results : Tests run: 5, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
3.3.3.3. 用命令行运行 Quickstarts
您可以轻易地从命令行用 Maven 构建和部署 Quickstarts。如果您还没有安装 Maven,请参考 Apache Maven 项目来下载并安装它。
Quickstarts 的根目录提供了一个 README.md 文件,它包含关于系统要求、配置 Maven、添加用户和运行 Quickstarts 的普通信息。
每个 Quickstart 也包含自己的 README.md 文件,它提供运行这个 Quickstart 的专门的说明及 Maven 命令。
从命令行运行 helloworld Quickstart
-
复查 helloworld quickstart 根目录里的
README.md文件。 启动 JBoss EAP 服务器。
$ EAP_HOME/bin/standalone.sh- 进入 helloworld quickstart 目录。
用
README.md文件里提供的 Maven 命令构建和部署 Quickstart。$ mvn clean install wildfly:deploy
-
helloworld 应用程序可通过 http://localhost:8080/helloworld 访问并显示文本
Hello World!。
3.4. 检查 Quickstart 例程
3.4.1. 探讨 helloworld Quickstart 例程
helloworld quickstart 显示了如何将简单的 servlet 部署至 JBoss EAP。业务逻辑被涵盖在服务之中,作为 Contexts and Dependency Injection (CDI) bean 提供,并被注入 Servlet。此 quickstart 是确保正确配置和启动服务器的起点。
有关使用命令行来构建和部署此 quickstart 的详细说明,请参考 helloworld quickstart 根目录中的 README.html 文件。本主题介绍如何使用 Red Hat JBoss Developer Studio 来运行 quickstart,并假定您已安装 Red Hat JBoss Developer Studio、配置 Maven、导入并成功运行 helloworld quickstart。
前提条件
- 安装 JBoss Developer Studio。有关说明,请参考《JBoss Developer Studio 安装指南》中的使用安装程序安装 JBoss Developer Studio Stand-alone 。
-
运行
helloworldquickstart。有关说明,请参考在 JBoss Developer Studio 里运行 Quickstarts。 -
打开 web 浏览器,访问 http://localhost:8080/helloworld 中的应用程序来验证
helloworldquickstart 是否已成功部署至 JBoss EAP。
检查目录结构
helloworld quickstart 的代码可在 QUICKSTART_HOME/helloworld/ 目录中找到。helloworld quickstart 由一个 Servlet 和一个 CDI bean 构成。它还包括一个 beans.xml 文件(位于应用程序的 WEB-INF/ 目录中),版本号为 1.1,以及一个 bean-discovery-mode(模式为 all)。这个标记文件将 WAR 识别为 bean 归档,指示 JBoss EAP 在本应用程序中查找 bean 和激活 CDI。
src/main/webapp/ 目录中包含 quickstart 文件。本示例的所有配置文件都位于 src/main/webapp/ 中 WEB-INF/ 目录中,其中包括 beans.xml 文件。src/main/webapp/ 目录中还包含 index.html 文件,它使用简单的 meta 刷新将用户的浏览器重定向到 Servlet,位于 http://localhost:8080/helloworld/HelloWorld。quickstart 不需要 web.xml 文件。
检查代码
这些列表里已经排除了软件包声明和导入。Quickstart 源代码里有完整的列表。
检查
HelloWorldServlet代码。HelloWorldServlet.java文件位于src/main/java/org/jboss/as/quickstarts/helloworld/目录。这个 servlet 发送信息至浏览器。示例:HelloWorldServlet 类别代码
42 @SuppressWarnings("serial") 43 @WebServlet("/HelloWorld") 44 public class HelloWorldServlet extends HttpServlet { 45 46 static String PAGE_HEADER = "<html><head><title>helloworld</title></head><body>"; 47 48 static String PAGE_FOOTER = "</body></html>"; 49 50 @Inject 51 HelloService helloService; 52 53 @Override 54 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 55 resp.setContentType("text/html"); 56 PrintWriter writer = resp.getWriter(); 57 writer.println(PAGE_HEADER); 58 writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>"); 59 writer.println(PAGE_FOOTER); 60 writer.close(); 61 } 62 63 }表 3.1. HelloWorldServlet 的细节
行数 备注 43
您只需要添加
@WebServlet注解,并提供一个映射到用于访问 servlet 的 URL。46-48
每个网页都需要正确的 HTML 格式。这个 Quickstart 使用了静态字符串编写最小的页头和页尾输出。
50-51
这些行会注入生成实际消息的 HelloService CDI bean。只要我们不更改 HelloService 的 API,此方法可让我们日后在不更改视图层的情况下更改 HelloService 实现。
58
这一行调用服务以生成 "Hello World" 信息,然后写入 HTTP 请求。
检查
HelloService代码。HelloService.java文件位于src/main/java/org/jboss/as/quickstarts/helloworld/目录中。此服务只是返回消息。无需 XML 或注解注册。示例:HelloService 类别代码
公共类 HelloService { String createHelloMessage(String name) { return "Hello " + name + "!"; } }
3.4.2. 探讨 numberguess Quickstart 例程
numberguess quickstart 显示了如何创建简单的非持久性应用程序并将其部署到 JBoss EAP。信息通过 JSF 视图显示,业务逻辑被涵盖在两个 CDI bean 中。在 numberguess quickstart 中,您拥有 10 次机会,可以猜选 1 到 100 之间的数字。每次猜选之后,系统会告知您数字是过高还是过低。
numberguess quickstart 的代码位于 QUICKSTART_HOME/numberguess/ 目录中,QUICKSTART_HOME 目录是您下载和解压 JBoss EAP quickstart 的位置。numberguess quickstart 由多个 bean、配置文件和 Facelets (JSF) 视图组成,封装成为 WAR 模块。
有关使用命令行来构建和部署此 quickstart 的详细说明,请参考 numberguess quickstart 根目录中的 README.html 文件。以下示例使用 Red Hat JBoss Developer Studio 来运行 quickstart。
前提条件
- 安装 JBoss Developer Studio。有关说明,请参考《JBoss Developer Studio 安装指南》中的使用安装程序安装 JBoss Developer Studio Stand-alone 。
-
运行
numberguessquickstart。有关说明,请参考在 JBoss Developer Studio 里运行 Quickstarts,并用说明中的numberguess代替helloworld。 -
打开 web 浏览器,访问在此 URL: http://localhost:8080/numberguess 中的应用程序来验证
numberguessquickstart 是否已成功部署至 JBoss EAP。
检查配置文件
本示例的所有配置文件都位于 quickstart 的 QUICKSTART_HOME/numberguess/src/main/webapp/WEB-INF/ 目录中。
检查
faces-config.xml文件。这个 quickstart 使用 JSF 2.2 版本的
faces-config.xml文件名。标准版 Facelets 是 JSF 2.2 中默认的视图处理程序,因此无需配置。本文件只包含根元素,仅作为标记文件,用于指示应当在应用程序中启用 JSF。<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"> </faces-config>检查
beans.xml文件。beans.xml文件包含 1.1 版本号和bean-discovery-mode(模式为all)。这个文件是标记文件,将 WAR 识别为 bean 归档,指示 JBoss EAP 在本应用程序中查找 bean 和激活 CDI。<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans>
这个 quickstart 不需要 web.xml 文件。
3.4.2.1. 检查 JSF 代码
JSF 将 .xhtml 文件扩展应用于源文件,但使用 .jsf 扩展来提供渲染视图。home.xhtml 文件位于 src/main/webapp/ 目录中。
示例:JSF 源代码
19<html xmlns="http://www.w3.org/1999/xhtml"
20 xmlns:ui="http://java.sun.com/jsf/facelets"
21 xmlns:h="http://java.sun.com/jsf/html"
22 xmlns:f="http://java.sun.com/jsf/core">
23
24 <head>
25 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
26 <title>Numberguess</title>
27 </head>
28
29 <body>
30 <div id="content">
31 <h1>Guess a number...</h1>
32 <h:form id="numberGuess">
33
34 <!-- Feedback for the user on their guess -->
35 <div style="color: red">
36 <h:messages id="messages" globalOnly="false" />
37 <h:outputText id="Higher" value="Higher!"
38 rendered="#{game.number gt game.guess and game.guess ne 0}" />
39 <h:outputText id="Lower" value="Lower!"
40 rendered="#{game.number lt game.guess and game.guess ne 0}" />
41 </div>
42
43 <!-- Instructions for the user -->
44 <div>
45 I'm thinking of a number between <span
46 id="numberGuess:smallest">#{game.smallest}</span> and <span
47 id="numberGuess:biggest">#{game.biggest}</span>. You have
48 #{game.remainingGuesses} guesses remaining.
49 </div>
50
51 <!-- Input box for the users guess, plus a button to submit, and reset -->
52 <!-- These are bound using EL to our CDI beans -->
53 <div>
54 Your guess:
55 <h:inputText id="inputGuess" value="#{game.guess}"
56 required="true" size="3"
57 disabled="#{game.number eq game.guess}"
58 validator="#{game.validateNumberRange}" />
59 <h:commandButton id="guessButton" value="Guess"
60 action="#{game.check}"
61 disabled="#{game.number eq game.guess}" />
62 </div>
63 <div>
64 <h:commandButton id="restartButton" value="Reset"
65 action="#{game.reset}" immediate="true" />
66 </div>
67 </h:form>
68
69 </div>
70
71 <br style="clear: both" />
72
73 </body>
74</html>
下列行编号与在 JBoss Developer Studio 中查看文件时显示的编号对应。
表 3.2. JSF 详情
| 行数 | 备注 |
|---|---|
|
36-40 |
这是发送给用户的信息:"Higher!" 和 "Lower!" |
|
45-48 |
随着用户不断猜选,他们能够猜选的数字范围会逐渐缩小。本句更改以确保他们知道有效的数字猜选范围。 |
|
55-58 |
这个输入字段绑定一个使用值表达式的 Bean 属性。 |
|
58 |
使用验证程序绑定,确保用户不会意外输入猜选范围以外的数字。如果未采用验证程序,用户可能使用猜选范围外的数值。 |
|
59-61 |
必须为用户提供将猜选值发送至服务器的方法。此处我们绑定 bean 上的操作方法。 |
3.4.2.2. 检查类文件
所有的 numberguess quickstart 源文件都可在 QUICKSTART_HOME/numberguess/src/main/java/org/jboss/as/quickstarts/numberguess/ 目录中找到。这些列表中已经排除了软件包声明和导入。quickstart 源代码中有完整的列表。
检查
Random.java限定词码限定词用于消除两个 bean 之间的歧义,这两个 bean 都能基于其类型进行注入。有关限定词的详细信息,请参考《JBoss EAP 开发指南》中的使用限定词解析模糊注入。
@Random限定词用于注入随机数。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface Random { }检查
MaxNumber.java限定词码@MaxNumber限定词用于注入允许的最大数。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface MaxNumber { }检查
Generator.java代码Generator类别通过生产方法创建随机数,以同样的方式给出可能的最大数值。此类别属于应用程序范围,所以您不会每次得到不同的随机数。@SuppressWarnings("serial") @ApplicationScoped public class Generator implements Serializable { private java.util.Random random = new java.util.Random(System.currentTimeMillis()); private int maxNumber = 100; java.util.Random getRandom() { return random; } @Produces @Random int next() { // a number between 1 and 100 return getRandom().nextInt(maxNumber - 1) + 1; } @Produces @MaxNumber int getMaxNumber() { return maxNumber; } }检查
Game.java代码属于会话范围的
Game类别是该应用程序的主要入口点。它负责设置或重新设置游戏、获取和验证用户的猜选,并利用FacesMessage向用户提供反馈。它使用构建后生命周期方法初始化游戏,从@Random Instance<Integer>bean 检索随机数。注意此类别中的
@Named注解。只有在您想要使用表达式语言 (EL)(本例中为#{game})使 bean 可由 JSF 视图访问时,才会需要此注解。@SuppressWarnings("serial") @Named @SessionScoped public class Game implements Serializable { /** * The number that the user needs to guess */ private int number; /** * The users latest guess */ private int guess; /** * The smallest number guessed so far (so we can track the valid guess range). */ private int smallest; /** * The largest number guessed so far */ private int biggest; /** * The number of guesses remaining */ private int remainingGuesses; /** * The maximum number we should ask them to guess */ @Inject @MaxNumber private int maxNumber; /** * The random number to guess */ @Inject @Random Instance<Integer> randomNumber; public Game() { } public int getNumber() { return number; } public int getGuess() { return guess; } public void setGuess(int guess) { this.guess = guess; } public int getSmallest() { return smallest; } public int getBiggest() { return biggest; } public int getRemainingGuesses() { return remainingGuesses; } /** * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. Give feedback to the user * if they are correct. */ public void check() { if (guess > number) { biggest = guess - 1; } else if (guess < number) { smallest = guess + 1; } else if (guess == number) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!")); } remainingGuesses--; } /** * Reset the game, by putting all values back to their defaults, and getting a new random number. We also call this method * when the user starts playing for the first time using {@linkplain PostConstruct @PostConstruct} to set the initial * values. */ @PostConstruct public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } /** * A JSF validation method which checks whether the guess is valid. It might not be valid because there are no guesses left, * or because the guess is not in range. * */ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) { if (remainingGuesses <= 0) { FacesMessage message = new FacesMessage("No guesses left!"); context.addMessage(toValidate.getClientId(context), message); ((UIInput) toValidate).setValid(false); return; } int input = (Integer) value; if (input < smallest || input > biggest) { ((UIInput) toValidate).setValid(false); FacesMessage message = new FacesMessage("Invalid guess"); context.addMessage(toValidate.getClientId(context), message); } } }

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.