调用 JSF 托管 bean 方法时未触发 CDI 拦截器
CDI interceptor not fired when JSF managed bean method is invoked
这是我的拦截器研究案例,但它没有触发。
拦截器注解
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface LogInterceptor {
}
拦截器的实现
import javax.annotation.Priority;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
@Interceptor
@LogInterceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LogInterceptorImpl {
@AroundInvoke
public Object log(InvocationContext context) {
Object o = null;
try {
System.out.println("START");
o = context.proceed();
System.out.println("END");
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
控制器
import modelo.Post;
import interceptor.LogInterceptor;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean(name = "postController")
@SessionScoped
public class PostController implements Serializable {
private List<Post> items = null;
private Post selected;
public PostController() {
MyFacade facade = new MyFacade();
items = facade.getItems();
}
@LogInterceptor
public List<Post> getItems() {
return items;
}
}
玻璃鱼日志
Informações: EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
Informações: file:/C:/Users/f9921257/Documents/NetBeansProjects/estudo/build/web/WEB-INF/classes/_estudoPU login successful
Informações: Portable JNDI names for EJB PostFacade: [java:global/estudo/PostFacade!facade.PostFacade, java:global/estudo/PostFacade]
Informações: Portable JNDI names for EJB CategoriaFacade: [java:global/estudo/CategoriaFacade!facade.CategoriaFacade, java:global/estudo/CategoriaFacade]
Informações: WELD-000900: 2.2.2 (Final)
WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled
WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
Informações: Inicializando Mojarra 2.2.7 ( 20140610-1547 https://svn.java.net/svn/mojarra~svn/tags/2.2.7@13362) para o contexto '/estudo'
Informações: Monitoring jndi:/server/estudo/WEB-INF/faces-config.xml for modifications
Informações: Running on PrimeFaces 5.0
Informações: Loading application [estudo] at [/estudo]
Informações: estudo was successfully deployed in 13.298 milliseconds.
LogInterceptorImpl上的标记"START"和"END"没有出现在日志文件中。为什么他们不开火?
您需要使用 @javax.inject.Named
注释而不是 @ManagedBean
:
@Named("postController")
@SessionScoped
public class PostController
同时添加@AroundInvoke标记拦截器方法:
@Interceptor
@LogInterceptor
public class LogInterceptorImpl {
@AroundInvoke
public Object log(InvocationContext context) {
...
}
}
最后一步,需要开启beans.xml中的拦截器,否则拦截器会被忽略:
beans.xml
<beans>
<interceptors>
<class>com.nameofyourpackage.LogInterceptorImpl </class>
</interceptors>
</beans>
使用@Named代替@ManagedBean的说明
这两个注释的含义基本相同 - 它们为 bean 提供了一个文本名称,以便可以在 JSF 页面中访问它。但是,标记为 @ManagedBean
的 bean 由 JSF 子系统创建,CDI 注释将被忽略(例如 SessionScoped 或拦截器限定符,例如您的 LogInterceptor)。标记为 @Named
的 bean 可以充分利用 CDI,而您不能使用 JSF 特定注释,例如 @ManagedProperty
(您应该将 @Inject 与 CDI 一起使用)。这不是问题,因为 @ManagedProperty
和 @ManagedBean
都已弃用,并且总有一种方法可以使用 CDI 完成相同的任务。此处对此进行了更详细的讨论:Backing beans (@ManagedBean) or CDI Beans (@Named)?
这是我的拦截器研究案例,但它没有触发。
拦截器注解
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface LogInterceptor {
}
拦截器的实现
import javax.annotation.Priority;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
@Interceptor
@LogInterceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LogInterceptorImpl {
@AroundInvoke
public Object log(InvocationContext context) {
Object o = null;
try {
System.out.println("START");
o = context.proceed();
System.out.println("END");
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
控制器
import modelo.Post;
import interceptor.LogInterceptor;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean(name = "postController")
@SessionScoped
public class PostController implements Serializable {
private List<Post> items = null;
private Post selected;
public PostController() {
MyFacade facade = new MyFacade();
items = facade.getItems();
}
@LogInterceptor
public List<Post> getItems() {
return items;
}
}
玻璃鱼日志
Informações: EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
Informações: file:/C:/Users/f9921257/Documents/NetBeansProjects/estudo/build/web/WEB-INF/classes/_estudoPU login successful
Informações: Portable JNDI names for EJB PostFacade: [java:global/estudo/PostFacade!facade.PostFacade, java:global/estudo/PostFacade]
Informações: Portable JNDI names for EJB CategoriaFacade: [java:global/estudo/CategoriaFacade!facade.CategoriaFacade, java:global/estudo/CategoriaFacade]
Informações: WELD-000900: 2.2.2 (Final)
WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled
WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN: WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
Informações: Inicializando Mojarra 2.2.7 ( 20140610-1547 https://svn.java.net/svn/mojarra~svn/tags/2.2.7@13362) para o contexto '/estudo'
Informações: Monitoring jndi:/server/estudo/WEB-INF/faces-config.xml for modifications
Informações: Running on PrimeFaces 5.0
Informações: Loading application [estudo] at [/estudo]
Informações: estudo was successfully deployed in 13.298 milliseconds.
LogInterceptorImpl上的标记"START"和"END"没有出现在日志文件中。为什么他们不开火?
您需要使用 @javax.inject.Named
注释而不是 @ManagedBean
:
@Named("postController")
@SessionScoped
public class PostController
同时添加@AroundInvoke标记拦截器方法:
@Interceptor
@LogInterceptor
public class LogInterceptorImpl {
@AroundInvoke
public Object log(InvocationContext context) {
...
}
}
最后一步,需要开启beans.xml中的拦截器,否则拦截器会被忽略:
beans.xml
<beans>
<interceptors>
<class>com.nameofyourpackage.LogInterceptorImpl </class>
</interceptors>
</beans>
使用@Named代替@ManagedBean的说明
这两个注释的含义基本相同 - 它们为 bean 提供了一个文本名称,以便可以在 JSF 页面中访问它。但是,标记为 @ManagedBean
的 bean 由 JSF 子系统创建,CDI 注释将被忽略(例如 SessionScoped 或拦截器限定符,例如您的 LogInterceptor)。标记为 @Named
的 bean 可以充分利用 CDI,而您不能使用 JSF 特定注释,例如 @ManagedProperty
(您应该将 @Inject 与 CDI 一起使用)。这不是问题,因为 @ManagedProperty
和 @ManagedBean
都已弃用,并且总有一种方法可以使用 CDI 完成相同的任务。此处对此进行了更详细的讨论:Backing beans (@ManagedBean) or CDI Beans (@Named)?