首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java Web开发 >

心急如焚啊再次提问,session过期后,为什么数据还存在?该怎么解决

2012-03-01 
心急如焚啊,再次提问,session过期后,为什么数据还存在?!在维护一个系统(struts1+jdbc),测试时在web.xml中

心急如焚啊,再次提问,session过期后,为什么数据还存在?!
在维护一个系统(struts1+jdbc),测试时在web.xml中设置了session过期时间是2分钟,首先,从登录页面中输入用户名、密码后,会到loginAction.do进行验证,然后导向页面index.jsp,2分钟后,index.jsp中的一些链接页面,如果点击的话,会显示请重新登录,session过期的一个页面,但是,我只要一刷新index.jsp页面,这些链接马上又可以用了,这是loginAction.do的代码 :

public class LoginAction extends DispatchAction
{
  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res)
  throws Exception
  {
   
  DynaActionForm myForm = (DynaActionForm)form;
  Map map = myForm.getMap();
  String loginName = map.get("loginName").toString().trim();
  String password = map.get("password").toString().trim();
   
  
  ILogin login = (ILogin)Class.forName(get(map, "loginImplClass")).newInstance();  
  login.setLoginParam(loginName, password);

  try
  {
  LoginResult result = login.login();

  ……(这里就是一些赋值操作)
   
  LoginInfo loginInfo = result.getLoginInfo();
   
   
  HttpSession session = req.getSession(true);  
  session.setAttribute("sUserName", loginInfo.getUserName());
  session.setAttribute("sDeptName", loginInfo.getDeptName());
   
  String key = session.getId();
   
  ……(这里是一些赋值操作 )
   
  synchronized(getServlet().getServletContext())
  {
  try{
  javax.servlet.GenericServlet slt = getServlet();
  javax.servlet.ServletContext sc = slt.getServletContext();
  ((Hashtable)(sc.getAttribute("aVisitedUser"))).put(key, loginInfo);
  beidian.com.commonpub.UserManager.onlineUser.put(key, loginInfo);
  }
  catch(Exception e)
{
  logger.info("aOnlineUser", e);
  e.printStackTrace();
}
  }
   
   
  }
  catch(LoginException le)
  {  
  return mapping.findForward("failed");
  }
  catch(LockException le)
  {  
  return mapping.findForward("locked");
  }
   
  return mapping.findForward("success");
  }
}
其中beidian.com.commonpub.UserManager的代码如下:(这个代码应该没什么吧)
public class UserManager {
  public static java.util.Hashtable onlineUser = new java.util.Hashtable();
  public UserManager() {
  }

  public static void main(String[] args) {
  UserManager usermanager = new UserManager();
  }
}


请各位高人指点……

[解决办法]
我觉得:

虽然 session 过期了, 但是数据依然存在缓存中. 它可能使用的获得 session 的方式可能是 true 的形式, 就是没有session我就重新申请一个.

解决办法:

1. 写一个 session 销毁监听, 当 destory 时, 在代码中我们将用户的信息从 session 中 remove 掉. 

3. 最重要的一步, 写一个 servlet 过滤器, 对指定的资源进行过滤, 在这段代码中, 我们使用以下几步

1),HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);

注意这个参数是 false, 就是当 session 不存在的时候会返回 null, 不会再申请新的 session.

2),

Java code
        if (session!=null){            if (session.getAttribute("user")!=null) {                isLogin = true;            }        }
[解决办法]
如果你login后是forward到index.jsp,刷新index.jsp就相当于重新登陆了一次,当然就能继续显示了。登录后最好用redirect


[解决办法]
呃…… 之前看过servlet规范,就算session过期,如果使用该session的所有的servlet service()方法没有执行完毕,那么过期时间的无效化就不会产生作用。恐怕楼主要研究一下DispatchAction中的源码才能找到满意的答案了。还有String key = session.getId(); 这条语句也让人在意,因为后面将其引用到了servletcontext。不知道有没有影响。哈哈。说的话跟没说的一个样。
[解决办法]
在JSP页面加下面清除缓存代码试下看看:
<%
response.setHeader("Pragma", "No-cache"); 
response.setHeader("Cache-Control", "no-cache"); 
response.setDateHeader("Expires", 0);
%>
[解决办法]
刷新的时候,你之前post提交的数据也会再次提交,当然可以取到用户名和密码了。

