php lastmodifieddate,Last-Modified的缓存机制在spring 注解方式中的应用

使用LastModified的一种方法

第一种方法是网上比较常见的,一般搜到的也是这种写法。但是说实在的,感觉不太能用得着。

首先,如果想要使用LastModified,controller类就要先实现LastModified接口,并且重写getLastModified()方法。那么我们用最基础的写controller的方法:继承AbstractController类或者实现Controller接口。所以感觉略微的不现实。当然下面有改良版。先看一下Controller类:

public class TestController implements Controller,LastModified{

private long lastModified = System.currentTimeMillis();

@Override

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

throws Exception {

System.out.println("start:"+lastModified);

return new ModelAndView("returnView");

}

@Override

public long getLastModified(HttpServletRequest request) {

if (lastModified == 0L) {

System.out.println("此时应为0 : "+lastModified);

System.out.println("感觉没有意义");

lastModified = System.currentTimeMillis();

}

System.out.println("lastModified: "+lastModified);

return lastModified;

}

}

这种比较基础的写法需要在dispatcher.xml中配置bean的,配置代码为:

而发出请求以及返回的视图,简单写了两个jsp:

$Title$

返回的视图:

Title

return

源码与API分析

这里,可能大家看得一头雾水:貌似在controller里面也没有干什么,这里我们看一下Spring MVC的文档,博主简单翻译了:

DispatcherServlet 也允许处理器返回一个Servlet API规范中定义的last-modification-date。决定这个属性的方式很直接:DispatcherServlet 会先找到对应的controller处理映射,然后检测它是否实现了LastModified 接口。若是,则调用接口的long getLastModified(request) 方法,并将该返回值返回给客户端。

还是略微的迷,但是可以了解到是在dispatcher找到映射之后再处理的,那么我们可以看一下dispatcher的源码,然后找到了这一段代码:

boolean isGet = "GET".equals(method);

if (isGet || "HEAD".equals(method)) {

long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

return;

}

}

可以看到这里突出了一个比较奇特的属性:如果想要实现这样的缓存机制,method就必须设置为get或者head。这里也专门比较了一下。当然,核心就在于这里:dispatcher如果发现是满足条件的话,是会调用getLastModified方法的,而很明显,这里我们的controller实现LastModified接口的话是会重写getLastModified方法的。而这个方法返回了一个时间戳。而接下来发现我们调用了ServletWebRequest对象的checkNotModified()方法。

这里瞎分析一下:我们重写了方法以后,主要就是返回历史保留的时间戳,而在dispatcher中,当然已经得到了这次的请求头,所以就有了当前的时间戳。然后在dispatcher中进行对比。

而我们看一下Spring MVC API中checkNotModified()方法的表述,这里还是博主的简单翻译:

根据上次修改的时间戳,检查是否已修改请求资源

所以我们的猜测并没有错,具体的时间戳对比封装进了checkNotModified()方法,而根据返回的boolean类型,可以知道请求是否发生了改变。

这样以来:上面的代码基本就了解应该怎么使用了:

public class TestController implements Controller,LastModified{

private long lastModified = System.currentTimeMillis();

@Override

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

throws Exception {

// 正常操作,具体返回不返回view不用我们管,dispatcher可能根本不执行这些代码,如果不要返回视图的话

return new ModelAndView("returnView");

}

@Override

public long getLastModified(HttpServletRequest request) {

if (lastModified == 0L) {

// 只用返回历史时间戳即可

return lastModified;

}

}

这样一来,使用还是比较方便的,核心封装进dispatcher,我们只用实现接口并返回数据就行了。

LastModified缓存的第二种用法

上面的写法毕竟还是比较老的,现在大家都用注解了,@Controller或者@RestController注解controller类,而@RequestMapping注解具体的请求。而这样的话,仿佛不好使用这个方法了。

其实这里我是有点疑惑的:源码上看,dispatcher在找到具体请求以后,就调用checkNotModified进行对比,如果发现时间戳一致,直接return,从而中断当前请求。理论上,仍然是controller类实现接口,重写方法就行了,其他没有任何变化。而实际上这样的想法是错误的。仿佛dispatcher每次匹配都认为是不同的请求。

博主找到的也都是上面的用法,但是看API的时候,checkNotModified()方法给出了一个demo,博主想:可不可以将dispatcher对这一段的处理自己写了。所以就有了这样的代码:

@Controller

public class TestController implements LastModified{

private long lastModified = System.currentTimeMillis();

@RequestMapping("/test.action")

public ModelAndView test(WebRequest webRequest,HttpServletRequest request){

System.out.println("start");

if(webRequest.checkNotModified(lastModified)){

System.out.println("check : "+lastModified);

return null;

}

System.out.println("no check : "+lastModified);

return new ModelAndView("returnView");

}

@Override

public long getLastModified(HttpServletRequest httpServletRequest) {

return lastModified;

}

}

仍然是实现了接口,但是在请求里面,额外多了WebRequest,等于说我主动调用checkNotModified()方法进行匹配。可以看到控制台的结果:

start

no check : 1543331931401

start

check : 1543331931401

很明显,我们实现了缓存功能。

另:不实现LastModified,使用WebRequest一样可以实现功能

a7161145ce5b

image.png

————————————————

版权声明:本文为CSDN博主「iwts_poi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/iwts_24/article/details/84575045

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值