NutzCN Logo
问答 session 为null
发布于 2898天前 作者 qq_ff330a3f 4533 次浏览 复制 上一个帖子 下一个帖子
标签:

想问下兽总,我通过IOC容器获取我指定的一个对象的字符串,然后设置到session回话当中,为何有的时候会返回null呢?如果是session失效的话,那么我应该在哪里去看这个问题呢?

@At
    @Ok("jsp:front.index")
    @Fail("jsp:front.login")
    @Filters()
    public void toFrontIndex(HttpServletRequest resq, HttpSession session) {
        User user = (User) session.getAttribute("me");
        if (user != null) {
            resq.setAttribute("name", user.getUsername());
            resq.setAttribute("ismanager", user.getIsmanager());
            resq.setAttribute("code", user.getUsercode());
            resq.setAttribute("pwd", user.getPassword());
            resq.setAttribute("deptId", user.getDeptid());
            String appName = (String) Mvcs.ctx().getDefaultIoc().get(App.class, "app").getName();
            resq.setAttribute("appName", appName);
            session.setAttribute("appName", appName);
        }

    }
37 回复

是session为null,还是session的me属性为null?

@wendal 这就不知道了,那个me还有可能为空吗?兽总?如果不是的话,我也去看了看每个session的id,都是同一个呢。如果为空的话可能就是像你说的是me为空了。那么如果是这种情况该怎么半呢?

@qq_ff330a3f 那先确定什么是null

@wendal 好的,兽总,想问一句,如果me为null的话,那么可能是什么原因导致的呢?

如果是用容器本身的session, 而且id一样的话, 可能是请求顺序的问题. 就是设置这个attr的请求之前发起的请求,会得到null

@wendal 我这个session交给shiro管理了,而且我是先有个验证用户的操作之后才设置的me这个属性的session,理论上应该不存在顺序的问题

多加点日志, 打印一下session id和me的值

@wendal 好的,知道啦,实在不行我就那个静态常量来存储,每次一登陆的时候我重新给那个静态变量赋值,这样总不能还出错吧?

@wendal 我输出了一下,确实是那个me的属性没有了,那么我最好应该怎么去做呢?兽总?

@qq_ff330a3f 贴输出

起码得分析一下,设置me属性后,什么情况下没有

是部分没有还是全部没有?
设置时的session id与读取时的session id是否一直?

另外shiro.ini也贴一下

@wendal
代码:

@At
    public ResultWrap<List<Stationdetail>> getStationData(HttpServletRequest resq,HttpSession session){
        System.out.println("deptId is:"+resq.getParameter("deptId"));
        int deptId;
        //根据部门查询所包含的站点,并且拼接站点对应部门的ID
        if(!(resq.getParameter("deptId").isEmpty())){
            deptId = Integer.parseInt(resq.getParameter("deptId"));
        }else{
            User user = (User) session.getAttribute("me");
            deptId = user.getDeptid();
        }
//        List<String> arr = new ArrayList<>();
        //获取所包含的站点id集合
//        List<String> ids = deptOpService.getStationIds(arr, deptId);
        List<String> ids =  (List<String>) session.getAttribute("ids");
        List<Stationdetail> list = stationdetailOpService.getStationData(ids);
        for(Stationdetail station : list){
            station.setLon(changeLonlat(station.getLon())+"");
            station.setLat(changeLonlat(station.getLat())+"");
        }
        return new ResultWrap<List<Stationdetail>>(list, 0, "");
    }

输出:

Get 'deptOpService'<>
deptId is:
 WARN] 2017-01-16 02:33:10 (FailProcessor.java:process:28)
Error@/stationdetail/getStationData :
java.lang.NullPointerException
	at com.beyondb.rainsnow.modules.StationdetailModule.getStationData(StationdetailModule.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:25)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.integration.shiro.NutShiroProcessor.process(NutShiroProcessor.java:126)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
	at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
	at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
	at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
	at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:198)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)
DEBUG] 2017-01-16 02:33:10 (UrlMappingImpl.java:get:110)

说的不是toFrontIndex方法吗?怎么变了?

是打印一下session id和me的值,看看有什么规律.

@我很多地方都用到了seesion的这个属性。。。嗯嗯好的,我打印下看看。

@wendal

