2.5. 回顾快速启动示例
2.5.1. 浏览 helloworld 快速启动
helloworld
快速入门演示了如何将简单的 Servlet 部署到 JBoss EAP。业务逻辑封装在服务中,作为上下文和依赖注入(CDI) Bean 提供,并注入到 Servlet 中。此快速入门是一个起点,可确保您已正确配置和启动服务器。
使用命令行构建和部署此快速启动的详细说明,请参见 helloworld
快速启动目录根目录下的 README.html
文件。本主题展示了如何使用 JBoss 工具来运行快速启动,并假设您已安装了 JBoss 工具、配置了 Maven,导入并成功运行了 helloworld
快速启动。
JBoss 工具在 JBoss EAP 8.0 中已弃用。不会对这个功能进行任何增强,它可能会在以后的版本中删除。
2.5.1.1. 检查目录结构
helloworld
快速启动的代码可以在 QUICKSTART_HOME/helloworld/
目录中找到。helloworld
快速启动由 Servlet 和一个 CDI bean 组成。它还包含应用的 WEB-INF/
目录中的 beans.xml
文件,其版本号为 1.1,并且 bean-discovery-mode
是 all
。此标志文件将 WAR 识别为 bean 存档,并告知 JBoss EAP 在此应用程序中查找 bean ,并激活 CDI。
src/main/webapp/
目录包含快速启动的文件。本例的所有配置文件都位于 src/main/webapp/
中的 WEB-INF/
目录中, 包括 beans.xml
文件。src/main/webapp/
目录还包括 index.html
文件,该文件使用简单的 meta refresh 将用户的浏览器重定向到 Servlet,它位于 http://localhost:8080/helloworld/HelloWorld。quickstart 不需要 web.xml
文件。
2.5.1.2. 回顾 HelloWorldServlet.java
代码
软件包声明和导入已从这些列表中排除。Quickstart 源代码中提供了完整的列表。
JBoss 工具在 JBoss EAP 8.0 中已弃用。不会对这个功能进行任何增强,它可能会在以后的版本中删除。
先决条件
- 安装 JBoss 工具。具体说明请查看 JBoss 工具安装指南中的 安装方法 。
-
运行
helloworld
快速入门。 -
打开 Web 浏览器并在 http://localhost:8080/helloworld 访问应用,以验证
helloworld
quickstart 已成功部署到 JBoss EAP。
流程
查看
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 }
2.5.1.2.1. HelloWorldServlet
详情
此 servlet 会向您的浏览器发送信息。
行 | 备注 |
---|---|
43 |
您只需要添加 |
46-48 | 每个网页都需要正确构成 HTML。这个快速入门使用静态字符串来编写最小标头和页脚输出。 |
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 类代码
public class HelloService { String createHelloMessage(String name) { return "Hello " + name + "!"; } }
其他资源
- 有关测试的 JBoss 工具版本的更多信息,请参阅 Red Hat JBoss Enterprise Application Platform (EAP)和 JBoss 工具。
2.5.2. 探索 numberguess 快速启动
numberguess
快速启动演示了如何将简单的非持久性应用创建和部署至 JBoss EAP。使用 JSF 视图显示信息,业务逻辑被封装到两个 CDI bean 中。在 numberguess
快速启动中,您有十次尝试猜测 1 到 100 之间的数字。在每次尝试后,您都会被告知您的猜测过高还是过低。
numberguess
Quickstart 的代码可以在 QUICKSTART_HOME/numberguess/
目录中找到,其中 QUICKSTART_HOME
是您下载并解压缩 JBoss EAP 快速入门的目录。numberguess
快速启动由多个 bean、配置文件和 Facelets (JSF)视图组成,并被打包为 WAR 模块。
使用命令行构建和部署此快速启动的详细说明,请参阅 numberguess
quickstart 目录的 README.html
文件。以下示例使用 JBoss 工具来运行快速启动。
JBoss 工具在 JBoss EAP 8.0 中已弃用。不会对这个功能进行任何增强,它可能会在以后的版本中删除。
2.5.2.1. 检查 numberguess
配置文件
本例的所有配置文件都位于 QUICKSTART_HOME/numberguess/src/main/webapp/WEB-INF/
目录中。
先决条件
- 安装 JBoss 工具。具体说明请查看 JBoss 工具安装指南中的 安装方法 。
-
运行
numberguess
Quickstart。 -
打开 Web 浏览器并访问 URL http://localhost:8080/numberguess 来访问这个应用,以验证
numbergues
quickstart 已成功部署到 JBoss EAP。
JBoss 工具在 JBoss EAP 8.0 中已弃用。不会对这个功能进行任何增强,它可能会在以后的版本中删除。
流程
检查
face-config.xml
文件。该快速启动使用
faces-config.xml
文件名的 JSF 2.2 版本。Facelets 的标准化版本是 JSF 2.2 中的默认视图处理程序,因此不需要配置。此文件仅包含 root 元素,只是指示应用中应启用 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>
此快速入门不需要 web.xml
文件。
其他资源
- 有关测试的 JBoss 工具版本的更多信息,请参阅 Red Hat JBoss Enterprise Application Platform (EAP)和 JBoss 工具。
2.5.2.2. 检查 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 工具中查看文件时看到的行号相对应。
JBoss 工具在 JBoss EAP 8.0 中已弃用。不会对这个功能进行任何增强,它可能会在以后的版本中删除。
行 | 备注 |
---|---|
36-40 | 这些消息可以发送给用户:"Higher!"和"Lower!"。 |
45-48 | 用户猜测,可以猜到的数字范围会较小。这一句子会改变,确保他们知道有效猜测的范围。 |
55-58 | 此输入字段绑定至使用值表达式的 bean 属性。 |
58 | 验证器绑定用于确保用户不会意外输入他们可能猜到的范围之外的数字。如果验证器不在此处,用户可能会对不限号使用一个猜测。 |
59-61 | 必须有办法让用户将其猜测发送到服务器。在这里,我们绑定了 Bean 的操作方法。 |
2.5.2.3. 检查 numberguess
类文件
所有 numberguess
快速启动源文件都可在 QUICKSTART_HOME/numberguess/src/main/java/org/jboss/as/quickstarts/numberguess/
目录中找到。软件包声明和导入已从这些列表中排除。Quickstart 源代码中提供了完整的列表。
流程
查看
Random.java
Qualifier Code限定符用于消除两个 Bean 之间的不确定性,两者都有资格根据其类型注入。
@Random
限定符用于注入随机数字。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface Random { }
查看
MaxNumber.java
Qualifier Code@MaxNumber
qualifier
用于注入允许的最大数量。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface MaxNumber { }
查看
Generator.java
CodeGenerator
类通过制作者方法创建随机数,并通过相同方式公开可能的最大数量。此类为应用范围,因此每次都不会出现不同的随机值。@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
注释。只有在您希望使用 Jakarta Expression Language (在本例中为#{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); } } }