57.3. 在阶段限制拦截器放置
概述
将拦截器放在阶段可能无法对放置进行精细的控制,以确保拦截器正常工作。例如,如果需要使用 SAAJ API 检查消息的 SOAP 标头,则需要在拦截器后将消息转换为 SAAJ 对象后运行。有些情况下,一个拦截器消耗另一个拦截器需要的消息的一部分。在这些情况下,开发人员可以提供在拦截器之前必须执行的拦截器列表。开发人员也可以提供在拦截器之后必须执行的拦截器列表。
运行时只能在拦截器的阶段使用这些列表。如果开发人员从早期阶段将拦截器放在必须在当前阶段之后执行的拦截器列表中,则运行时将忽略请求。
添加到链前
开发拦截器时出现的一个问题是,拦截器所需的数据并不总是存在。当链中的一个拦截器消耗后续拦截器所需的消息数据时,可能会发生这种情况。开发人员可以通过修改其拦截器来控制自定义拦截器消耗的内容,并可能会解决这个问题。但是,这并不总是可行,因为 Apache CXF 使用了多个拦截器,开发人员无法修改它们。
另一种解决方法是确保在任何使用定制拦截器所需的消息数据的拦截器之前放置自定义拦截器。执行此操作的最简单方法是将其放在早期阶段,但并不总是可能。对于需要在一个或多个拦截器之前放置拦截器,Apache CXF 的 AbstractPhaseInterceptor
类提供了两个 addBefore ()
方法。
如 例 57.2 “在其他拦截器前添加拦截器的方法” 所示,一个使用单个拦截器 ID,另一个使用拦截器 ID。您可以进行多个调用来继续向列表添加拦截器。
例 57.2. 在其他拦截器前添加拦截器的方法
publicaddBefore
String
i
publicaddBefore
Collection<String>
i
如 例 57.3 “指定在当前拦截器后必须运行的拦截器列表” 所示,开发人员在自定义拦截器的 constuctor 中调用 addBefore ()
方法。
例 57.3. 指定在当前拦截器后必须运行的拦截器列表
public class MyPhasedOutInterceptor extends AbstractPhaseInterceptor
{
public MyPhasedOutInterceptor() {
super(Phase.PRE_LOGICAL);
addBefore(HolderOutInterceptor.class.getName());
}
...
}
大多数拦截器使用它们的类名称进行拦截器 ID。
将 添加到链后
拦截器所需的另一个原因是数据没有被放在消息对象中。例如,拦截器可能希望将消息数据用作 SOAP 消息,但在消息转换为 SOAP 消息之前,它将无法正常工作。开发人员可以通过修改其拦截器来控制自定义拦截器消耗的内容,并可能会解决这个问题。但是,这并不总是可行,因为 Apache CXF 使用了多个拦截器,开发人员无法修改它们。
另一种解决方法是确保将自定义拦截器放在拦截器或拦截器后,生成自定义拦截器所需的消息数据。执行此操作的最简单方法是将其放在后续阶段,但并不总是可能。AbstractPhaseInterceptor
类为需要在一个或多个其它拦截器之后放置拦截器的情况提供两个 addAfter ()
方法。
如 例 57.4 “在其他拦截器后添加拦截器的方法” 所示,一个方法采用单个拦截器 ID,另一个方法采用拦截器 ID 的集合。您可以进行多个调用来继续向列表添加拦截器。
例 57.4. 在其他拦截器后添加拦截器的方法
publicaddAfter
String
i
publicaddAfter
Collection<String>
i
如 例 57.5 “指定在当前拦截器前必须运行的拦截器列表” 所示,开发人员在自定义拦截器的 constuctor 中调用 addAfter ()
方法。
例 57.5. 指定在当前拦截器前必须运行的拦截器列表
public class MyPhasedOutInterceptor extends AbstractPhaseInterceptor
{
public MyPhasedOutInterceptor() {
super(Phase.PRE_LOGICAL);
addAfter(StartingOutInterceptor.class.getName());
}
...
}
大多数拦截器使用它们的类名称进行拦截器 ID。