这是我的toFrontIndex方法:

 @At
    @Ok("jsp:front.index")
    @Fail("jsp:front.login")
    @Filters()
    public void toFrontIndex(HttpServletRequest resq, HttpSession session) {
        System.out.println("index sessionId is:"+session.getId());
        User user = (User) session.getAttribute("me");
        if (user != null) {
            resq.setAttribute("name", user.getUsername());
            resq.setAttribute("ismanager", user.getIsmanager());
            resq.setAttribute("code", user.getUsercode());
            resq.setAttribute("pwd", user.getPassword());
            resq.setAttribute("deptId", user.getDeptid());
            String appName = (String) Mvcs.ctx().getDefaultIoc().get(App.class, "app").getName();
            resq.setAttribute("appName", appName);
            session.setAttribute("appName", appName);
        }

    }

输出的sessionId 为:

index sessionId is:99D9834390496F6F05A7BBEFDBF44069

这是我的那个getStationData的方法:

@At
    public ResultWrap<List<Stationdetail>> getStationData(HttpServletRequest resq,HttpSession session){
        System.out.println("sessionId is:"+session.getId());
        int deptId;
        //根据部门查询所包含的站点,并且拼接站点对应部门的ID
        if(!(resq.getParameter("deptId").isEmpty())){
            deptId = Integer.parseInt(resq.getParameter("deptId"));
        }else{
            User user = (User) session.getAttribute("me");
            deptId = user.getDeptid();
        }
//        List<String> arr = new ArrayList<>();
        //获取所包含的站点id集合
//        List<String> ids = deptOpService.getStationIds(arr, deptId);
        List<String> ids =  (List<String>) session.getAttribute("ids");
        List<Stationdetail> list = stationdetailOpService.getStationData(ids);
        for(Stationdetail station : list){
            station.setLon(changeLonlat(station.getLon())+"");
            station.setLat(changeLonlat(station.getLat())+"");
        }
        return new ResultWrap<List<Stationdetail>>(list, 0, "");
    }

输出为:

sessionId is:99D9834390496F6F05A7BBEFDBF44069

ID是一样的。

@wendal 这是我的ini文件:

[main]
nutzdao_realm = com.beyondb.rainsnow.shiro.realm.SimpleAuthorizingRealm

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile=classpath:ehcache.xml
nutzdao_realm.cacheManager = $cacheManager

authc = org.nutz.integration.shiro.SimpleAuthenticationFilter
authc.loginUrl  = /user/login
logout.redirectUrl= /user/login


