NutzCN Logo
问答 请教一个关于定时任务的问题
发布于 2124天前 作者 码农 1885 次浏览 复制 上一个帖子 下一个帖子
标签:

系统要求在后台写一个定时退出任务,使用token从远程获取用户信息,有一个问题就是我需要在后台写一个定时退出任务,我的token应该怎么存呢?String _token = SysLoginController.loginToken;这样存静态变量的只能存一个,或者用静态变量list之类,怎么去标识呢?一开始没想好,以为可以获取到session,但是后来发现没有定时器中无法获取req、resp这些东西,这下苦恼了,不知道怎么弄了,求大神指点迷津

            System.err.println("=====后台检测token====开始检测token=========");
            String _token = SysLoginController.loginToken;
            //Object _token = session.getAttribute("token");
            String token = _token.toString();
            StringBuffer buffer = new StringBuffer();
            String url = "http://172.16.64.72:8090/bam/identity/json/attributes?subjectid="+token;
            URI uri = new URI(url);
            URL urls = uri.toURL();
            HttpURLConnection connection = (HttpURLConnection) urls.openConnection();
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Charset", "utf-8");
            connection.setRequestMethod("GET");
            connection.connect();
            int responseCode = connection.getResponseCode();
            if(responseCode==401 || responseCode!=200){
               //loginController.logout();
                loginController.doOut();
            }else{
                InputStream inputStream = connection.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String str = null;
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
                bufferedReader.close();
                inputStreamReader.close();
                // 释放资源
                inputStream.close();
                connection.disconnect();
                String str1 = buffer.toString();
                System.err.println(str1);
                JSONObject jsonObject = new JSONObject(str1);
                JSONArray attributes = jsonObject.getJSONArray("attributes");
                String s = attributes.get(0).toString();
                JSONObject jsonObject1 = new JSONObject(s);
                JSONArray values = jsonObject1.getJSONArray("values");
                Object username = values.get(0);
                if (null==username){
                    loginController.doOut();
                }
            }
56 回复

从远程获取用户信息是啥意思

印象中你问过好多次了,一直不知道你到底做什么,把具体需求描述一下?

@wendal
http://172.16.64.72:8090/bam/identity/json/attributes?subjectid="+token
我们系统是这样从远程去获取当前登录的用户信息,以便于我们这边进行登录,一个简易的单点登录吧,
然后我现在需要做一个后台的定时任务,定时检测这个token是不是能够成功的获取到用户信息,获取不到就说明这个用户已经退出了,我的系统也需要进行退出,我遇到的问题是不知道该怎么存储这个token,因为可能会有十几个用户一起登录,token都是不一样的

做个map不就好了?

@wendal
我现在也是在考虑用map,我直接用登录名作为key,这样可以保证不会重复,但是在定时器中如何获取map的key呢?
nutMap.setv(username.toString(),token);

