本教程将逐步介绍如何使用回调异步调用 Oracle Data Integrator (ODI) 以管理 BPEL 流程中长时间运行的 ODI 方案。本教程将演示一个更高级的方法,将 ODI 方案与 Java 服务包装在一起来管理与 BPEL 流程的异步通信。
大约 1 小时 30 分钟
本 OBE 教程包括下列主题:
将鼠标置于此图标上以加载和查看本教程的所有屏幕截图。(警告:此操作会同时加载所有屏幕截图,网速较慢时,响应时间可能会比较长。)
注:此外,您还可以在下列步骤中将鼠标放在每个单独的图标上,从而仅加载和查看与该步骤相关的屏幕截图。
这些屏幕截图不能反映用户的具体环境。只是说明如何在 Oracle Data Integrator 中找到特定功能。
ODI 提供了同步和异步 Web 服务接口供应用程序调用现成的 ODI 方案。目前,ODI 可以异步执行 Web 服务,但当 Web 服务完成时,不能重新引用它成功完成或失败的 ODI 作业和信号。回调引用允许 ODI 异步调用 Web 服务,从而使 Web 服务知道作业完成时从哪里回调 ODI 以发出作业输出信号。如果 BPEL 业务流程使用该接口调用长时间运行的大型 ODI 加载,则同步调用可能超时从而导致 ODI 加载无法完成。在本示例中,您将一个 Java web 服务 (ODIInvokerService) 部署为 BPEL 和 ODI 之间的中介。BPEL 将调用 Java 服务来传递 ODI 方案详细信息,然后 Java 服务通过 ODI API 调用 ODI 加载。当加载完成后,Java 服务通过 BPEL PM 的 Java API 或通过更改 Web 服务调用中的参数来异步回调 BPEL 实例,回调将使用 WS 寻址完成。这样,BPEL 可以与长时间运行的 ODI 加载异步交互。Java 服务按通用方式构建,这样可以从任一 Web 服务进程中调用任何 ODI 方案。
Linda 是 Global Enterprise 的数据库管理员。在 Global Enterprise,Linda 负责执行关于机构内各种资源的数据库管理和集成任务。具体来说,Linda 负责数据的加载、转换和验证。她需要管理 BPEL 流程中长时间运行的 Oracle Data Integrator (ODI) 方案。如果此类 BPEL 业务流程使用该接口调用长时间运行的大型 ODI 加载,则同步调用将超时从而导致 ODI 加载无法完成。因此,Linda 决定使用回调来异步调用 ODI 方案。
在启动任务前,确保您的系统环境满足以下要求:
软件要求
系统应该已安装以下产品:
系统应该包括以下配置:
在本示例的这一部分,您将把 Java 包装服务 ODIInvokerService 部署到 Oracle 应用服务器。要创建新的应用程序并将 ODI 包装服务部署到 Oracle 应用服务器,执行以下步骤:
|
1. |
通过单击 G:\jdevStudio10131 中的 jdeveloper.exe 启动 JDeveloper。或者,使用桌面上的 SOA Suite JDeveloper 快捷方式。如果打开了一个对话框,询问您是否要从 JDeveloper 的早期版本迁移,单击 NO。在左侧的 Applications Navigator 中,右键单击 Applications 并选择 New Application。
|
|
2. |
在打开的窗口中,在 Application Name 域中输入 BPEL2ODIAsync。单击 OK。
|
| 3. |
在显示的 Create project 窗口中,选择 Cancel。BPEL2ODIAsync 应用程序出现在 Applications Navigator 中。
|
| 4. |
从 Main 菜单中选择 File > Open。浏览至 G:\ODIInvokerService_generation2 目录并选择 ODIInvokerService.jpr 文件。单击 Open,ODIInvokerService 将出现在 Applications Navigator 中。 注:此时,您已导入 Java 包装服务 (ODIInvokerService),它将充当 BPEL 和 ODI 之间的中介。建议您花些时间浏览该服务的类和详细信息以了解其工作方式。注意,该 Java 应用程序包含两个接口:同步 Web 服务接口 (ODIAsyncStarterWebService) 和独立的 java 接口 (odi-async-standalone.jar)。您将调用 Web 服务接口,这需要传递回调信息以通过 BPEL API 回调正确的 BPEL 实例并传递 ODI 信息以通过 ODI API 调用正确的 ODI 方案。
|
| 6. |
要配置运行时的库位置,右键单击 Applications Navigator 中的 ODIInvokerService 并选择 Project Properties。在打开的窗口中,从左侧 Explorer 中选择 Libraries。在 Libraries 列表中,选择 Orabpel.jar 库并单击 Edit。在 Edit Library Definition 窗口中,高亮显示当前的 Class Path 值并选择 Remove。
|
| 7. | 高亮显示 Class Path 并选择 Add Entry。浏览至您的 SOA_HOME/bpel/lib 目录 ( E:\SOASuite10131\bpel\lib) 并选择 orabpel.jar(如果您从其他位置获得该库,请确保其版本与所安装的 SOA 套件版本相同)。单击 Select。在 Edit Library Definition 页面中,确保已选中 Deployed By Default 选项并单击 OK。
|
| 8. | 同样,在 Libraries 列表中,选择 Orabpel-common.jar 库并选择 Edit。在窗口中,高亮显示当前的 Class Path 值并选择 Remove,然后高亮显示 Class Path 并选择 Add Entry。浏览至您的 SOA_HOME/bpel/lib 目录 ( E:\SOASuite10131\bpel\lib) 并选择 orabpelcommon.jar(如果您从其他位置获得该库,请确保其版本与所安装的 SOA 套件版本相同)。在 Edit Library Definition 页面中,确保已选中 Deployed By Default 并单击 OK。
|
| 9. | 在 Project Properties 页面中,确保针对这 3 个库都选中了 Export,然后单击 OK。在 Applications Navigator 中,右键单击 ODIInvokerService 并单击 Rebuild。
|
| 10. | 要部署 Java 服务,请确保已在 JDeveloper 中配置了一个到应用服务器的连接,并且该连接已启动并在运行。在 Applications Navigator 中,展开 Applications > BPEL2ODIAsync > ODIInvokerService > Resources。右键单击 WebServices.deploy 并展开 Deploy to,然后选择应用服务器连接(例如 SoademoApplicationServer,如屏幕截图所示)。在显示的所有窗口中选择 OK。Deployment Log 将出现在页面底部,显示一条消息,表明部署已完成,如下所示。
|
| 11. | 要验证服务已部署并可访问,在浏览器中打开 Application Server Control (http://localhost:8888/em/)。使用您的管理员凭证(User name:oc4jadmin,Password:welcome1)登录。在 Enterprise Manager 页面中,选择您在其中部署了 ODIInvokerService (Home JVM) 的 oc4j 容器。在 OC4J Home 页面中,选择 Applications 选项卡。在 Applications 选项卡的 default 下,找到并选择 odi-webservice 应用。
|
| 12. | 在 odi-webservice 页面中,选择 Web Services 选项卡,然后单击 Test Service 按钮。
|
| 13. | 在新页面中,保留默认的 URL 并单击 Test Web Service。单击 Test Service 按钮。ODIAsyncStarterWebservice 页面出现,包含用于调用 ODIInvokerService 的 HTML 表单 以及到 WSDL 服务定义和文档的链接。单击 Service Description 链接。在 JDeveloper 中,从 Main 菜单中选择 File > Save All 保存您的工作。
注:请勿关闭在浏览器页面中打开的最后一个页面,因为在下一部分您将需要使用它复制 WSDL URL 位置。此时,您尚未测试服务,但可看到输入域,该域将用于调用 ODI 方案,然后回调到 BPEL 流程。ODIINvokerService 现在已部署并可以运行了。
|
要创建一个新的 BPEL 流程,执行以下步骤:
|
1. |
在左侧的 Applications navigator 中,右键单击 BPEL2ODIAsync 并选择 New Project。在显示的窗口中,选择 BPEL Process Project,然后单击 OK。
|
|
2. |
在 BPEL Project Creation Wizard 中,将项目命名为 AsyncODICall 并确保已选择 Asynchronous BPEL Process。单击 Next。选择 Input Schema Element 域旁边的手电筒图标。浏览至 OBE_LAB 目录并选择 ODIService.xsd。单击 Open。
|
| 3. |
在 Type Chooser 窗口中,展开 Imported Schemas > ODIService.xsd 并选择 ODIProcessRequest。选择 OK。
|
| 4. |
选择 Output Schema Element 域旁边的手电筒图标。在 Type Chooser 窗口中,展开 Imported Schemas > ODIService.xsd 并选择 ODIProcessResponse。单击 OK。
|
| 5. |
单击 BPEL Project Creation Wizard 中的 Finish。新的 AsyncODICall 项目将在 JDeveloper 主窗口中打开。保存您的项目(从 Main 菜单中选择 File > Save All)。
|
在接下来的步骤中,您将修改默认创建的 BPEL 流程结构,使其包括两个新操作。这两个操作将添加到 WSDL 中的入站端口类型。它们将用于从您先前部署的 ODIInvokerService 接收异步响应。
要更新 BPEL 流程接口,执行以下步骤:
|
1. |
在左侧的 Application Navigator 中,展开 BPEL2ODIAsync > AsyncODICall > Integration Content,双击 AsyncODICall.wsdl 打开。在 AsyncODICall.wsdl 文件中,选择左上角的 Switch View 按钮。在主窗格中打开 AsyncODICall.wsdl 文件,找到结构窗格(您可能需要单击 View > Structure)。展开 Definitions 并右键单击 Messages。单击 Insert message。在该窗口中,将消息命名为 ODIInvokerServiceResponseMessage。选择 OK。
|
| 3. | 右键单击 ODIInvokerServiceResponceMessage,展开 Insert Inside message > ODIInvokerServiceResponseMessage > http://schemas.xmlsoap.org/wsdl/ 并选择 Part。在显示的窗口中,将部件命名为 payload。从 Reference Type 中选择 element。在 Part Type 中输入 ns1:ODIInvokerServiceResponse。单击 OK。
|
| 4. |
同样,在 Structure 窗格中,展开 Definitions 并右键单击 Messages。选择 Insert message。在该窗口中,将消息命名为 ODIInvokerServiceFaultMessage。选择 OK。右键单击 ODIInvokerServiceFaultMessage,展开 Insert Inside message > ODIInvokerServiceFaultMessage >http://schemas.xmlsoap.org/wsdl/ 并选择 Part。将部件命名为 payload,从 Reference Type 中选择 element。在 Part Type 中键入 ns1:ODIInvokerServiceFault。单击 OK。
|
| 5. |
验证您的 AsyncODICall.wsdl 具有如下所示的结构。
|
| 6. |
在 Port Types 下,选择并右键单击 AsyncODICall。展开 Insert Inside AsyncODICall > http://schemas.xmlsoap.org/wsdl/ 并选择 Operation。在显示的窗口中,将操作命名为 onODIResult。从 Operation Type 下拉菜单中选择 One Way。从 Input 下拉菜单中选择 client:ODIInvokerServiceResponseMessage 并单击 OK。 新操作出现在 initiate 下。
|
| 7. | 再次在 Port Types 下,选择并右键单击 AsyncODICall。展开 Insert Inside AsyncODICall > http://schemas.xmlsoap.org/wsdl/ 并选择 Operation。在显示的窗口中,将操作命名为 onODIError。从 Operation Type 下拉菜单中选择 One Way。从 Input 下拉菜单中选择 client:ODIInvokerServiceFaultMessage 并单击 OK。新操作出现在 initiate 下。
|
| 8. | 验证您的 AsyncODICall.wsdl 具有如下所示的结构。保存您的项目(单击 File > Save all)并关闭 AsynchODICall.wsdl 文件。单击 AsynchODICall.bpel 文件选项卡并选择页面顶部的绿色对号按钮。将使用您刚刚所做的更改刷新 BPEL 流程(您可能需要关闭 BPEL 文件再重新打开以使更改生效)。
注:通过创建 onODIResult 和 onODIError 这两个新操作,您现在已经更新了 BPEL 接口。 |
在接下来的步骤中,您将创建一个 BPEL Partner Link 以表示 Java 包装服务 ODIInvokerService。要创建 ODIInvikerService 的 Partner Link 表示,执行以下步骤。
|
1. |
在 Component Palette 中,选择 Partner Link 并将其拖到图表右侧的灰色 Services 泳道中。在 Create Partner Link 窗口中,将该 Partner Link 命名为 ODIAsyncStarterWebservice。从 Oracle Application Server Control 页面(您应该已在浏览器中打开)复制已部署的 ODIInvokerService 的 WSDL URL,并将其粘贴到 Create Partner Link 窗口中的 WSDL file 域。选择蓝色双箭头按钮刷新页面。将出现一个窗口,询问您是否要创建 partner link。单击 Yes 。
|
|
2. |
从 Partner Link Type 下拉菜单中选择 ODIAsyncStarterWebservice_PL。从 Partner Role 下拉菜单中选择 ODIAsyncStarterWebservice_Role。保留其他域的默认值并选择 OK。ODIAsyncStarterWebservice Partner Link 出现在您的流程图中。
|
| 4. | 从右侧的 component pallette 中选择 Process Activities,然后将调用活动拖动到流程中的 receiveInput 和 callbackClient 活动之间。将一个箭头从新的调用活动拖到 ODIAsyncStarterWebservice Partner Link 上。
|
| 5. | 在 Create variable 窗口中,将活动命名为 Invoke_ODI。选择 Input Variable 域旁边的 Magic wand 按钮。在 Create variable 窗口中,将变量命名为 startOdiPlan_InputVariable。单击 OK。
|
| 6. | 选择 Output variable 域旁边的魔术棒按钮。在 Create variable 窗口中,将变量命名为 startOdiPlan_OutputVariable。选择 OK。单击 Edit Invoke 页面中的 OK。您的流程图应该看起来如下所示。保存您的项目。
|
在本部分中,您将创建 5 个 BPEL 首选项(在流程级别设置全局变量),这样当您要更改全局变量值时不必重新编译流程。BPEL 流程将回调信息传递到 ODIINvokerService,这样可以在以后进行异步回调,由于该信息特定于服务器,因此通过创建这些首选项,您不必在将信息部署到新服务器时重新编译流程。
要创建 BPEL 首选项从而动态更新流程级别值,执行以下步骤:
|
1. |
在图表左上角的 AsynchODICall.bpel 流程中,选择 Deployment Descriptor Properties 按钮。在出现的窗口中,选择 Preferences 选项卡中的 Create。在 Create preference 窗口中,将首选项命名为 retryCount。单击 OK。
|
||||||||||||||||||
|
2. |
在 Property Value 窗口中,键入 1。在 encryption 域中,选择 Plain Text。单击 Create 按钮,并针对下表中的首选项重复以上步骤。您应该按如下屏幕截图所示设置 Deployment Descriptor Properties。单击 OK。 注:某些属性值将特定于您的环境,如果您已经进行了基本的 SOA 安装,则此处的值通常是正确的。
|
要指定 ODIStarterWebservice 输入值,执行以下步骤:
|
1. |
从右侧的 Component Palette 中,将一个 Assign 活动拖放到流程图中的 Receive_Input 和 Invoke_ODI 活动之间。
|
||||||||||||||||||
|
2. |
双击新的 Assign_1 活动。选择 General 选项卡,将活动命名为 Assign_ODIValues。单击 Copy Operation 选项卡,从 Create 下拉菜单中选择 Copy Operation。
|
||||||||||||||||||
| 3. | 在打开的窗口中,在 From 列中,展开 Process > Variables > inputVariable > payload > ODIProcessRequest 并选择 ODI_Info。在 To 列中,展开
|
||||||||||||||||||
| 4. | 现在,您将设置最后一个部分中的首选项。从 Create 下拉菜单中选择 Copy Operation。一个新的对话框出现。在 From 列中,从 Type下拉菜单中选择 Expression。选择 From 列右上角的 Xpath Expression Builder 按钮。
|
||||||||||||||||||
| 5. | 在 Expression Builder 窗口中的 Functions 标题下,从下拉菜单中选择 BPEL Xpath Extension Functions。从更新的列表中选择 getPreference,然后单击 Insert Into Expression 按钮。Expression 窗口现在包含 ora:getPreference(),将其更改为 ora:getPreference("retryCount"),其中 retryCount 是您先前设置的一个首选项的名称。单击 OK。 |
||||||||||||||||||
| 6. | 在 To 列中,展开 Process > Variables > startOdiPlan_InputVariable > Parameters > StartOdiPlanElement > CallbackInformationDTO_2 并选择 retryAttempts。单击 OK。 |
||||||||||||||||||
| 7. | 重复上述步骤(从首选项创建 retryCount 复制规则)为其他首选项创建复制规则。From 和 To 域在下表中列出。包含 6 个复制规则的 Assign 活动现在应该与下面的屏幕截图匹配。
|
||||||||||||||||||
您还再需要创建 8 个复制规则。为下表中的每行创建一个复制规则,在 From 列中选择 Expression 并输入下表中的相应值。在 To 列中,展开
|
ODIInvokerService 希望以加密方式发送口令并使用进程转换 ID 散列口令。您将使用 Java Embedding 活动加密口令。要加密回调并设置口令,执行以下步骤:
1. |
从 component palette 中,将 Java Embedding 活动拖放到图表中的 Assign_ODIValues 活动下。双击新的 Java_Embedding_1 活动打开它。
|
|
2. |
在 Code Snippet 域中,剪切并粘贴下面提供的代码。要保存您的项目,单击 File > Save All。
|
您将使用 pick 活动处理来自 ODIInvokerService 的回调。您需要为两个响应消息 onODIResponse 和 onODIError 以及一个超时活动设置处理程序。要接收异步回复,执行以下步骤:
1. |
从右侧的 component palette 中,将 Pick 活动拖放到图表中的 Invoke_ODI 活动后。展开新的 Pick_1 活动。选择 Add OnMessage Branch 按钮。
|
|||||||||||||||
2. |
双击 pick 活动最左侧的消息分支。在弹出窗口中,选择 Partner Link 域旁边的手电筒图标。展开 Process > Partner Links 并选择 Client。单击 OK。
|
|||||||||||||||
| 3. | 从 Operation 下拉菜单中选择 onODIResult。选择 Variable 域旁边的魔术棒图标。将变量命名为 OnMessage_onODIResult 并选择 OK。选择 OnMessage Branch 上的 OK。
|
|||||||||||||||
| 4. | 双击 pick 活动的其余(右侧)消息分支。在出现的窗口上,选择 Partner Link 域旁边的手电筒图标。展开 Process > Partner Links 并选择 Client。单击 OK。
|
|||||||||||||||
| 5. | 从 Operation 下拉菜单中选择 onODIError。选择 Variable 域旁边的魔术棒图标。将变量命名为 OnMessage_onODIError 并选择 OK。单击 OnMessage Branch 窗口上的 OK。
|
|||||||||||||||
| 6. | 双击 Alarm 分支。将超时由 1 天改为 1 小时(或者适合加载完成的任何时间),如下所示。单击 OK。
|
|||||||||||||||
| 7. | 将三个分支全部展开。从 component palette 中,将一个 Assign 活动拖放到 3 个分支中,如下所示。
|
|||||||||||||||
| 8. | 在第一个 (onODIResponse) onMessage 分支中打开 Assign_1。创建新的复制规则,将以下变量和表达式映射到输出变量,如下表所示(参考以下屏幕截图示例)。
|
|||||||||||||||
| 9. | 选择 General 选项卡,将活动命名为 Assign_ODIResponse。单击 OK。 |
|||||||||||||||
| 10. | 双击打开第二个 (onODIError) onMessage 分支中的 Assign_2。创建新的复制规则,将以下变量和表达式映射到输出变量,如下表所示。您的 Assign_2 活动应该如屏幕截图所示。选择 General 选项卡,将活动命名为 Assign_ODIError。选择 OK。
|
|||||||||||||||
| 11. | 打开第三个 onAlarm 分支中的 Assign_3 活动。创建新的复制规则,将以下变量和表达式映射到输出变量,如下表所示。您的 Assign_3 活动应该如下所示。选择 General 选项卡,将活动命名为 Assign_TimeOut。单击 OK。
|
|||||||||||||||
| 12. | 验证您的流程图与下图匹配。选择流程图顶部的 Validate 流程按钮 刷新并验证您的流程。保存您的项目 (File> Save All)。
|
如果出于某种原因 ODIINvokerService 不可用,您需要捕获错误并返回结果。
要捕获可能的远程故障,执行以下步骤:
|
1. |
在 main 流程作用域中,选择 Add Catch Branch 图标。向右滚动并双击图表右侧的 Catch Branch 图标。选择 Fault Qname 部分中的手电筒图标。
|
||||||||||||
| 2. | 在浏览器中,展开 System Faults 并选择 remoteFault。单击 OK。 |
||||||||||||
| 3. | 选择 Fault Variable 域旁边的魔术棒图标新建一个变量。将变量命名为 RemoteFaultVar 并选择 OK。单击 Catch Branch 窗口上的 OK。
|
||||||||||||
| 4. | 展开 Catch 活动。从右侧的 component palette 中,将 Invoke 活动拖放到图表中空白的 catch 分支中。双击新的 Invoke 活动。
|
||||||||||||
| 5. | 将活动命名为 Invoke_Callback。选择 Partner Link 域旁边的手电筒图标。选择 Client 并单击 OK。
|
||||||||||||
| 6. | 选择 Input Variable 域旁边的魔术棒按钮。将新变量命名为 ErrorOutput。单击 OK。单击 Invoke 活动窗口上的 OK。
|
||||||||||||
| 7. | 从 component palette 中,将一个 Assign 活动拖放到 Catch 分支中的 Invoke_Callback 活动上。双击新的 Assign 活动打开它。创建新的复制规则,将以下变量和表达式映射到 ErrorOutput 变量,如下表所示。
|
||||||||||||
| 8. | 验证您的 Assign 活动,如下所示。选择 General 选项卡,将活动命名为 Assign_CallbackError。单击 OK。保存您的项目。您的流程图现在应如下图所示。
|
在接下来的步骤中,您将设置默认的输入以便于以后从 BPEL 控制台测试流程。这样,您就不必再重新输入数据。要设置默认输入以调用流程,执行以下步骤:
1. |
选择主图表顶部的 Deployment Descriptor properties 按钮。在出现的窗口中,选择 Configurations 选项卡。
|
|
2. |
选择 Create 按钮,在下拉菜单中选择 defaultInput。单击 OK。
|
|
| 3. | 复制下面提供的 XML 代码,将其粘贴到 Property Value 域中。单击 OK。保存您的项目。
注:上述 XML 包含调用特定 ODI 方案 SCEN_IMPORTXFORMEXPORTXML 的详细信息,该方案在 OBE“开发可在 BPEL 流程中执行的 ODI XML 转换”中创建,位于特定的 ODI 信息库 (WORKREP) 上。如果您尝试调用自己的方案,请确保更新上述 XML 中的值以正确表示 ODI 方案中的详细信息。在这种情况下,更新 XML 值以调用您的 ODI 方案并删除注释的部分(如果您未传递任何参数)。
|
要部署 BPEL 流程,执行以下步骤:
1. |
从左侧的 Application Navigator 中,展开 BPEL2ODIAsync。右键单击您的项目 AsyncODICall 并选择 Deploy > SoademoIntegConnection > Deploy to Default Domain 。
|
2. |
在页面底部的日志记录窗口中,选择 Apache Ant 选项卡。完成流程部署后,验证 Build Successful 以绿色显示。 注:如果您发现任何错误和/或者您的流程部署失败,再次执行上述步骤以更正错误。
|
在接下来的步骤中,您将从 BPEL 控制台调用 BPEL 流程并查看我们的 ODI 方案是否已运行。要测试流程,执行以下步骤:
1. |
打开一个浏览器并在 URL 中输入 http://localhost:8888/BPELConsole。登录页面将出现。输入您的应用服务器凭证:在 user 域中键入 oc4jadmin,在 password 域中键入 welcome1。选择 Login。主 BPEL 信息板将出现。验证 AsyncODICall BPEL 项目出现在左侧的 Deployed BPEL Processes 列下。
|
2. |
在左侧的流程列表中选择您的 AsyncODICall 流程。选择 Descriptor 选项卡。在该选项卡上,您可以查看并设置在先前的步骤中创建的首选项。查看这些值,如果不正确,对其进行更新。
|
| 3. | 返回 Initiate 选项卡。从 Operation 下拉菜单中,选择 Initiate。确保您的 ODI 代理正在运行,您的 ODI 方案已经做好被调用准备。选择 Post XML Message 按钮启动该流程。当页面刷新时,选择 Visual Flow 链接查看流程执行。
|
| 4. | 单击打开 Invoke_ODI 活动窗口,查看来自已成功接收了请求的 ODIInvokerService 的同步响应。关闭 Invoke_ODI 活动窗口。
|
| 5. | 单击 Refresh view 链接。
|
在本教程中,您学习了如何:
| 有关本 OBE 教程的问题,请在 OBE 论坛上发布查询。 |
将鼠标置于该图标上可以隐藏所有的屏幕截图。