定时获取微信的 AccessToken

发布于 2024-01-10 12:57:09 字数 14032 浏览 27 评论 0

使用 Quartz 2.2.3 开启定时任务,每个整点获取一次,如下:

String jobName = "GetWeixinAccessToken";
String triggerName = jobName;
// 每个整点执行一次
quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);

QuartzManager 使用 Spring 注入:

import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;

@Service
public class QuartzManager {
	public static SchedulerFactory schedulerFactory = new StdSchedulerFactory();  

	public void addJob(String jobName, String triggerName,
			Class jobClass, String cron, Object obj) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			// 任务名,任务组,任务执行类
			JobDetail jobDetail = JobBuilder.newJob(jobClass)
					.withIdentity(jobName).build();
			jobDetail.getJobDataMap().put("obj", obj);
			// 触发器
			TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
					.newTrigger();
			// 触发器名
			triggerBuilder.withIdentity(triggerName);
			triggerBuilder.startNow();
			// 触发器时间设定
			triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
			// 创建 Trigger 对象
			CronTrigger trigger = (CronTrigger) triggerBuilder.build();

			// 调度容器设置 JobDetail 和 Trigger
			sched.scheduleJob(jobDetail, trigger);

			// 启动
			if (!sched.isShutdown()) {
				sched.start();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	    /** 
	     * @Description: 添加一个定时任务 
	     *  
	     * @param jobName 任务名 
	     * @param jobGroupName  任务组名 
	     * @param triggerName 触发器名 
	     * @param triggerGroupName 触发器组名 
	     * @param jobClass  任务 
	     * @param cron   时间设置,参考 quartz 说明文档  
	     */  
	    @SuppressWarnings({ "unchecked", "rawtypes" })  
	    public void addJob(String jobName, String jobGroupName, 
	            String triggerName, String triggerGroupName, Class jobClass, String cron) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            // 任务名,任务组,任务执行类
	            JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();

	            // 触发器  
	            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
	            // 触发器名,触发器组  
	            triggerBuilder.withIdentity(triggerName, triggerGroupName);
	            triggerBuilder.startNow();
	            // 触发器时间设定  
	            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
	            // 创建 Trigger 对象
	            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

	            // 调度容器设置 JobDetail 和 Trigger
	            sched.scheduleJob(jobDetail, trigger);  

	            // 启动  
	            if (!sched.isShutdown()) {  
	                sched.start();  
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	/**
	 * 修改任务的触发时间
	 * @param jobName
	 * @param triggerName
	 * @param cron
	 */
	public void modifyJobTime(String jobName, String triggerName,
			String cron) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(cron)) {
				/** 方式一 :调用 rescheduleJob 开始 */
				// 触发器
				TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
						.newTrigger();
				// 触发器名,触发器组
				triggerBuilder.withIdentity(triggerName);
				triggerBuilder.startNow();
				// 触发器时间设定
				triggerBuilder.withSchedule(CronScheduleBuilder
						.cronSchedule(cron));
				// 创建 Trigger 对象
				trigger = (CronTrigger) triggerBuilder.build();
				// 方式一 :修改一个任务的触发时间
				sched.rescheduleJob(triggerKey, trigger);
				/** 方式一 :调用 rescheduleJob 结束 */

				/** 方式二:先删除,然后在创建一个新的 Job */
				// JobDetail jobDetail =
				// sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
				// Class<? extends Job> jobClass = jobDetail.getJobClass();
				// removeJob(jobName, jobGroupName, triggerName,
				// triggerGroupName);
				// addJob(jobName, jobGroupName, triggerName, triggerGroupName,
				// jobClass, cron);
				/** 方式二 :先删除,然后在创建一个新的 Job */
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	    /** 
	     * @Description: 修改一个任务的触发时间
	     *  
	     * @param jobName 
	     * @param jobGroupName
	     * @param triggerName 触发器名
	     * @param triggerGroupName 触发器组名 
	     * @param cron   时间设置,参考 quartz 说明文档   
	     */  
	    public void modifyJobTime(String jobName, 
	            String jobGroupName, String triggerName, String triggerGroupName, String cron) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
	            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);  
	            if (trigger == null) {  
	                return;  
	            }  

	            String oldTime = trigger.getCronExpression();  
	            if (!oldTime.equalsIgnoreCase(cron)) { 
	                /** 方式一 :调用 rescheduleJob 开始 */
	                // 触发器  
	                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
	                // 触发器名,触发器组  
	                triggerBuilder.withIdentity(triggerName, triggerGroupName);
	                triggerBuilder.startNow();
	                // 触发器时间设定  
	                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
	                // 创建 Trigger 对象
	                trigger = (CronTrigger) triggerBuilder.build();
	                // 方式一 :修改一个任务的触发时间
	                sched.rescheduleJob(triggerKey, trigger);
	                /** 方式一 :调用 rescheduleJob 结束 */

	                /** 方式二:先删除,然后在创建一个新的 Job  */
	                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));  
	                //Class<? extends Job> jobClass = jobDetail.getJobClass();  
	                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);  
	                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron); 
	                /** 方式二 :先删除,然后在创建一个新的 Job */
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	/**
	 * @Description: 移除一个任务
	 * 
	 * @param jobName
	 * @param triggerName
	 */
	public void removeJob(String jobName, String triggerName) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			sched.deleteJob(JobKey.jobKey(jobName));// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
 
	    /** 
	     * @Description: 移除一个任务 
	     *  
	     * @param jobName 
	     * @param jobGroupName 
	     * @param triggerName 
	     * @param triggerGroupName 
	     */  
	    public void removeJob(String jobName, String jobGroupName,  
	            String triggerName, String triggerGroupName) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  

	            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

	            sched.pauseTrigger(triggerKey);// 停止触发器  
	            sched.unscheduleJob(triggerKey);// 移除触发器  
	            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	    /** 
	     * @Description:启动所有定时任务 
	     */  
	    public static void startJobs() {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            sched.start();  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	    /** 
	     * @Description:关闭所有定时任务 
	     */  
	    public static void shutdownJobs() {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            if (!sched.isShutdown()) {  
	                sched.shutdown();  
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }
	    
	    /**
	     * 判断 JobName 是否在执行队列中
	     * @param jobName
	     * @return
	     */
	    public synchronized static boolean isJobExist(String jobName) throws SchedulerException {
	    	boolean isExistJob = false;
	    	Scheduler scheduler = schedulerFactory.getScheduler();
	    	for (String groupName : scheduler.getJobGroupNames()) {
	    		for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
	    				.jobGroupEquals(groupName))) {
	    			String tmpJobName = jobKey.getName();
	    			String jobGroup = jobKey.getGroup();
	    			// get job's trigger
	    			@SuppressWarnings("unchecked")
	    			List<Trigger> triggers = (List<Trigger>) scheduler
	    			.getTriggersOfJob(jobKey);
	    			Date nextFireTime = triggers.get(0).getNextFireTime();
	    			System.out.println("[jobName] : " + tmpJobName
	    					+ " [groupName] : " + jobGroup + " - "
	    					+ nextFireTime);
	    			if (tmpJobName.equals(jobName)) {
	    				return true;
	    			}
	    		}
	    	}
			return isExistJob;
	    }
}

