如何在springboot中从一个公共类中获取会话

时间:2018-01-28 16:43:26

标签: spring spring-mvc spring-boot

我想从一个普通班级获得会话。 @Autowired没有工作。

public class TMessageHandlerFactory implements MessageHandlerFactory {
    @Autowired
    private HttpSession session;

    @Override
    public void data(InputStream data) {
        int userId = (int)session.getAtrribute("key"); //session null
        ....        //do sth
    }
}

构造函数也没有工作

@Component
public class SMTPRunner implements ApplicationRunner {
    @Autowired
    private UserService userService;    //userService can access
    @Autowired
    private HttpSession session;        //session can't access

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        TMessageHandlerFactory myFactory = new TMessageHandlerFactory(session);
        ....
    }
}

然后我尝试使用SpringBeanFactory,它也没有用。

@Component
public class SpringBeanFactoryUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringBeanFactoryUtil.applicationContext == null) {
            SpringBeanFactoryUtil.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}

SpringBeanFactoryUtil只能获取我的自定义bean,无法获得httpsession。 我该怎么办?

3 个答案:

答案 0 :(得分:3)

如果我理解正确,您希望从更广泛范围(单例)的组件访问会话范围中的某些内容,因此系统无法知道您在服务器中的哪个潜在并发会话受到关注实际上,它会在spring init时间说会话范围没有定义。

你可以使用ObjectFactory模式(可能的解决方案中的一个)获得arround

@Autowired
ObjectFactory<HttpSession> httpSessionFactory;

然后当你需要它时,从一个绑定到会话的线程:

HttpSession session = httpSessionFactory.getObject();

这样spring绑定一个receipe来获取你调用getObject()方法所需类型的对象,而不是那个尚未可用的实际对象。

请理解,如果在运行代码时没有绑定到当前线程的会话,则会因为没有会话可用而失败(返回null)。这意味着你要么从你未能转发请求/会话的请求线程本地信息的线程中调用此代码,要么从没有意义的上下文中调用此代码。

答案 1 :(得分:0)

以pojo样式创建会话范围bean。注入它并在需要设置的地方使用或从HttpSession中获取数据。 Spring会自动将相应的数据设置到HttpSession中。例如:

@Component
@Scope(proxyMode= ScopedProxyMode.TARGET_CLASS, value=WebApplicationContext.SCOPE_SESSION)
public class SessionData {
    private Currency currency;

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }
}


@Service
public class UserService {

   @Autowired
   private SessionData sessionData;

   public Currency getCurrentCurrency() {
       return sessionData.getCurrency();
   }

   public void setCurrentCurrency(Currency currency) {
       sessionData.setCurrency(currency);
   }
}

通过这种方式,使用UserService获取/设置当前货币将反映在当前HttpSession中,并带有会话bean属性的相应属性名称(“ currency”)。

答案 2 :(得分:0)

@Autowired HttpSession session在Singleton类中将注入AutowireUtils$ObjectFactoryDelegatingInvocationHandler-Spring似乎很聪明,可以自动为较窄范围的对象创建代理。