redis 页面缓存html,使用redis实现页面缓存

本文是<>一书 第二章的读书笔记

我们要缓存的就是形式如下面的url http://test.com/shwoItem?item=itemX

设计方案 第一个域,是zset类型的------key是viewed:userSessionid

存放的是商品id与用户查看此商品时的timestamp

第二个域,是zset类型的------可以是viewed:

member是商品id(全局范围内),score是商品被用户(全局范围内)浏览的次数(是负数)

第三个域,是hash类型的------key是item:itemId

存放的是商品的信息

用户查看了某件商品

public void viewItem(Jedis conn, String token, String user, String item) {

long timestamp = System.currentTimeMillis() / 1000;

if (item != null) {

//用户user在某时浏览了某件商品

conn.zadd("viewed:" + token, timestamp, item);

//只记录用户最近查看的25件商品

conn.zremrangeByRank("viewed:" + token, 0, -26);

//有序set里 score的越小排名越靠前

conn.zincrby("viewed:", -1, item); //-1还是1?

}

}

试着缓存这个页面 首先我们要判断,某个url是否能缓存

/**

* 如果request 不符合规范 就不缓存 返回false

* 如果商品还没有被访问过 自然不能缓存 返回false

* 如果商品被访问过 但是访问的排名在10000之后 也就不缓存了 返回false

* 如果商品被访问过 且访问的排名在10000之内 就说明可以缓存 返回true

*

* @param conn

* @param request

* @return

*/

public boolean canCache(Jedis conn, String request) {

//从类似http://test.com/shwoItem?item=itemX

//这样的字符串中获得paramter 代码就不赘述了

Map params = getParams(request);

if (params == null)

return false;

//获得itemX这个信息

String itemId = extractItemId(params);

//params.containsKey("_") 这个条件只是示例

//用户可以加上自己的判别条件

if (itemId == null || params.containsKey("_")) {

return false;

}

// viewed:这个有序集里存放的是 商品的访问次数

Long rank = conn.zrank("viewed:", itemId);

// 查看这个商品的访问量是否在前10000内

//如果rank==null 说明商品还没有被访问过

return rank != null && rank < 10000;

}

实现缓存request

public String cacheRequest(Jedis conn, String request, Callback callback) {

if (!canCache(conn, request)) {

return callback != null ? callback.call(request) : null;

}

String pageKey = "cache:" + hashRequest(request);

//这个只是示例 真实的情况 应该是复杂的业务逻辑产生最后的反馈页面

String content = conn.get(pageKey);

if (content == null && callback != null) {

content = callback.call(request);

//我们可以认为这个content就是html

//我们将要显示的数据缓存5分钟

conn.setex(pageKey, 300, content);

}

return content;

}传入的callback如下:

Callback callback = new Callback() {

public String call(String request) {

return "content for " + request;

}

};

我们看看测试代码

package redisinaction;

import org.junit.BeforeClass;

import org.junit.Test;

import redis.clients.jedis.Jedis;

import redisinaction.Chapter02.Callback;

/**

* This class is used for ...

* @author dlf([email protected])

* @version 1.0, 2016年10月18日 下午9:34:27

*/

public class Chapter02Test {

static Jedis conn = null;

static Chapter02 ch2=null;

@BeforeClass

public static void initConn(){

System.out.println("test before");

ch2=new Chapter02();

conn = new Jedis("10.150.0.80");

conn.auth("dlf123123");

}

@Test

public void testCacheRequest() {

Callback callback = new Callback() {

public String call(String request) {

return "content for " + request;

}

};

//必须先viewItem 否则不管调用几次cacheRequest 都不能缓存

//为什么? 自己想

ch2.viewItem(conn, "dlf_session_id", "dlf", "itemX");

String url = "http://test.com/?item=itemX";

String result = ch2.cacheRequest(conn, url, callback);

System.out.println( result);

String result3 = ch2.cacheRequest(conn, url, null);

System.out.println(result3);

String result4 = ch2.cacheRequest(conn, url, null);

System.out.println(result4);

}

}

全局范围内被用户查看最多的n件产品(和上一章那个文章排序差不多)

private static final int ARTICLES_PER_PAGE = 25;

public List> getMostPopulate(Jedis conn, int page) {

int start = (page - 1) * ARTICLES_PER_PAGE;

int end = start + ARTICLES_PER_PAGE - 1;

Set ids = conn.zrevrange("viewed:", start, end);

List> items = new ArrayList>();

for (String id : ids){

Map itemData = conn.hgetAll(id);

itemData.put("id", id);

items.add(itemData);

}

return items;

}

在viewItem里,我们已经记录了所有商品的浏览次数(负数)

conn.zincrby("viewed:", -1, item);

那么经过n天后,这个viewed里的数据项就很多了,而且其实也没有必要一直保存着所有商品的浏览次数

所以

public class RescaleViewedThread implements Runnable{

private Jedis conn;

private boolean quit;

public RescaleViewedThread(int limit) {

conn = new Jedis("10.150.0.80");

conn.auth("dlf123123");

}

public void shutDown(){

quit=true;

}

@Override

public void run() {

while (!quit) {

try {

//移除排名20000之后的商品浏览信息

conn.zremrangeByRank("viewed:", 0, -20001);

//将所有商品的浏览数量降低一半

conn.zinterstore("viewed","viewed:0.5");

Thread.sleep(300);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}系统启动后就,一直运行这个线程。

那么怎么做呢?怎么集成到我的项目里呢?我的项目是使用struts2开发的。

哥哥,您不知道有个东西叫拦截器么?interceptor?

看这个:http://www.2cto.com/kf/201506/408009.html

这个是springmvc的?struts怎么用?

笨死!

在struts2的拦截器里获得request和response你不会么?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值