未调用拦截器方法
Interceptor Method Not Invoked
容器是 Glassfish。我已经在一个简单的 DAO bean class 中实现了一个 @PostConstruct
生命周期事件拦截器方法,但似乎由于某种原因它根本没有拦截我的业务方法。我没有在任何地方手动实例化 bean classes。 beans.xml
发现模式是全部,因为我没有注释 DefaultUserDao
bean,所以它获得默认范围。
public class DefaultUserDao implements UserDao {
private String userName;
private String password;
Scanner users = null;
String[] userNamePasswordPairs = null;
public DefaultUserDao() {
try {
users = new Scanner(Paths.get("/home/NetBeansProjects/EJBInAction/web/users"));
}
catch (IOException ex) {
Logger.getLogger(DefaultUserDao.class.getName()).log(Level.SEVERE, null, ex);
}
}
/*The interceptor for this method is defined right below, that
interceptor method is not called at all. If I insert a
System.out.println(userNamePasswordPairs) after the split()
method below, it prints [userName:password] pair twice and there
is only one line in the text file from which the pair was read in the
form like this admin:admin. Notice that I also insert a System.out.println()
method in the interceptor method but if I remove the print()
method from this init() method, I don't see it prints anything
*/
@PostConstruct
public void init() {
while (users.hasNextLine()) {
String line = users.nextLine();
userNamePasswordPairs = line.split(":");
//If I uncomment this, I see it prints [admin:admin] pair
//twice, but when I comment it out, I don't see it prints anything
//System.out.println(Arrays.toString(userNamePasswordPairs));
userName = userNamePasswordPairs[0];
password = userNamePasswordPairs[1];
}
}
@AroundConstruct
private void printUser(InvocationContext ic) {
//If this interceptor was invoked, it should print at least "Interceptor invoked: "
//But it does not print this.
System.out.println("Interceptor invoked: " + Arrays.toString(userNamePasswordPairs));
try {
ic.proceed();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
一个收集用户名和密码的简单 JSF 页面
@Named
@RequestScoped
public class LoginBean {
private String userName;
private String password;
@Inject
private UserDao userDao;
public LoginBean() {
}
public LoginBean(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String validateUser() {
if (userDao.getUserName().equals(userName) && userDao.getPassword().equals(password)) {
}
else {
userName = "Error";
password = "Error";
}
return "confirmation.xhtml";
}
//getter and setter for userName and password
}
首先,请注意 @PostContruct
是生命周期回调 - 而不是拦截器 - 而 @AroundConstruct
是拦截器方法。它们的含义不同,声明也不同。
另请注意,调用顺序通常如下:
- 构造函数拦截器被调用
- 通过拦截器中的
proceed()
方法调用构造函数
- 执行注入(基本上
@Inject
fields/setters都设置好了)
@PostConstruct
生命周期回调被调用。
关于@PostConstruct
生命周期回调,你声明正确。它似乎被调用,因为它打印了一些文本。
关于拦截器,缺少以下内容:
- 您的拦截器必须在单独的 class 中声明,而不是在 bean 中声明。
- 您的拦截器 class 必须在
META-INF/beans.xml
文件中的 <interceptors>
元素下声明 或者 它必须用 [= 注释22=] 指定优先级值的注解。后面的选项使您的拦截器在整个应用程序范围内,基本上:它将应用于整个应用程序,而不仅仅是包含 META-INF/beans.xml
的 jar。首先,我建议您在 META-INF/beans.xml
. 中声明它
- 你的拦截器必须注解
@Interceptor
(javax.interceptor.Interceptor
)
- 您必须在您的拦截器上声明一个拦截器绑定,并声明您要用它拦截的beans/methods。
总而言之,您必须为拦截器创建一个拦截器绑定:
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Greet {
}
然后你必须为你的拦截器创建一个class,使用拦截器绑定:
@Greet
@Interceptor
public class GreetInterceptor {
@AroundConstruct
public void aroundConstruct(InvocationContext ic) throws Exception {
System.out.println("Hello!!");
ic.proceed();
}
}
然后在你的META-INF/beans.xml
中声明它:
<interceptors>
<class>com.sandbox.GreetInterceptor</class>
</interceptors>
最后,用拦截器绑定注释要拦截调用的 bean:
@Greet
public class DefaultUserDao implements UserDao {
...
}
容器是 Glassfish。我已经在一个简单的 DAO bean class 中实现了一个 @PostConstruct
生命周期事件拦截器方法,但似乎由于某种原因它根本没有拦截我的业务方法。我没有在任何地方手动实例化 bean classes。 beans.xml
发现模式是全部,因为我没有注释 DefaultUserDao
bean,所以它获得默认范围。
public class DefaultUserDao implements UserDao {
private String userName;
private String password;
Scanner users = null;
String[] userNamePasswordPairs = null;
public DefaultUserDao() {
try {
users = new Scanner(Paths.get("/home/NetBeansProjects/EJBInAction/web/users"));
}
catch (IOException ex) {
Logger.getLogger(DefaultUserDao.class.getName()).log(Level.SEVERE, null, ex);
}
}
/*The interceptor for this method is defined right below, that
interceptor method is not called at all. If I insert a
System.out.println(userNamePasswordPairs) after the split()
method below, it prints [userName:password] pair twice and there
is only one line in the text file from which the pair was read in the
form like this admin:admin. Notice that I also insert a System.out.println()
method in the interceptor method but if I remove the print()
method from this init() method, I don't see it prints anything
*/
@PostConstruct
public void init() {
while (users.hasNextLine()) {
String line = users.nextLine();
userNamePasswordPairs = line.split(":");
//If I uncomment this, I see it prints [admin:admin] pair
//twice, but when I comment it out, I don't see it prints anything
//System.out.println(Arrays.toString(userNamePasswordPairs));
userName = userNamePasswordPairs[0];
password = userNamePasswordPairs[1];
}
}
@AroundConstruct
private void printUser(InvocationContext ic) {
//If this interceptor was invoked, it should print at least "Interceptor invoked: "
//But it does not print this.
System.out.println("Interceptor invoked: " + Arrays.toString(userNamePasswordPairs));
try {
ic.proceed();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
一个收集用户名和密码的简单 JSF 页面
@Named
@RequestScoped
public class LoginBean {
private String userName;
private String password;
@Inject
private UserDao userDao;
public LoginBean() {
}
public LoginBean(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String validateUser() {
if (userDao.getUserName().equals(userName) && userDao.getPassword().equals(password)) {
}
else {
userName = "Error";
password = "Error";
}
return "confirmation.xhtml";
}
//getter and setter for userName and password
}
首先,请注意 @PostContruct
是生命周期回调 - 而不是拦截器 - 而 @AroundConstruct
是拦截器方法。它们的含义不同,声明也不同。
另请注意,调用顺序通常如下:
- 构造函数拦截器被调用
- 通过拦截器中的
proceed()
方法调用构造函数 - 执行注入(基本上
@Inject
fields/setters都设置好了) @PostConstruct
生命周期回调被调用。
关于@PostConstruct
生命周期回调,你声明正确。它似乎被调用,因为它打印了一些文本。
关于拦截器,缺少以下内容:
- 您的拦截器必须在单独的 class 中声明,而不是在 bean 中声明。
- 您的拦截器 class 必须在
META-INF/beans.xml
文件中的<interceptors>
元素下声明 或者 它必须用 [= 注释22=] 指定优先级值的注解。后面的选项使您的拦截器在整个应用程序范围内,基本上:它将应用于整个应用程序,而不仅仅是包含META-INF/beans.xml
的 jar。首先,我建议您在META-INF/beans.xml
. 中声明它
- 你的拦截器必须注解
@Interceptor
(javax.interceptor.Interceptor
) - 您必须在您的拦截器上声明一个拦截器绑定,并声明您要用它拦截的beans/methods。
总而言之,您必须为拦截器创建一个拦截器绑定:
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Greet {
}
然后你必须为你的拦截器创建一个class,使用拦截器绑定:
@Greet
@Interceptor
public class GreetInterceptor {
@AroundConstruct
public void aroundConstruct(InvocationContext ic) throws Exception {
System.out.println("Hello!!");
ic.proceed();
}
}
然后在你的META-INF/beans.xml
中声明它:
<interceptors>
<class>com.sandbox.GreetInterceptor</class>
</interceptors>
最后,用拦截器绑定注释要拦截调用的 bean:
@Greet
public class DefaultUserDao implements UserDao {
...
}