如何从 Spring 引导中的公共 class 获取会话?
How can I get session from a common class in Spring Boot?
我想从公共 class 获取会话。使用 @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
。
我该怎么办?
如果我没理解错的话,您想从范围更广的组件(单例)访问会话范围内的某些内容,因此系统无法知道您服务器中的哪个潜在并发会话实际上,它会在 spring 初始时间说未定义会话范围。
您可以使用 ObjectFactory 模式(可能的解决方案之一)解决这个问题
import `org.springframework.beans.factory.ObjectFactory`;
// ...
// ...
@Autowired
ObjectFactory<HttpSession> httpSessionFactory;
然后在需要时,从绑定到会话的线程:
HttpSession session = httpSessionFactory.getObject();
这样 spring 绑定一个 receipe 以您调用 getObject() 方法的类型获取您需要的对象,而不是尚不可用的实际对象。
请理解,如果在您 运行 代码时没有绑定到当前线程的会话,这将失败 (return null),因为没有会话可用。这意味着您要么从无法转发 request/session 的请求线程本地信息的线程中调用此代码,要么从没有意义的上下文中调用此代码。
以 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);
}
}
这样 getting/setting 使用 UserService
的当前货币将反映在当前 HttpSession
中,会话 bean 的相应属性名称 属性 ('currency')。
@Autowired HttpSession session
在单例中 class 将注入一个 AutowireUtils$ObjectFactoryDelegatingInvocationHandler
- Spring 似乎足够聪明,可以自动为范围较窄的对象创建代理。
我想从公共 class 获取会话。使用 @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
。
我该怎么办?
如果我没理解错的话,您想从范围更广的组件(单例)访问会话范围内的某些内容,因此系统无法知道您服务器中的哪个潜在并发会话实际上,它会在 spring 初始时间说未定义会话范围。
您可以使用 ObjectFactory 模式(可能的解决方案之一)解决这个问题
import `org.springframework.beans.factory.ObjectFactory`;
// ...
// ...
@Autowired
ObjectFactory<HttpSession> httpSessionFactory;
然后在需要时,从绑定到会话的线程:
HttpSession session = httpSessionFactory.getObject();
这样 spring 绑定一个 receipe 以您调用 getObject() 方法的类型获取您需要的对象,而不是尚不可用的实际对象。
请理解,如果在您 运行 代码时没有绑定到当前线程的会话,这将失败 (return null),因为没有会话可用。这意味着您要么从无法转发 request/session 的请求线程本地信息的线程中调用此代码,要么从没有意义的上下文中调用此代码。
以 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);
}
}
这样 getting/setting 使用 UserService
的当前货币将反映在当前 HttpSession
中,会话 bean 的相应属性名称 属性 ('currency')。
@Autowired HttpSession session
在单例中 class 将注入一个 AutowireUtils$ObjectFactoryDelegatingInvocationHandler
- Spring 似乎足够聪明,可以自动为范围较窄的对象创建代理。