[解决办法]
刷新一下,就重复提交一下之前那个表单。所有你得用令牌来阻止重复提交.
[解决办法]

探讨
刷新的时候,你之前post提交的数据也会再次提交,当然可以取到用户名和密码了。

[解决办法]
刷新的时候,你之前post提交的数据也会再次提交

恩,这个结论有道理。url地址中存在用户名和密码,刷新后相当于重新登录。
[解决办法]
刷新一下页面,相当于重新提交了一次登陆请求(loginAction.do),你可以使用struts的validate.或者打开首页为重定向方式。
[解决办法]
学习中,
[解决办法]
学习
[解决办法]
study
[解决办法]
study

[解决办法]
刷新就是重新提交了表单,再次登录了,当然新的session产生了!
[解决办法]
原因很简单,因为楼主使用Forward方式重定向.
Forward的特点是:
请求过程中使用同一个request对象.

既然是同一个request对象,自然登录时使用的用户名和口令也保存在登录后的请求中

此时刷新,会使用上次的表单信息进行form的submit动作,自然就相当于重新登录了

解决的办法有两种:
1.使用struts的"令牌"机制,这个机制是专门用来解决重复的数据提交问题的
2.简单的使用response对象的sendRedirect方法取代forward方法,重定向到首页

redirect会使用新的request对象发起请求,之前提交的表单数据全部失效,自然就不会再有问题了.
[解决办法]
如果用户对一个html表单多次提交,web应用应该能够判断用户的重复提交行为,并作出相应的处理。 

最常见的是新增一条数据,用户已经提交表单并且服务器端已经完成新增成功。此时用户可能有两个误操作: 
1.用户通过浏览器的后退功能,返回到录入页面,重复提交(此时浏览器提供回退功能基本上是个邪恶行为) 
2.刷新该页面(因为新增成功的提示页面通常是通过请求转发(forward)过来的,所以此操作实际效果通常等同于1) 

这样造成的可能结果有: 
1.若程序级别和数据库级别限制了重复记录,会提示类似于“xxx字段已存在,请修改后重新保存”的信息 
2.若没有此限制,服务器端会再插入一条数据,而这通常不是用户想要的 

误操作2和可能结果2的结合就达成了与用户意图相背的结果:服务器端不停地在增加重复记录,用户认为自己只不过是刷新该提示信息页面。 

通用的解决思路是: 
用户请求录入页面,这个与服务器建立的一次连接过程中,在服务器端①【生成一个session标识,同时返回到客户端一个与此匹配的hidden域】。用户提交了此页面,服务器端首先②【判断此hidden域与session标识是否匹配】,若不匹配,终止保存操作,提示同一表单不能提交两次,同时①【新建一个session标识和hidden域】,返回录入页面;若匹配,执行插入保存操作,同时③【清空(重置reset)session标识】。 

Struts正在基于这样的思路在org.apache.struts.action.Action类中提供了内置支持方法: 
java代码: 

protected void saveToken(HttpServletRequest request) 配合标签对应于① 
protected boolean isTokenValid(HttpServletRequest request) 对应于② 
protected void resetToken(HttpServletRequest request) 对应于③

这样我们在写程序的时候,结合Struts的html标签,只要 
1.在forward到insert.jsp页面前加一个action执行saveToken(request)操作,或干脆在insert.jsp中写 
2.保存前加个判断操作isTokenValid(request) 
3.若isTokenValid(request)返回false,执行saveToken(request)操作,返回错误提示页面;true则执行resetToken(request)操作,然后进行实际的保存操作


Java code

   进入创建前的Actionpublic final class EnterNewProjectPageAction extends Action {        public ActionForward execute(ActionMapping mapping, ActionForm form,                        HttpServletRequest request, HttpServletResponse response)                        throws Exception {                                        saveToken(request);                                return (mapping.findForward("createproject_jsp"));        }}// 创建Actionpublic final class CreateProjectAction extends Action {        public ActionForward execute(ActionMapping mapping, ActionForm form,                        HttpServletRequest request, HttpServletResponse response)                        throws Exception {                                        if(isTokenValid(request)){                        resetToken(request);                                                CreateProjectForm createProjectForm=(CreateProjectForm)form;                                Project newProject=createProjectForm.getProject();                                                newProject.setCreateTime(Util.getCurrTime());                                ProjectService.create(newProject);                                                }                else{                                                System.out.println("重复提交");                }                                        ProjectUtil.setupPages(0,request);                return (mapping.findForward("projects_jsp"));        }}