[urls]
/rs/*        = anon, noSessionCreation
/druid/*        = anon, noSessionCreation
/asserts/*        = anon, noSessionCreation
/user/logout = logout
/user/error  = anon
/user/profile/active/mail = anon
#/user/**     = authc

我在这个方法都输出了那个me,但是为null了,始终不知道为什么。。。

id一样,也得打印一下me的值嘛

index没报错只是因为判断了null,不代表就存在me值呢

... 我知道了

那是因为根本没放进session呢,你可以去翻一下登录入口,肯定没放

另外,既然用shiro的,就不需要用me了

@wendal 是这样,我登录入口那里确实没有放。。。
这是我的登录入口方法,

@At
    @Ok("jsp:front.login")
    @Filters()
    public void toFrontLogin(HttpServletRequest resq, HttpSession session) {
        String appName = (String) Mvcs.ctx().getDefaultIoc().get(App.class, "app").getName();
        resq.setAttribute("appName", appName);
        session.setAttribute("appName", appName);
    }

那么问题来了,我在登录的时候就是一个单纯的页面跳转,还没有用户的概念的。。我没有办法在那里设置me那个属性的,我后面还有一个验证的方法,如果验证成功之后才可以设置这个属性的。。。兽总,这种情况我该怎么办呢?

@qq_ff330a3f 验证的时候放进去,可以不?

额,验证之后放进,有什么问题吗?

@wendal 我那个验证还不是用的shiro的验证,是我自己写的一个,我那个登录的入口就是上面写的那个,只是一个页面跳转,然后到login.jsp之后有一个表单,提交表单后调用我那个自定义的验证方法,我在那里加的me属性。。。验证之后放进去就会出现你说的那种情况,就是为null了。。。

@qq_ff330a3f 那验证的时候,不执行shiro登录吗?

@wendal 是的,没有执行,只是我做的一个验证,并没有把用户交给shiro管理。我有一个进入后台的操作,点击进入后台的时候才会做shiro的身份认证。

@qq_ff330a3f 放进去的session id跟取出来时的session id是同一个?有点不敢相信→_→

@wendal 这是我自己写的验证方法:

@At
      @Filters()
    public Object authcUser(HttpServletRequest resq, HttpSession session, HttpServletResponse resp) {
        String status = resq.getParameter("status");//获取是否选中的状态
        String code = resq.getParameter("username");
        String password = resq.getParameter("password");
        User user = userOpService.authcUser(code, password);
        if (null != user) {
            List<String> arr = new ArrayList<>();
            //获取所包含的站点id集合
            List<String> ids = deptOpService.getStationIds(arr, user.getDeptid());
            //获取所包含的站点的sno集合
            List<String> snos = deptOpService.getStationSnos(arr, user.getDeptid());
            //获取所有站点编码和站点名称对应的map集合
            Map<String,String> snoMap = deptOpService.getSnoMap();
            if (status.equals("1")) {
                //创建两个Cookie对象
                Cookie nameCookie = new Cookie("username", code);
                //设置Cookie的有效期为3天
                nameCookie.setMaxAge(60 * 60 * 24 * 3);
                String key = "bjbeyondb";
                Cookie pwdCookie = new Cookie("password", CyptoUtils.encode(key, password));
                pwdCookie.setMaxAge(60 * 60 * 24 * 3);
                resp.addCookie(nameCookie);
                resp.addCookie(pwdCookie);
            }
            Cookie statusCookie = new Cookie("status", status);
            statusCookie.setMaxAge(60 * 60 * 24 * 3);
            resp.addCookie(statusCookie);
            session.setAttribute("me", user);
            session.setAttribute("ids", ids);//存储到session当中
            session.setAttribute("snos", snos);//存储到session当中
            session.setAttribute("snoMap", snoMap);

            resq.setAttribute("name", user.getUsername());
            resq.setAttribute("code", user.getUsercode());
            return new NutMap().setv("data", "success");
        } else {
            return new NutMap().setv("data", "fail");
        }
    }

然后是跳转到login.jsp执行的操作,:

 //点击登录按钮
            $("#loginBtn").on("click",function(){
                var username = $('input[name="username"]').val();
                var password = $('input[name="password"]').val();
                var status = $('input[name="rememberCk"]').val();
                if(username==''||password==''){
                    alert("用户名或密码为空,请重新输入!");
                    return;
                }
                //发送ajax请求判断是否用户已经登录并且跳转页面
                $.ajax({ 
                    url: "<%=basePath%>user/authcUser",
                    type:"POST",
                    data:{
                        "username":username,
                        "password":password,
                        "status":status
                    },
                    dataType:"json",
                    success: function(data){
                        if(data.data=="success"){
                            window.location.href = "<%=basePath%>user/toFrontIndex";
                        }else{
                            alert("该用户不存在,请重新登录!");
                            $('input[name="username"]').val("");
                            $('input[name="password"]').val("");
                            return;
                        }
                    }
                });
            });

@wendal 应该是登录入口的那个session跟其他地方的session不一样,而登录那里的session又没有me属性,所以才空了吧。。。问题是,我只要手动的把浏览器的路径改成一登陆时候的路径,重新登录之后就都出来了,但是在进行业务操作的时候就没准什么时候会出现null了、、、这个就不知道该怎么解决比较好了。我也认为就是我刷新的时候还是从登录那里从头来了一遍,如果那里没有,那么接下来的肯定也没有了。。。

因为那个cookie吗? session已过期,但cookie还是老的,所以访问的时候是新session

我觉得cookies应该没有影响,我刚才看了下浏览器的那个cookies自带的JSESSIONID,跟我刚才给你打印的数值都是一样的, 99D9834390496F6F05A7BBEFDBF44069。而且我用的是默认的半个小时,应该不至于失效那么快吧?

@qq_ff330a3f 重启过浏览器,所以瞬间过期?

@wendal 没有重启过浏览器,最多就是清除过cookies,还有就是我刚才也重新登录了一下,然后还是输出登录入口的那个session id,也是跟其他的id是一样的。。。

@wendal 兽总,我刚才做了这么一个操作,就是我在进行业务操作的时候清除了下浏览器的cookies,然后刷新的时候就null了。还有就是我觉得清除浏览器缓存的结果和session本身过期的结果是不是一样呢?那如果是的话,我是不是去做一个判断,判断当前这个sessionID对应的session还在不在,如果不在的话去重新登录一下?那么如果可以的话,我那些方法是不是都得写成返回view类型的了呢?T T

写个处理器

@wendal 什么意思呢?能简单指点一下吗,兽总?

添加回复
请先登陆
回到顶部