前言
之前做过一款APP观看历史时长记录功能,需求爸爸要求要实时记录观看时长。由于该项目是基于别人基础上开发发,APP观看视频每隔20s会请求端口保存数据。由于用户增多所以要"改接口"!结果…
一、当然要配置SpringMcv的定时任务文件了
废话不多说,直接上代码。
<?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:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<!-- 配置任务扫描 -->
<task:annotation-driven />
<!-- 扫描任务 这里配置你的定时类的路径-->
<context:component-scan base-package="com.yunxue.co.config" />
二、创建定时类
暂时瞎乱起个名字每15分钟执行一次任务
注意:类上边的注解要添加…
@Controller
@EnableScheduling
public void taskCycle() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String mapKey = "CoWatchhistory:" + "Watchhistorykey";
Map<String,String> map = new HashMap<>(16);
Map<String,String> mp = new HashMap<>(16);
Long time = System.currentTimeMillis();
map = redisProxy.hgetAll(mapKey);
Iterator it=map.keySet().iterator();
while(it.hasNext()){
String key=it.next().toString();
String value=map.get(key);
if (time - Long.parseLong(value) > 20*1000) {
it.remove();
logger.info("保存数据");
}
logger.info(key+"--"+value);
}
/**保存新的map到redis*/
mp = map;
redisProxy.del(mapKey);
if(mp.size() > 0){
redisProxy.hmset(mapKey,mp);
}
}
}
三、肯定是我们的Controller
这个应该全会写!!! ApiResponse是我封装的公共方法
@RequestMapping(value = "/addWatchClass", method = RequestMethod.GET)
public ApiResponse<> addWatchClass(@ApiParam(required = true, name = "partId", value = "课程小节id")){
Integer watchhistory;
try {
watchhistory= courseService.addWatchClass(taskItemId,partId, memberId,watchTime,watchType,taskId,whClassType,20,"Android");
}catch (Exception e) {
logger.error("获取概要信息异常!",e);
return new ApiResponse(ApiResponse.FAIL,e.getMessage(),null);
}
return ApiResponse.ok(bpmQuery);
}
四、我们接口层
这个更简单
public interface CourseService {
/**
* 提交课程观看进度
* @param partId 课程小节id
* @return
*/
Integer addWatchClass(nteger taskItemId,Integer partId, Integer memberId, Integer watchTime,Integer watchType,Integer taskId,Integer whClassType,Integer whTotalTime,String whSource) throws Exception;
五、到了我们具体实现了
重点来了…
/**引用redis*/
@Autowired
RedisProxy redisProxy;
/**jackson 转换json要用到*/
@Autowired
ObjectMapper objectMapper
/**
* 提交课程观看历史
*
* @param partId 课程小节id
* @param taskItemId 子任务id
* @param memberId 会员id
* @param watchTime 课程观看时长(秒)
* @param watchType 课程观看进入类型 1 任务进入 2 直接进入
* @param taskId 任务id
* @return
*/
@Override
public Integer addWatchClass(Integer taskItemId, Integer partId, Integer memberId, Integer watchTime, Integer watchType,
Integer taskId, Integer whClassType, Integer whTotalTime, String whSource) throws Exception {
/**生成当前用户观看的key*/
String historyKey ="CoWatchhistory:" + memberId.toString()+partId.toString()+watchType.toString();
String mapKey = "CoWatchhistory:" + "Watchhistorykey";
/**获取当前时间戳*/
Long time = System.currentTimeMillis();
Map<String,String> map = new HashMap<>(16);
try {
/**首先获取redis有没有map(当前请求接口的Key key保存在map中)*/
map = redisProxy.hgetAll(mapKey);
if(map.isEmpty() || !map.containsKey(historyKey)){
logger.info("新纪录");
/**将map保存到redis (map 保存key跟初始时间)*/
map.put(historyKey,time.toString());
redisProxy.hmset(mapKey,map);
/**将对象转换成json保存到redis*/
json = objectMapper.writeValueAsString(watchHistory( partId, memberId, watchTime, watchType,
time,classId,whClassType, whTotalTime, whSource));
redisProxy.set(historyKey,json);
}else{
logger.info("更新纪录");
CoWatchhistory coWatchhistory = objectMapper.readValue(redisProxy.get(historyKey),CoWatchhistory.class);
coWatchhistory.setWhWatchtime(watchTime);
/**累加时间*/
coWatchhistory.setWhTotalTime(coWatchhistory.getWhTotalTime() + whTotalTime);
coWatchhistory.setWhCreateon(new Date());
json = objectMapper.writeValueAsString(coWatchhistory);
redisProxy.set(historyKey,json);
}
}catch (Exception e){
e.printStackTrace();
logger.info("处理数据异常!");
}
}
/**
* 方法封装
* @param partId
* @param memberId
* @param watchTime
* @param watchType
* @param time
* @return
*/
private CoWatchhistory watchHistory( Integer partId, Integer memberId, Integer watchTime, Integer watchType,
long time,Integer classId,Integer whClassType, Integer whTotalTime, String whSource){
CoWatchhistory watchhistory = new CoWatchhistory();
watchhistory.setWhClassid(classId);
watchhistory.setWhCreateon(new Date());
watchhistory.setWhPartid(partId);
watchhistory.setWhWatchtime(watchTime);
watchhistory.setWhMemberid(memberId);
watchhistory.setWhType(watchType.byteValue());
watchhistory.setWhTotalTime(whTotalTime);
watchhistory.setWhClassType(whClassType);
watchhistory.setWhSource(whSource);
watchhistory.setTime(time);
return watchhistory;
}
六、实体类
想了一下 还是把实体加上吧
public class CoWatchhistory {
private Integer whId;
private Integer whPartid;
private Integer whWatchtime;
private Date whCreateon;
private Integer whMemberid;
private Integer whClassid;
/**课程观看进入类型 1 任务进入 2 直接进入**/
private Byte whType=1;
/**子任务Id*/
private Integer whTaskItemId=0;
/**1、课程 2、语音直播 3、视频直播 4、文档*/
private Integer whClassType;
/**观看时长*/
private Integer whTotalTime;
/**接口来源 Android iOS */
private String whSource;
/**记录视频统计开始时间*/
private long time;
}
总结
虽然用redis糊弄过去了,但有些地方还需要完善。