背景:接到领导反馈有爬虫经常爬取M站的页面,导致后台不断查solr,故要把文章缓存在redis,不再从redis读取,需求不难,就是把几百篇文章缓存在redis,一下子就做完了,
public List<Doc> getPagingList(int page, int pageSize) {
List<Doc> dp =new ArrayList<>();
List<Map<String, String>> docList = (List<Map<String, String>>) JedisUtils.getEList("free_docList");//所有生成的300篇文章缓存
if (docList==null) {
getIdList();//重新生成缓存数据
docList = (List<Map<String, String>>) JedisUtils.getEList("free_docList");
}
for (int i = (page-1)*pageSize; i < pageSize*page; i++) {
Doc doc = new Doc();
doc.setFieldMaps(docList.get(i));
dp.add(doc);
}
return dp;
}
public List<String> getIdList() {
List<String> idsList=JedisUtils.getList("free_id"); //免费公告id
if(idsList==null || idsList.size()<1){ //免费公告为空时,初始化免费公告列表
SearchCondition searchCondition = new SearchCondition();
List<Doc> dp=new ArrayList<Doc>();
if(StringUtil.isEmpty(searchCondition.getSearchType())){
searchCondition.setSearchType("any");
}
if(StringUtil.isEmpty(searchCondition.getDtype())){
searchCondition.setDtype("10");
}
String etime = DateUtil.reduceDate(7, "yyyy-MM-dd", false, null);
String stime = DateUtil.reduceDate(8, "yyyy-MM-dd", false, null);
searchCondition.setEtime(etime);
searchCondition.setStime(stime);
searchCondition.setPageSize(30);
searchCondition.setChannelIds("52");
idsList=new ArrayList<String>();
List<Map<String, String>> docList= new ArrayList<>();
for (int i = 1; i <11; i++) {
searchCondition.setPageIndex(i);
dp = SolrUtils.search(searchCondition);
SearchInfo info = searchInfoList(dp);
JedisUtils.setObject("free_html"+i,info,24*60*60);
for(Doc doc:dp){
idsList.add(doc.getFieldMaps().get("docid"));
docList.add(doc.getFieldMaps());
}
}
JedisUtils.setList("free_id",idsList,24*60*60);
JedisUtils.setEList("free_docList",docList,24*60*60);
}
return idsList;
}
大概思路就是当M站有爬虫爬取数据的时候,调用getPagingList方法, 如果缓存为空, 调用getIdList()重新生成300篇文章的缓存,然后再加载,getIdList()方法里面有部分内容是给pc端用的,这里只需要添加生成的300篇文章的缓存方法即可,经本地测试也没有啥问题,然后就部署服务器,问题来了
doc.setFieldMaps(docList.get(i));是这一行报空指针异常,docList如果有数据肯定是有300条的,有点懵逼了,看意思是缓存里面没有数据,但是我明显做了判断,如果缓存docList 为空,则重新生成缓存再赋值,感觉不太可能,难到是格式转化问题,线上的比较难debug,而本地测试又正常,这就比较尴尬了,有点不知所措,再查看下去,问题出现在这一行, List idsList=JedisUtils.getList(“free_id”); 因为我本地测试是先把缓存清空了,而线上是不可能随便就清缓存,其实就是当程序进来的时候检查docList 为空,然后调用生成缓存的方法,但是线上的free_id缓存不是空的,所以无法生成,就这样陷入了无限循环中,故一直报空指针异常,问题定位到了就很简单了。
if (docList==null) {
JedisUtils.del(“free_id”);
getIdList();//重新生成缓存数据
docList = (List<Map<String, String>>) JedisUtils.getEList(“free_docList”);
}
当docList为空的时候先去删除free_id的缓存,这样就肯定能重新生成新的缓存数据了。