Struts2 Guice 3.0@ScopeSession用户对象在会话超时时不失效
我有一门课:Struts2 Guice 3.0@ScopeSession用户对象在会话超时时不失效,struts2,guice,session-timeout,inject,Struts2,Guice,Session Timeout,Inject,我有一门课: @SessionScoped public class LoggedUser { private User user; ... } 如果用户登录到我的应用程序,我将使用它来跟踪 在我的Struts2应用程序中,我有一个拦截器来检查用户是否已登录,如果没有,他是否已转发到登录页面 public class LoggedUserInterceptor extends AbstractInterceptor { private static final l
@SessionScoped
public class LoggedUser {
private User user;
...
}
如果用户登录到我的应用程序,我将使用它来跟踪
在我的Struts2应用程序中,我有一个拦截器来检查用户是否已登录,如果没有,他是否已转发到登录页面
public class LoggedUserInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2822434409188961460L;
@Inject
private LoggedUser loggedUser;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
if(loggedUser==null || !loggedUser.isLogged()){
return "login";
}
return invocation.invoke();
}
}
会话超时时会出现问题。对象LoggdeUser从不为null或删除。我总是最后一个例子
我添加了一个会话侦听器
public class SessionListener implements HttpSessionListener {
private static Logger logger = Logger.getLogger(SessionListener.class.getName());
@Override
public void sessionCreated(HttpSessionEvent event) {
logger.info("sessionCreated = " + event.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
logger.info("sessionDestroyed = " + event.getSession().getId());
}
}
我看到sessionDestroyed被调用,但是当我再次进入我的拦截器时。。不会为新会话重新创建LoggedUser
为什么?
我的Struts2登录操作如下
public class LoginUserAction extends ActionSupport implements ModelDriven<LoggedUser>, ServletRequestAware {
...
@Inject
private LoggedUser loggedUser;
public String execute() throws Exception {
...
loggerUser.setLoggedTime(now);
...
return SUCCESS;
}
公共类LoginUserAction扩展ActionSupport实现模型驱动的ServletRequestAware{
...
@注入
私人LoggedUser LoggedUser;
公共字符串execute()引发异常{
...
setLoggedTime(现在);
...
回归成功;
}
我在web.xml中也添加了这一点
session-config
session-timeout 2 /session-timeout
/session-config
会话配置
会话超时2/会话超时
/会话配置我不知道guice,但该会话可供拦截器使用,并可通过SessionAware随时供操作使用: ActionInvocation提供对会话的访问。以下是“身份验证”侦听器的一部分。如果没有“用户”对象,则返回Action.LOGIN
public String intercept(ActionInvocation invocation) throws Exception {
Map session = invocation.getInvocationContext().getSession();
appLayer.User user = (appLayer.User) session.get("User");
if (user == null){
return Action.LOGIN;
}
return invocation.invoke();
}
我仅在用户登录时将用户对象放置在会话上
在登录操作中,我将用户对象放置在会话上:
public class Login extends ActionSupport implements SessionAware {
private Map<String, Object> session;
private String userName;
private String password;
public String execute() {
//use DB authentication once this works
//if ("ken".equalsIgnoreCase(userName) && "ken".equalsIgnoreCase(password)){
try {
User user = new User(userName, password);
session.put("User", user);
return ActionSupport.SUCCESS;
} catch (Exception e) {
System.out.println("There was an exception" + e.getMessage());
return ActionSupport.LOGIN;
}
}
public void validate() {
String user = this.getUserName();
String pass = this.getPassword();
//This block is a bit redundant but I couldn't figure out how
//to get just the hibernate part to report an exception on Username/pass
if (!StringUtils.isBlank(this.getUserName()) && !StringUtils.isBlank(this.getPassword())) {
try {
Class.forName("com.ibm.as400.access.AS400JDBCDriver").newInstance();
String url = "jdbc:as400://192.168.1.14";
DriverManager.getConnection(url, user, pass).close();
} catch (Exception e) {
addFieldError("login.error.authenticate", "Bad Username / Password");
}
}
if (StringUtils.isBlank(getUserName())) {
addFieldError("login.error.name", "Missing User Name");
}
if (StringUtils.isBlank(getPassword())) {
addFieldError("login.error.password", "Missing Password");
}
//else both are blank don't report an error at this time
}
... getters/setters....
}//end class
公共类登录扩展ActionSupport实现SessionAware{
私人Map会议;
私有字符串用户名;
私有字符串密码;
公共字符串execute(){
//一旦成功,请使用DB身份验证
//如果(“ken.equalsIgnoreCase(用户名)&&“ken.equalsIgnoreCase(密码)){
试一试{
用户=新用户(用户名、密码);
session.put(“用户”,User);
返回ActionSupport.SUCCESS;
}捕获(例外e){
System.out.println(“出现异常”+e.getMessage());
返回ActionSupport.LOGIN;
}
}
public void validate(){
字符串user=this.getUserName();
String pass=this.getPassword();
//这个区块有点多余,但我不知道怎么做
//只让hibernate部分报告用户名/密码异常
如果(!StringUtils.isBlank(this.getUserName())和&!StringUtils.isBlank(this.getPassword()){
试一试{
Class.forName(“com.ibm.as400.access.as400jdbdriver”).newInstance();
String url=“jdbc:as400://192.168.1.14”;
getConnection(url、用户、密码).close();
}捕获(例外e){
addFieldError(“login.error.authenticate”,“错误的用户名/密码”);
}
}
if(StringUtils.isBlank(getUserName())){
addFieldError(“login.error.name”,“缺少用户名”);
}
if(StringUtils.isBlank(getPassword())){
addFieldError(“login.error.password”,“缺少密码”);
}
//否则两者都为空,此时不报告错误
}
…接受者/接受者。。。。
}//末级
如果我没记错的话,这至少部分来自“Struts2在行动”.无论如何,我非常相信DI,但由于会话可以从拦截器访问,而且操作我也不介意。我对Struts2一无所知,但我猜拦截器的作用域比会话的作用域更广。换句话说,拦截器实例比会话保持的时间更长。Guice不能也不会会话结束时,不要将注入的字段设置为
null
,也不会自动重新注入对象
如果在生命周期较长的对象中使用生命周期较短的对象(例如SessionScoped
对象中的RequestScoped
对象或单例中的SessionScoped
对象),则需要为生命周期较短的对象注入提供程序
就你而言,我认为这可能是你需要的:
public class LoggedUserInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2822434409188961460L;
@Inject
private Provider<LoggedUser> loggedUserProvider;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
LoggedUser loggedUser = loggedUserProvider.get();
if(loggedUser==null || !loggedUser.isLogged()){
return "login";
}
return invocation.invoke();
}
}
公共类LoggedUserInterceptor扩展了AbstractInterceptor{
私有静态最终长serialVersionUID=282434409188961460L;
@注入
私人提供商loggedUserProvider;
@凌驾
公共字符串截获(ActionInvocation调用)引发异常{
LoggedUser LoggedUser=loggedUserProvider.get();
if(loggedUser==null | |!loggedUser.isLogged()){
返回“登录”;
}
返回invocation.invoke();
}
}
最简单的方法是最终在登录时将令牌放入会话中,并使用拦截器进行检查
@Override
public String intercept(ActionInvocation invocation) throws Exception {
loggedUser = (LoggedUser) invocation.getInvocationContext().getSession().get(LoggedUser.SESSIONTOKEN);
if(loggedUser==null || !loggedUser.isLogged()){
logger.info("loggedUser not present in session");
return "login";
}
return invocation.invoke();
}
request.getSession().setAttribute(LoggedUser.SESSIONTOKEN, loggedUser);
@凌驾
公共字符串截获(ActionInvocation调用)引发异常{
loggedUser=(loggedUser)invocation.getInvocationContext().getSession().get(loggedUser.SESSIONTOKEN);
if(loggedUser==null | |!loggedUser.isLogged()){
logger.info(“loggedUser不在会话中”);
返回“登录”;
}
返回invocation.invoke();
}
在行动中
@Override
public String intercept(ActionInvocation invocation) throws Exception {
loggedUser = (LoggedUser) invocation.getInvocationContext().getSession().get(LoggedUser.SESSIONTOKEN);
if(loggedUser==null || !loggedUser.isLogged()){
logger.info("loggedUser not present in session");
return "login";
}
return invocation.invoke();
}
request.getSession().setAttribute(LoggedUser.SESSIONTOKEN, loggedUser);
request.getSession().setAttribute(LoggedUser.SESSIONTOKEN,LoggedUser);
如果我不能让它与DI一起工作,我会像以前一样手动进行会话。但是这次我真的想知道我错过了什么使它工作。我也这么做了…你能为注释@Inject添加导入吗?S2也有一个@Inject。我尝试了你的解决方案。问题是,该对象从未从因此,当会话被破坏时,用户总是连接到事件。