最近做项目的时候,碰到这样的需求,由于一些页面的ajax请求数据太多,而且sql效率很低,导致压力测试时一个页面打开需要一分多钟,所以就想到如下几种解决方案:
1.将请求的数据,通过IO写入硬盘缓存文件,当发现有对应文件时,便从该文件读取存储的请求数据;
2.写一个工具类,在工具类定义一个map类型的成员变量,将请求数据存储到该map中;
3.修改数据库服务器的配置(当然这不是本文要讨论的内容)
既然有了方案,就开始实现,页面中有很多这样的action:
@Action("test")
public void test(){
writeJson(testService.getTestData());
}
基本都是通过service中的方法返回list(map(String,Object)) 类型的数据,然后通过writeJson返回json到前台
方案一:
//请求缓存数据方法
public void requestData(String requestName){
try {
//创建File对象,参数为String类型,表示目录名
File myFilePath = new File("D:\\cache");
//先创建父路径再创建文件
File myFile = new File("D:\\cache\\"+requestName+".json");
//如果父路径存在
if(myFilePath.exists()){
//如果文件存在
if(myFile.exists()){
//文件最后修改时间
Date date = new Date(myFile.lastModified());
//当前日期
Date today = new Date();
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
String lastModifiedDateStr = sdf.format(date);
String todayStr = sdf.format(today);
//如果最后修改时间小于当前日期
if(lastModifiedDateStr.compareTo(todayStr)<0){
//将当前文件删除
myFile.delete();
//创建新的缓存文件
createFile(myFile,requestName);
//如果最后修改时间大于或等于当前日期,则从该文件读取缓存内容
}else{
// 读取文件内容 (输入流)
StringBuffer sb=new StringBuffer();
String tempstr=null;
FileInputStream fis=new FileInputStream(myFile);
BufferedReader br=new BufferedReader(new InputStreamReader(fis));
while((tempstr=br.readLine())!=null){
sb.append(tempstr);
}
Gson gson = new Gson();
//使用gson获取文件中存储的List<Map<String, Object>>结构的数据
List<Map<String, Object>> list = gson.fromJson(sb.toString(), new TypeToken<List<Map<String, Object>>>(){}.getType());
writeJson(list);
br.close();
fis.close();
}
}else{
//创建新的缓存文件
createFile(myFile,requestName);
}
}else{
//创建目录
myFilePath.mkdir();
//创建新的缓存文件
createFile(myFile,requestName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//创建文件方法
public void createFile(File file,String requestName){
try{
file.createNewFile();
//下面把数据写入创建的文件,首先新建文件名为参数创建FileWriter对象
FileWriter resultFile = new FileWriter(file);
//把该对象包装进PrinterWriter对象
PrintWriter myNewFile = new PrintWriter(resultFile);
//使用反射获取service中对应的方法
Method method = mHService.getClass().getDeclaredMethod(requestName, new Class[]{});
//动态执行该service的方法
Object result = method.invoke(this.mHService);
//将数据写到前台
writeJson(result);
//再通过PrinterWriter对象的println()方法把字符串数据写入新建文件
myNewFile.println(JsonUtils.toJson(result));
myNewFile.close();
resultFile.close();
}catch(Exception e){
e.printStackTrace();
}
}
方案一有很不好的地方,会产生缓存文件,读写受到硬盘读写速度限制等
方案二:
//首先在类中定义map成员存储缓存数据
public static Map<String,Object> cacheData = new HashMap<>();
//通过service和对应方法名来获取缓存数据
public static Object getCacheData(String methodName,Object service,Object... params){
try{
Method method = service.getClass().getDeclaredMethod(methodName);
String key = method.getName();
Object[] objs = null;
//获取可变长参数
if(params.length > 0){
objs = new Object[params.length];
int i = 0;
for(Object p : params){
objs[i++] = p;
key += "_" + JsonUtils.toJson(p);
}
}
//如果缓存中有该请求的缓存数据
if(cacheData.containsKey(key)){
System.out.println("read cache!");
//获取对应缓存数据
return cacheData.get(key);
}else{
Object result = null;
try{
//有参数
if(objs != null){
//动态执行该方法,请求数据
result = method.invoke(service,objs);
}else{
//动态执行该方法,请求数据
result = method.invoke(service);
}
System.out.println("read db!");
//将请求的数据存入静态成员,变成缓存
cacheData.put(key, result);
}catch(Exception e){
e.printStackTrace();
}
return result;
}
}catch(Exception e){
return null;
}
}
如有不妥和错误之处请各位评论指出。