[解决办法]

哈哈。。。我觉得yys79 的答案是正解。。。你一刷新又发送了一次表单数据进行了验证,
楼主可以在Action中输出语句试一下...

我也觉得应该用重定向到跳转页面,而不该用转发。。forward...
[解决办法]
1、加个防重复提交代码,Struts里面有的
2、Action中跳转时,不要使用mapping.findForward()方式跳转,跳转时候,用return new ActionForward("URL",true);
3、在页面上加上判断session,为空,则session失效
[解决办法]
楼主应该好好的学习一下forward和Redirect这两种转发方式,之前我们的项目也是遇到像你这样的问题。

有2种方式去解决,
1.登陆验证完毕后,将用户信息放入Session,再重定向,也就是Redirect
2.我自己写了一个类似的令牌机制

Java code
package cn.net.ssd.pubUtil;import java.util.ArrayList;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/** *  * @author 大米辉 Mar 26, 2009 * @project SSD_ZH_ALARM * */public class CheckToken{    /**     * 检测是否是重复提交     * @param request     * @param reset 保存令牌     * @return     *//*    public static boolean isTokenValid(HttpServletRequest request,boolean reset){        boolean rs=true;        HttpSession session =request.getSession();        Object token=session.getAttribute("isValid");        if(token!=null){            String isValid=token.toString();            if(isValid.equals("1")){                rs=true;            }        }else{            rs=false;        }        if(reset){            saveToken(request);        }                return rs;    }        *//**     * 保存令牌     * @param request     *//*    public static void saveToken(HttpServletRequest request){        HttpSession session =request.getSession();        session.setAttribute("isValid","1");    }        *//**     * 重置Token     * @param request     *//*    public static void resetToken(HttpServletRequest request){        HttpSession session =request.getSession();        if(session.getAttribute("isValid")!=null){            session.removeAttribute("isValid");        }            }*/        private static final String TOKEN_LIST_NAME = "tokenList";    public static final String TOKEN_STRING_NAME = "token";    @SuppressWarnings("unchecked")    private static ArrayList<String> getTokenList(HttpSession session) {       Object obj = session.getAttribute(TOKEN_LIST_NAME);       if (obj != null) {          return (ArrayList<String>) obj;       } else {          ArrayList<String> tokenList = new ArrayList<String>();          session.setAttribute(TOKEN_LIST_NAME, tokenList);          return tokenList;       }    }    /**     * 保存令牌字符串     * @param tokenStr     * @param session     */    private static void saveTokenString(String tokenStr, HttpSession session) {       ArrayList<String> tokenList = getTokenList(session);       tokenList.add(tokenStr);       session.setAttribute(TOKEN_LIST_NAME, tokenList);    }    /**     * 得到令牌字符串     * @param tokenStr     * @param session     */    private static String generateTokenString(){       return new Long(System.currentTimeMillis()).toString();    }    /**      * Generate a token string, and save the string in session, then return the token string.     *      * @param HttpSession     *            session     * @return a token string used for enforcing a single request for a particular transaction.     */    public static String getTokenString(HttpSession session) {       String tokenStr = generateTokenString();       saveTokenString(tokenStr, session);       return tokenStr;    }    /**      * check whether token string is valid. if session contains the token string, return true.      * otherwise, return false.     *      * @param String     *            tokenStr     * @param HttpSession     *            session     * @return true: session contains tokenStr; false: session is null or tokenStr is id not in session     */    public static boolean isTokenStringValid(String tokenStr, HttpSession session) {       boolean valid = false;       if(session != null){          ArrayList<String> tokenList = getTokenList(session);          if (tokenList.contains(tokenStr)) {             valid = true;             tokenList.remove(tokenStr);          }       }       return valid;    }    public static boolean isTokenValid(HttpServletRequest request){        return isTokenStringValid(request.getParameter(CheckToken.TOKEN_STRING_NAME), request.getSession());    }} 

热点排行