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。