在 Spring ApplicationContext 注入后,才可获取 bean,web.xml 配置拦截如下:

<!--Spring ApplicationContext 载入 -->
<listener>
	<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -->
	<listener-class>com.test.hello.ContextLoaderListenerOverWrite</listener-class>
</listener>

拦截类是为了获取 manager,然后存放 AccessToken 到数据库中。实现如下:

public class ContextLoaderListenerOverWrite extends ContextLoaderListener {

	@Override
	public void contextInitialized(ServletContextEvent event) {
		// TODO Auto-generated method stub
		super.contextInitialized(event);
		ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());  
      		startGetWeixinAccessTokenJobs(applicationContext);
	}
	/**
	 * 开启整点定时任务
	 */
	public void startGetWeixinAccessTokenJobs(ApplicationContext ctx) {
		WxBean currentBean = Utility.getAccessToken();
		WxAccesstoken currentToken = new WxAccesstoken();
		currentToken.setAccesstoken(currentBean.getAccess_token());
		currentToken.setExpiresIn(Integer.valueOf(currentBean.getExpires_in()));
		currentToken.setLastRequestTime(new Date());
		
		QuartzManager quartzManager = (QuartzManager)ctx.getBean("quartzManager");
		WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)ctx.getBean("wxAccesstokenManager");
		WxAccesstoken dbWxToken = wxAccesstokenManager.findFirst();
		if (dbWxToken == null) {	// 新增 Token
			wxAccesstokenManager.save(currentToken);
			System.out.println("新增 Token:" + currentToken);
		} else {	// 更新 Token
			currentToken.setId(dbWxToken.getId());
			wxAccesstokenManager.update(currentToken);
			System.out.println("更新 Token:" + currentToken);
		}
		String jobName = "GetWeixinAccessToken";
		String triggerName = jobName;
		// 每个整点执行一次
		quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);
	}
}

获取微信 AccessToken 的办法如下:

/**
 * 获取微信的 AccessToken
 * @return
 */
public static WxBean getAccessToken() {
	WxBean bean = null;
	Map<String, String> params = new HashMap<String, String>();
	params.put("grant_type", "client_credential");
	params.put("appid", Constants.WEIXIN_APPID);
	params.put("secret", Constants.WEIXIN_APPSECRET);
	try {
		String jstoken = HttpUtils.sendGet(
				"https://api.weixin.qq.com/cgi-bin/token", params);
		// String access_token = JSONObject.fromObject(jstoken).getString(
		// "access_token"); // 获取到 token 并赋值保存
		ObjectMapper objectMapper = JsonUtils.createObjectMapper();
		try {
			bean = objectMapper.readValue(jstoken, WxBean.class);
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return bean;
}

对了,还有关键的部分,在这个 Job 里面每个整点更新 AccessToken

public class WeixinAccessTokenJob implements Job{
	
	public WeixinAccessTokenJob() {
	}
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		//打印任务详情  
        System.out.println( "WeixinTokenJob:" + "-" +
                context.getJobDetail().getKey().getGroup() 
                +"——"+context.getJobDetail().getKey().getName()  
                +"——"+context.getTrigger().getKey().getName()  
                +"——"+context.getTrigger().getKey().getGroup() + new Date());
                JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
                WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)jobDataMap.get("obj");
		// Todo 使用 wxAccesstokenManager 来管理数据库存放的 AccessToken
	}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

故乡的云

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文