未调用拦截器方法

时间:2015-06-01 03:00:31

标签: jsf glassfish cdi interceptor

容器是Glassfish。我在一个简单的DAO bean类中实现了一个@PostConstruct生命周期事件拦截器方法,但似乎由于某种原因它根本没有拦截我的业务方法。我没有在任何地方手动实例化bean类。 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/nhuyvan1106/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

}

1 个答案:

答案 0 :(得分:0)

首先,请注意@PostContruct是生命周期回调 - 而不是拦截器 - 而@AroundConstruct是拦截器方法。它们有不同的含义,并以不同的方式声明。

另请注意,调用顺序通常如下:

  1. 构造函数拦截器名为
  2. 通过拦截器中的proceed()方法调用构造函数。
  3. 执行注入(基本上设置@Inject字段/设置器)
  4. 调用@PostConstruct生命周期回调。
  5. 关于@PostConstruct生命周期回调,您可以正确声明它。它似乎被打电话,因为它打印了一些文字。

    关于拦截器,缺少以下内容:

    • 您的拦截器必须在单独的类中声明,而不是在bean中声明。
    • 您的拦截器类必须在META-INF/beans.xml元素 OR 下的<interceptors>文件中声明,必须使用指定优先级值的javax.annotations.Priority注释进行注释。后面的选项基本上使你的拦截器在应用程序范围内:它将应用于整个应用程序,而不仅仅是包含META-INF/beans.xml的jar。首先,我建议您在META-INF/beans.xml
    • 中声明它
    • 您的拦截器必须使用@Interceptorjavax.interceptor.Interceptor
    • 进行注释
    • 您必须在拦截器上声明一个拦截器绑定,并声明要拦截它的bean /方法。

    总而言之,您必须为拦截器创建一个拦截器绑定:

    @InterceptorBinding
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Greet {
    
    }
    

    然后你必须使用拦截器绑定为你的拦截器创建一个类:

    @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 {
        ...
    }