private void checkLoginOut(){
        try {
            System.err.println("=====后台检测token====开始检测token=========");
            NutMap nutMap = SysLoginController.nutMap;
            //Object _token = session.getAttribute("token");
            String token = _token.toString();
            StringBuffer buffer = new StringBuffer();
            String url = "http://172.16.64.72:8090/bam/identity/json/attributes?subjectid="+token;
            URI uri = new URI(url);
            URL urls = uri.toURL();
            HttpURLConnection connection = (HttpURLConnection) urls.openConnection();
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Charset", "utf-8");
            connection.setRequestMethod("GET");
            connection.connect();
            int responseCode = connection.getResponseCode();
            if(responseCode==401 || responseCode!=200){
               //loginController.logout();
                loginController.doOut();
            }else{
                InputStream inputStream = connection.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String str = null;
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
                bufferedReader.close();
                inputStreamReader.close();
                // 释放资源
                inputStream.close();
                connection.disconnect();
                String str1 = buffer.toString();
                System.err.println(str1);
                JSONObject jsonObject = new JSONObject(str1);
                JSONArray attributes = jsonObject.getJSONArray("attributes");
                String s = attributes.get(0).toString();
                JSONObject jsonObject1 = new JSONObject(s);
                JSONArray values = jsonObject1.getJSONArray("values");
                Object username = values.get(0);
                if (null==username){
                    loginController.doOut();
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
            loginController.logout();
        } catch (IOException e) {
            e.printStackTrace();
            loginController.logout();
        }catch (Exception e){
            e.printStackTrace();
            loginController.logout();
        }
    }

@wendal
大神,又想到什么解决方法吗?或者这个map的key设置成什么别的?

Map<String, String> 用户名做key,token做value

private void checkLoginOut()
这么存的话,checkLoginOut这个方法里我不知道该怎么获取用户名啊,

登录的时候把用户名记起来呗

@wendal
直接把token存list,然后遍历着检测,这样会不会靠谱一点啊。。。

为啥不靠谱?

@wendal
定时器中可以用这个吗?

Sender.setup(null);
        Future<Response> send = Sender.create(url).send(new Callback<Response>() {
            Stopwatch sw=  Stopwatch.begin();
            @Override
            public void invoke(Response res) {
                sw.stop();
                res.getContent();
                int status = res.getStatus();
                System.err.println(status);
                System.err.println(String.format("线程[%s] %s", Thread.currentThread().getName(), sw.toString()));
            }
        });
        Sender.shutdown();

先说说为啥不靠谱

担心循环遍历消耗性能

业务都完成不了还担心性能?远不是那个时候

有点慌啊,先说说这个能在定时器里面用不?

Sender.setup(null);
        Future<Response> send = Sender.create(url).send(new Callback<Response>() {
            Stopwatch sw=  Stopwatch.begin();
            @Override
            public void invoke(Response res) {
                sw.stop();
                res.getContent();
                int status = res.getStatus();
                System.err.println(status);
                System.err.println(String.format("线程[%s] %s", Thread.currentThread().getName(), sw.toString()));
            }
        });
        Sender.shutdown();

Sender.setup(null); 只应该全局调用一次,Sender.shutdown不要调用

for
(){
Future send = Sender.create(url).send(new Callback() {
Stopwatch sw= Stopwatch.begin();
@Override
public void invoke(Response res) {
sw.stop();
res.getContent();
int status = res.getStatus();
System.err.println(status);
System.err.println(String.format("线程[%s] %s", Thread.currentThread().getName(), sw.toString()));
}
});
}

@wendal
quartz这个梗,有时候执行,有时候不执行,有时候执行一次后就不执行了,什么梗啊,兄弟

之前的问题解决了?

@wendal
如果quartz正常执行就解决了,现在quartz在找茬啊,一会执行一会不执行的。。。

把quartz日志调到debug级别,观察之

额。。。有点尬尴,不知道在哪设置这个日志级别。。。。。

log4j了解一下?

log4j.logger.org.quartz=DEBUG ?

Found 0 triggers that missed their scheduled fire-time
焦躁不安。。。

cron表达式写错了吧?

private void CheckLoginOut(NutConfig config, Dao dao) {
        // 首先,必需要取得一个Scheduler的引用
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = null;
        Date ft = null;
        try {
            sched = sf.getScheduler();
            JobDetail job = JobBuilder.newJob(LoginOutJob.class).withIdentity("logout", "logoutGroup").build();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("logoutTrigger", "logoutGroup")
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")).build();
            ft = sched.scheduleJob(job, trigger);                                           //十秒执行一次   0/10 * * * * ?   测试用
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

不死不行啦,竟然每次新建一个quartz实例

@wendal 早,这个是改写nutzwk里面的,基本代码没怎么变动,
你上面提到的问题是因为这个吗?

SchedulerFactory sf = new StdSchedulerFactory();

还是这个?

JobDetail job = JobBuilder.newJob(LoginOutJob.class).withIdentity("logout", "logoutGroup").build();

我不信nutzwk里面有你说这行

SchedulerFactory sf = new StdSchedulerFactory();

@wendal
事实证明真的有。。。。

/**
	 * 定时删除上三个月数据
	 */
	private void delLogs(NutConfig config, Dao dao) {
		// 首先,必需要取得一个Scheduler的引用
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler sched = null;
		Date ft = null;
		try {
			sched = sf.getScheduler();
			JobDetail job = JobBuilder.newJob(DelLogsJob.class).withIdentity("job1", "group1").build();
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
					.withSchedule(CronScheduleBuilder.cronSchedule("0 0 1 * * ?")).build();//每天凌晨一点执行0 0 1 * * ?  
			ft = sched.scheduleJob(job, trigger);                                           //十秒执行一次   0/10 * * * * ?   测试用
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}	

。。。 给nutzwk报个issue

额,这个应该是比较旧的版本有,后面的好像在初始化setup.java里面没有定时任务了,那这个StdSchedulerFactory可以注入吗?

注入Scheduler

SchedulerFactory sf = new StdSchedulerFactory();直接写到全局行不?

完蛋了。。。服务器内部调用这个会报错,

Subject currentUser = SecurityUtils.getSubject();
                Sys_user user = (Sys_user) currentUser.getPrincipal();
                currentUser.logout();

当然不是取当前用户, 而且根据session id获取shiro的session对象,然后注销掉

听着好像很复杂的样子。。。

Subject requestSubject = new Subject.Builder().sessionId(sessionId).buildSubject();

@wendal
所以在登录的时候还得去记录sessionId?

你的token就是session id吧?

不是的,token另外一个系统发过来的东西,拼接在url后面来获取用户信息的,

那就只能记session id了吧

如果这样重定向跳转方法行得通吗?

 @At
    @Ok("re")
    public Object doOut(){
        return "/platform/login/logout";
    }
 /**
     * 退出系统
     */
    @At
    @Ok(">>:/platform/login")
    public void logout() {
        try {
                Subject currentUser = SecurityUtils.getSubject();
                Sys_user user = (Sys_user) currentUser.getPrincipal();
                currentUser.logout();
                //退出后清空cookie

                if (user != null) {
                    userService.update(Chain.make("isOnline", false), Cnd.where("id", "=", user.getId()));
                    sysOperateLogService.insertOperateLog(StringUtil.getRemoteAddr(), "退出", "成功退出系统", "用户退出系统", "系统操作日志", user.getId(),user.getUsername(),"3e967b028ba44a6c942b396e530df526");
                }
        } catch (SessionException ise) {
            log.debug("Encountered session exception during logout.  This can generally safely be ignored.", ise);
        } catch (Exception e) {
            log.debug("Logout error", e);
        }
    }

顺便问一下,shiro的session多久过期?

配置文件里面有

来来来,https://github.com/Wizzercn/NutzWk
@qq_0d17d15e 请你给指出来哪里有你说的这段代码?

SchedulerFactory sf = new StdSchedulerFactory();

@Wizzercn 新版本的没有了,我这边用的是比较旧的版本,

@wendal
很尴尬啊,怎么注销那么难搞呢,再去记录一次sessionId也很麻烦啊

@qq_0d17d15e 来,所有的commits记录都在,你能在提交记录里找出这段代码出来,我就认你做大哥~~~

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