【问题标题】:How to use session scoped bean properly如何正确使用会话范围的 bean
【发布时间】:2014-04-22 23:22:19
【问题描述】:

我的 Spring MVC 应用中有 3 个类:UserDetailsInterceptor 类、MyAdvice 类和 UserDetails 类(会话范围)。

我想要完成的事情很简单:

  1. UserDetailsInterceptor 拦截请求并在UserDetails bean 范围内的会话中设置用户 ID。
  2. 稍后,当调用 AOP 建议类中的方法时,从范围为 UserDetails bean 的会话中检索用户的 id。

问题(也标记在下面的代码中):

  1. UserDetails 对象在 MyAdvice 类中为空。
  2. UserDetailsInterceptoruserDetails.setUserID(request.getRemoteUser()); 什么都不做。

代码

UserDetailsInterceptor类:

public class UserDetailsInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private UserDetails userDetails;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //set user ID, but next line doesn't do anything for some reason (e.g. `userID` is still null)
        userDetails.setUserID(request.getRemoteUser());
        return true;
    }
}

MyAdvice类:

public class MyAdvice implements MethodInterceptor {

    @Autowired
    private UserDetails userDetails; //It's null

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //Print user ID
        System.out.println(userDetails.getID());
        return invocation.proceed();
    }
}

UserDetails类:

public class UserDetails {

    private String userID;

    public void setUserID(String userID) {
        this.userID= userID;
    }

    public String getUserID() {
        return this.userID;
    }
}

dispatcher-servlet.xml:

<bean id="userDetails " class="package.UserDetails " scope="session">
    <aop:scoped-proxy/>
</bean>

MyPointcutAdvisor类:

public class MyPointcutAdvisor implements PointcutAdvisor {

    private MyPointcut pointcut = new MyPointcut();
    private MyAdvice advice = new MyAdvice();

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }

    @Override
    public Advice getAdvice() {
        return this.advice;
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

有什么想法吗?提前致谢。

更新:

通过注册MyAdvice类,其中的userDetails对象不再为空。但是,它与UserDetailsInterceptor 中的对象不同。所以bean实际上不是“会话范围”?

回答

问题出在以下代码:

private MyPointcut pointcut = new MyPointcut();
private MyAdvice advice = new MyAdvice();

它们都不是由 spring 管理的。结果,事情是连线的,并没有按我们预期的方式工作。

【问题讨论】:

  • 你在哪里使用MyAdvice类?
  • @SotiriosDelimanolis 它用于拦截迄今为止映射到 url 的任何控制器方法(它作为我定制的 Spring AOP 顾问的建议)。
  • 我的问题是在哪里,而不是如何。您似乎是自己创建它,而不是从上下文中获取它作为 bean。
  • @SotiriosDelimanolis 我不太清楚你的意思。我注册了一个org.springframework.aop.PointcutAdvisor,这个advice class就是它的advice。
  • 向我们展示该配置。

标签: java session spring-mvc spring-aop


【解决方案1】:

这个

UserDetails 对象是 nullMyAdvice 类中。

如果 MyAdvice 实例由 Spring 管理,则不可能。您必须自己实例化它,而不是从上下文中获取它。

如果 Spring 不管理该对象,它就无法将任何内容注入到 @Autowired 目标中,因此您的字段仍然是 null

如果 Spring 正在管理您的对象(一个 bean)并且无法解析依赖关系,它会抛出异常。

【讨论】:

  • 您能解释一下原因吗?谢谢
  • @Conan 查看编辑。我的回答仍然是基于一个假设。如果我错了,请通过显示您的配置来纠正我。
  • 感谢您的回复。这绝对是有道理的。如果我在配置文件中将MyAdvice类注册为一个bean,是否意味着它是由Spring管理的?
  • @柯南是的。如果你有合适的component-scanannotation-config,Spring 可以正确地进行注入。请注意,您可能需要更改进行 Advisor 注册的方式。
  • 通过将MyAdvice 类注册到配置中,MyAdvice 类中的 UserDetails 对象不再为空。谢谢!但是,我也注意到它与 UserDetailsInterceptor 中的对象不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 2015-01-27
  • 2012-10-31
相关资源
最近更新 更多