广告弹窗后台管理bug修改,定时任务编写:
任务:
广告弹窗bug修改:
改:修改页面广告位置回显
定时任务编写:
(1)发布精选:
需求:
一个小时执行一次:将精选表album_top中发布时间publish_time在当前时间之前一个小时到当前时间内的记录的status改成已发布状态,并且进行小米消息推送
(2)用户积分核查:
需求:
每天执行一次:查找前一天用户做每日任务超过了最大次数的错误记录,并记录下来
问题:
1:考虑到服务器重启的话,lastTime会为null
解决方案:在京台代码块中做判断,如果lastTime为null,就把lastTime设为当天零点
static { if (lastTime == null) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.MILLISECOND, 0); lastTime = cal.getTime(); } }此方法是十二小时制的,如果当前时间是0-12点时lastTime则为当天零点,如果时12-24点时lastTime则为当天12:00
2:properties取值取不到,配置文件问题
解决方案:修改spring-common配置文件
收获:
1.方法名要取得有标示度,Mapper中的id取名尽量规范:取一条的时候用get开头,取list的时候用find开头2.Dto和Vo中的属性取名尽量规范,is开头的一般是boolean型,有多个值的一般用Integer类型
3.定时任务配置文件spring-quartz
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 定时任务的配置文件 --> <!-- 第1步和第4步公用,2、3步需要自定义 --> <!-- 第一步:启动定时任务 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <!-- 这里可以定义多个定时任务的Bean,每一个定时任务配置一个bean --> <ref bean="albumTopPublishActJobTask"/> <!-- 预存话费的定时任务 --> <!-- <ref bean="prestoreTask"/> --> <ref bean="userScoreCheckActJobTask"/> </list> </property> </bean> <!-- 第二步 调度act定时任务,每1分钟轮询一次,这里的id属性就是第一步定义的bean属性 --> <bean id="albumTopPublishActJobTask" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="albumTopPublishActJobMethod"/> <!--<property name="cronExpression" value="0/5 * * * * ?"/>--> <property name="cronExpression" value="0 0 * * * ?"></property><!--每小时执行一次--> </bean> <bean id="userScoreCheckActJobTask" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="userScoreCheckActJobMethod"/> <property name="cronExpression" value="0/5 * * * * ?"/> <!--<property name="cronExpression" value="0 0 0 * * ?"></property><!–每天执行一次–>--> </bean> <!-- 第三步 配置act定时任务所引用的Bean和方法名,这里的id即为第二步的返回ref属性--> <!--<bean id="actJobMethod" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.ibbpp.business.job.AlbumTopUpdateJob" /> </bean> --> <bean name="albumTopPublishActJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <ref bean="albumTopPublishQuartzTask"/> </property> <!-- 调用类中的方法 --> <property name="targetMethod"> <value>execute</value> </property> <property name="concurrent" value="false"/> </bean> <bean name="userScoreCheckActJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <ref bean="userScoreCheckQuartzTask"/> </property> <!-- 调用类中的方法 --> <property name="targetMethod"> <value>execute</value> </property> <property name="concurrent" value="false"/> </bean> <!--第四步 处理定时任务的Bean--> <bean id="albumTopPublishQuartzTask" class="com.ibbpp.business.job.AlbumTopPublishJob"> </bean> <bean id="userScoreCheckQuartzTask" class="com.ibbpp.business.job.UserScoreCheckJob"> </bean> </beans>4.定时任务执行类
package com.ibbpp.business.job; /*import com.nicemother.sns.common.Constant; import com.nicemother.sns.persistence.AnswerMapper; import com.nicemother.sns.persistence.BatchProcessDao;*/ import com.alibaba.fastjson.JSONObject; import com.ibbpp.base.commons.Constants; import com.ibbpp.business.dao.AlbumTopDao; import com.ibbpp.business.entity.AlbumTop; import com.ibbpp.business.entity.PushMsg; import com.ibbpp.business.service.MsgPushService; import org.json.simple.parser.ParseException; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; //import org.json.simple.JSONObject; public class AlbumTopPublishJob {//todo private static Logger logger = LoggerFactory.getLogger(AlbumTopPublishJob.class); private static Date lastTime; private static boolean done = true; //如果lastTime为null时,把lastTime设为当天零点 static { if (lastTime == null) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.MILLISECOND, 0); lastTime = cal.getTime(); } } @Autowired private AlbumTopDao albumTopDao; @Autowired private MsgPushService msgPushService; public void execute() throws JobExecutionException { logger.info("AlbumTopPublishJob start! lastTime={}" + lastTime); if (!done) { logger.info("AlbumTopPublishJob skip!"); return; } done = false; try { Date curDate = new Date(); //保证任务执行期间的数据,在下一次执行时被处理。 albumTopPublishAndPush(curDate); lastTime = curDate; } catch (Exception e) { logger.error("AlbumTopPublishJob fail! errorMsg={}" + e.getMessage(), e); } done = true; logger.info("AlbumTopPublishJob end! lastTime={}" + lastTime); } private void albumTopPublishAndPush(Date curDate) throws IOException, ParseException { TODO: 16/7/26 albumTopDao.updateStatus(curDate, lastTime); AlbumTop albumTop = albumTopDao.getAlbumTop(curDate, lastTime); albumTopPush(albumTop); } private void albumTopPush(AlbumTop albumTop) throws IOException, ParseException { if (albumTop == null) { return; } PushMsg pushMsg = new PushMsg(); pushMsg.setTitle(Constants.PUSH_MSG_TITLE); pushMsg.setContent(albumTop.getDescription()); pushMsg.setTargetType(Constants.PUSH_MSG_TATGET_TYPE); Map targetExtraMap = new HashMap(); targetExtraMap.put("albumId", albumTop.getAlbumId()); String targetExtra = JSONObject.toJSONString(targetExtraMap); //将字符串{“id”:1} pushMsg.setTargetExtra(targetExtra); msgPushService.broadcast(pushMsg,Constants.PUSH_TOPIC); } }done的默认值为true
进入方法先做判断:如果done不为true,就跳出任务
if (!done) { logger.info("AlbumTopPublishJob skip!"); return; }如果done为true,则在执行任务前将其设为false
done = false;然后执行任务,如果成功之行则将lastTime设为当前时间再将done设为true,此处的lastTime放在try里面,这样是为了保证lastTime只在任务成功之行时才能被赋值为当前时间,若放在try外面,则如果任务抛出异常,lastTime也会被赋值为当前时间,这样是错误的
try { Date curDate = new Date(); //保证任务执行期间的数据,在下一次执行时被处理。 albumTopPublishAndPush(curDate); lastTime = curDate; } catch (Exception e) { logger.error("AlbumTopPublishJob fail! errorMsg={}" + e.getMessage(), e); } done = true;5.sql语句收获
left jion效率较低,一千条以内的记录可以考虑使用,但不建议,毕竟记录会越来越多,所有连接查询都能拆,通常是以遍历的方式再查询一次,group by使用
private void userScoreCheck(Date curDate) { List<ScoreTask> scoreTaskList = scoreTaskDao.queryByLimitScope(Constants.SCORE_CHECK_TASK_LIMITSCOPR); TODO: 16/7/30 if (scoreTaskList == null || scoreTaskList.isEmpty()) { return; } for (ScoreTask scoreTask : scoreTaskList) { Long taskId = scoreTask.getId(); int limitMax = scoreTask.getLimitMax(); List<UserScoreDto> userScoreDtoList = userScoreDao.queryForCheck(curDate, lastTime, taskId, limitMax); if (null == userScoreDtoList || userScoreDtoList.isEmpty()) { return; } for (UserScoreDto userScoreDto : userScoreDtoList) { if (userScoreDto == null) { return; } UserScoreCheck userScoreCheck = transform(curDate, userScoreDto); userScoreCheckDao.add(userScoreCheck); } } }
<select id="queryForCheck" resultMap="BaseResultMap"> SELECT us.user_id,us.task_id,count(us.id) as record_count FROM user_score us <where> create_time > #{lastTime,jdbcType=TIMESTAMP} and create_time <= #{curDate,jdbcType=TIMESTAMP} <if test="taskId != null "> and task_id=#{taskId,jdbcType=BIGINT} </if> </where> group by user_id <if test="limitMax!=null"> HAVING count(id)>#{limitMax,jdbcType=BIGINT} </if> </select>