练习 - 将 Jakarta EE 应用程序部署到 Azure 应用服务上的 JBoss EAP
在本单元中,你将一个 Jakarta EE 应用程序部署到 Azure 应用服务上的 Red Hat JBoss Enterprise 应用程序平台(JBoss EAP)。 使用适用于 Azure 应用服务的 Maven 插件来配置项目、编译和部署应用程序,以及配置数据源。
配置应用
使用适用于 Azure 应用服务的 Maven 插件配置应用,请执行以下步骤:
使用以下命令以交互方式运行 Azure 插件的配置目标:
./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.13.0:config
重要
如果更改 MySQL 服务器的区域,则应将该区域与 Jakarta EE 应用程序服务器的区域匹配,以最大程度地减少延迟延迟。
使用下表中的值回答交互式提示:
输入元素 价值 Create new run configuration (Y/N) [Y]:
Y
Define value for OS [Linux]:
Linux
Define value for javaVersion [Java 17]:
1: Java 17
Define value for runtimeStack:
3: Jbosseap 7
Define value for pricingTier [P1v3]:
P1v3
Confirm (Y/N) [Y]:
Y
以下输出是典型的:
[INFO] Saving configuration to pom. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 03:00 min [INFO] Finished at: 2025-02-21T06:24:11+09:00 [INFO] ------------------------------------------------------------------------
使用 Maven 命令后,以下示例是 Maven pom.xml 文件的典型补充:
<build> <finalName>ROOT</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.4.0</version> </plugin> <plugin> <groupId>com.microsoft.azure</groupId> <artifactId>azure-webapp-maven-plugin</artifactId> <version>2.13.0</version> <configuration> <schemaVersion>v2</schemaVersion> <resourceGroup>jakartaee-app-on-jboss-rg</resourceGroup> <appName>jakartaee-app-on-jboss</appName> <pricingTier>P1v3</pricingTier> <region>centralus</region> <runtime> <os>Linux</os> <javaVersion>Java 17</javaVersion> <webContainer>Jbosseap 7</webContainer> </runtime> <deployment> <resources> <resource> <directory>${project.basedir}/target</directory> <includes> <include>*.war</include> </includes> </resource> </resources> </deployment> </configuration> </plugin> </plugins> </build>
检查
<region>
文件中的元素。 如果其值与 MySQL 的安装位置不匹配,请将其更改为同一位置。使用以下示例在 Azure 应用服务上的 JBoss EAP 8 环境中,将
webContainer
文件中的 值修改为Jbosseap 8
。小窍门
截至 2025 年 2 月,JBoss EAP 的最新可用版本为 8.0 Update 4.1。
<runtime> <os>Linux</os> <javaVersion>Java 17</javaVersion> <webContainer>Jbosseap 8</webContainer> <!-- Change this value --> </runtime>
将以下 XML 添加到
<resources>
文件的 元素。 此配置用于部署启动文件,稍后在本单元中更新该文件。<resource> <type>startup</type> <directory>${project.basedir}/src/main/webapp/WEB-INF/</directory> <includes> <include>createMySQLDataSource.sh</include> </includes> </resource>
资源
<type>
值为startup
时,会将指定的脚本部署为 startup.sh 文件(适用于 Linux)或 startup.cmd 文件(适用于 Windows)。 部署位置为 /home/site/scripts/。注释
可以通过以下方法之一指定
type
部署选项和部署位置:- 如果未指定
type=war
,则将 WAR 文件部署到path
。 type=war&path=webapps/<appname>
将 WAR 文件部署到 /home/site/wwwroot/webapps/<appname>。type=jar
将 WAR 文件部署到 /home/site/wwwroot/app.jar。 忽略path
参数。type=ear
将 WAR 文件部署到 /home/site/wwwroot/app.ear。 忽略path
参数。type=lib
将 JAR 部署到 /home/site/libs。 必须指定path
参数。type=static
将脚本部署到 /home/site/scripts。 必须指定path
参数。type=startup
在 Linux 上部署脚本为 startup.sh,或在 Windows 上部署为 startup.cmd。 该脚本部署到 /home/site/scripts/。 忽略path
参数。type=zip
将 .zip 文件解压缩到 /home/site/wwwroot。path
参数是可选的。
- 如果未指定
请检查
resourceGroup
和appName
元素在 pom.xml 文件中的值。使用以下命令将
resourceGroup
和appName
的值分配给环境变量:export RESOURCE_GROUP_NAME=<resource-group> export WEB_APP_NAME=<app-name>
编译并生成 Jakarta EE 应用
配置 Azure 应用服务部署设置后,使用以下命令编译和打包源代码:
./mvnw clean package
以下输出是典型的:
[INFO] --- war:3.4.0:war (default-war) @ jakartaee-app-on-jboss ---
[INFO] Packaging webapp
[INFO] Assembling webapp [jakartaee-app-on-jboss] in [/private/tmp/mslearn-jakarta-ee-azure/target/ROOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/private/tmp/mslearn-jakarta-ee-azure/src/main/webapp]
[INFO] Building war: /private/tmp/mslearn-jakarta-ee-azure/target/ROOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.881 s
[INFO] Finished at: 2025-02-21T06:32:30+09:00
[INFO] ------------------------------------------------------------------------
将 Jakarta EE 应用部署到 Azure 应用服务上的 JBoss EAP
编译并打包代码后,使用以下命令部署应用程序:
./mvnw azure-webapp:deploy
应会看到包含成功消息和已部署应用程序的 URL 的输出。 请务必将 URL 保存为以后使用。
配置数据库连接
示例应用程序连接到 MySQL 数据库并显示数据。 pom.xml 文件中的 Maven 项目配置指定 MySQL JDBC 驱动程序,如以下示例所示:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-jdbc-driver}</version>
</dependency>
因此,JBoss EAP 会自动将 JDBC 驱动程序 ROOT.war_com.mysql.cj.jdbc.Driver_9_2
安装到部署包 ROOT.war。
在 JBoss EAP 中创建 MySQL DataSource 对象
若要访问 Azure Database for MySQL,需要在 JBoss EAP 中配置 DataSource
对象,并在源代码中指定 Java 命名和目录接口(JNDI)名称。 若要在 JBoss EAP 中创建 MySQL DataSource
对象,请使用 /WEB-INF/createMySQLDataSource.sh 启动 shell 脚本。 以下示例演示 Azure 应用服务中已存在脚本的未配置版本:
#!/bin/bash
# In order to use the variables in CLI scripts
# https://access.redhat.com/solutions/321513
sed -i -e "s|.*<resolve-parameter-values.*|<resolve-parameter-values>true</resolve-parameter-values>|g" /opt/eap/bin/jboss-cli.xml
/opt/eap/bin/jboss-cli.sh --connect <<EOF
data-source add --name=JPAWorldDataSourceDS \
--jndi-name=java:jboss/datasources/JPAWorldDataSource \
--connection-url=${AZURE_MYSQL_CONNECTIONSTRING}&characterEncoding=utf8&sslMode=REQUIRED&serverTimezone=UTC&authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin \
--driver-name=ROOT.war_com.mysql.cj.jdbc.Driver_9_2 \
--min-pool-size=5 \
--max-pool-size=20 \
--blocking-timeout-wait-millis=5000 \
--enabled=true \
--driver-class=com.mysql.cj.jdbc.Driver \
--jta=true \
--use-java-context=true \
--valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker \
--exception-sorter-class-name=com.mysql.cj.jdbc.integration.jboss.ExtendedMysqlExceptionSorter
exit
EOF
注释
创建数据源时,不指定 MySQL 连接的密码。 环境变量AZURE_MYSQL_CONNECTIONSTRING
在参数--connection-url
中指定。 稍后创建服务连接时,会自动设置此环境变量。
服务连接值设置为 jdbc:mysql://$MYSQL_SERVER_INSTANCE.mysql.database.azure.com:3306/world?serverTimezone=UTC&sslmode=required&user=aad_jbossapp
,使用用户名而不使用 aad_jbossapp
密码。
通过追加 &authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin
到此 URL,Microsoft为用户启用 aad_jbossapp
Entra ID 身份验证。
使用以下命令配置应用服务实例以调用启动脚本:
az webapp config set \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${WEB_APP_NAME} \
--startup-file '/home/site/scripts/startup.sh'
脚本运行后,应用程序服务器会在每次重新启动应用程序服务器时调用它。
注释
如果部署项目不是 ROOT.war,则还更改 --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_9_2
值。
为 MySQL 灵活服务器配置服务连接
配置启动脚本后,使用以下步骤将应用服务配置为使用 Service Connector 进行 MySQL 灵活服务器连接:
使用以下命令设置环境变量:
export PASSWORDLESS_USER_NAME_SUFFIX=jbossapp export SOURCE_WEB_APP_ID=$(az webapp list \ --resource-group $RESOURCE_GROUP_NAME \ --query "[0].id" \ --output tsv) export MYSQL_ID=$(az mysql flexible-server list \ --resource-group $RESOURCE_GROUP_NAME \ --query "[0].id" \ --output tsv) export TARGET_MYSQL_ID=$MYSQL_ID/databases/world export MANAGED_ID=$(az identity list \ --resource-group $RESOURCE_GROUP_NAME \ --query "[0].id" \ --output tsv)
环境变量用于以下目的:
PASSWORDLESS_USER_NAME_SUFFIX
是用于连接到 MySQL 灵活服务器的用户名的后缀。 创建的用户名具有前缀aad_
,后跟指定的后缀。SOURCE_WEB_APP_ID
是用于连接到 MySQL 灵活服务器的 Azure 应用服务实例的 ID。MYSQL_ID
是 MySQL 灵活服务器的 ID。TARGET_MYSQL_ID
指定数据库名称$MYSQL_ID/databases/world
,以便与有权访问world
数据库的用户建立连接。MANAGED_ID
是用于连接到 MySQL 灵活服务器的托管标识。
使用以下命令添加扩展
serviceconnector-passwordless
并创建服务连接:az extension add \ --name serviceconnector-passwordless \ --upgrade az webapp connection create mysql-flexible \ --resource-group ${RESOURCE_GROUP_NAME} \ --connection $PASSWORDLESS_USER_NAME_SUFFIX \ --source-id $SOURCE_WEB_APP_ID \ --target-id $TARGET_MYSQL_ID \ --client-type java \ --system-identity mysql-identity-id=$MANAGED_ID
注释
如果收到类似
Resource '********-****-****-****-************' does not exist or one of its queried reference-property objects are not present.
错误消息,请在几秒钟后重新运行该命令。在 SQL 提示符下,使用以下查询检查在 MySQL 中注册的用户列表:
SELECT user, host, plugin FROM mysql.user;
以下输出是典型的:
+----------------------------------+-----------+-----------------------+ | user | host | plugin | +----------------------------------+-----------+-----------------------+ | aad_jbossapp | % | aad_auth | | azureuser | % | mysql_native_password | | $CURRENT_AZ_LOGIN_USER_NAME#EXT#@| % | aad_auth | | azure_superuser | 127.0.0.1 | mysql_native_password | | azure_superuser | localhost | mysql_native_password | | mysql.infoschema | localhost | caching_sha2_password | | mysql.session | localhost | caching_sha2_password | | mysql.sys | localhost | caching_sha2_password | +----------------------------------+-----------+-----------------------+ 8 rows in set (2.06 sec)
应该会看到使用
aad_jbossapp
插件的aad_auth
用户。 在 Azure 上部署的 JBoss EAP 中,可以使用用户名(无需密码)连接到 MySQL 灵活服务器aad_jbossapp
。
确认代码中的 DataSource 引用
若要从应用程序访问 MySQL 数据库,需要在应用程序项目中配置数据源引用。
数据库访问代码是使用 Java 持久性 API (JPA) 实现的。 引用的配置 DataSource
位于 JPA 配置文件 persistence.xml中。
使用以下步骤确认 DataSource
引用:
打开 src/main/resources/META-INF/persistence.xml 文件,并检查名称是否
DataSource
与配置中使用的名称匹配。 启动脚本已创建java:jboss/datasources/JPAWorldDataSource
JNDI 名称,如以下示例所示:<persistence-unit name="JPAWorldDatasourcePU" transaction-type="JTA"> <jta-data-source>java:jboss/datasources/JPAWorldDataSource</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="hibernate.generate_statistics" value="true" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> </properties> </persistence-unit>
访问单元名称中的
PersistenceContext
MySQL 数据库,如以下示例所示:@Transactional(REQUIRED) @RequestScoped public class CityService { @PersistenceContext(unitName = "JPAWorldDatasourcePU") EntityManager em;
访问应用程序
示例应用程序实现三个 REST 终结点。 若要访问应用程序和检索数据,请使用以下步骤:
练习摘要
在本单元中,你验证了应用程序 REST 终结点,并确认应用程序可以从 MySQL 数据库获取数据。 在下一个单元中,你将检查服务器日志。