考虑Struts 2 + Spring 4项目。
对于每次登录,User
对象都会被放入会话中。作为一个非常简单的动作,它将看起来
public class LoginProcess implements ServletRequestAware {
@Inject
private AuthenticationServices authenticationServices;
public String execute() {
//The login method makes a new User and fills its setters
User newUser = authenticationServices.login(....);
getServletRequest().getSession().setAttribute("USER_SESSION", user);
}
}
当我们手动创建一个新的User
对象,因此它不是托管的spring bean,我们无法在User
类中使用spring功能:@Inject
,@Value
,...
我尝试将用户更改为:
@Named
@Scope(value="session")
public class User { ...
@Inject
private AccountServices accountServices;
}
并注入User
而不是调用new User
,但我收到错误:
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
虽然它描述了错误,但我找不到如何解决它,我不确定这是否是正确的方法。当我使用session scope
spring mvc
有任何意见吗?!
为什么我需要这个? (简化情况)
用户对象具有getAccounts()
个方法,可以获取所有用户帐户。获取用户帐户是一项昂贵的操作,并且用户可能在登录期间不需要其帐户。
因此,我们不会在用户登录后立即获取用户帐户,而是让get方法获取用户帐户(如果没有用户帐户):
public class User() {
private Accounts accounts;
@Inject
private AccountServices accountServices;
Accounts getAccounts() {
if (accounts == null) {
accounts = accountServices.getUserAccountsFromDB(...)
}
return accounts;
}
答案 0 :(得分:2)
不要自己创建User
的新实例,而是从Spring上下文中获取bean。
例如,您可以通过实现ApplicationContextAware
接口并调用getBean
方法之一来实现它。
User user = applicationContext.getBean(User.class);
// populate user and put it into session
以这种方式,它是一个Spring托管bean,应该注入所有必需的属性。
但请考虑将您的User
更改为简单的POJO并将所有业务逻辑(例如提取用户帐户)移动到更合适的位置,这样您的模型层就会更清晰,更容易测试。