Servlet的生态中,提供了一种友好机制用来提高系统的响应速度,当客户端查询的数据在没有变化的情况下直接返回,以减少服务器压力和网络传输的压力。Spring MVC也很好的继承了该机制,下面我们就学习下怎么使用LastModified。
public class MyServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -2471386444207404619L;
private static Long count= -1L;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
System.out.println("req....");
count= System.currentTimeMillis();
resp.getWriter().write("hello" +count);
}
@Override
public long getLastModified(HttpServletRequest req) {
return count;
}
}
Spring-mvc.xml配置如下:
因为handler是Servlet,所以此处使用了BeanNameUrlHandlerMapping和SimpleServletHandlerAdapter。
然后在对该请求的时候,就能在request headers中发现If-Modified-Since头信息,response中发现Last-Modified。
public class InfoController extends AbstractController implements LastModified{
private static Long count= -1L;
public String test() {
return "hello";
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response)
throws Exception {
count= System.currentTimeMillis();
response.getWriter().write("hello" +count);
return null;
}
@Override
public long getLastModified(HttpServletRequest request) {
// TODO Auto-generated method stub
return count;
}
}
因为handler是Controller,所以Adapter使用了SimpleControllerHandlerAdapter。
请求的时候在request headers中发现If-Modified-Since头信息,response中发现Last-Modified。
@RestController
@RequestMapping("/info")
public class JJController
{
private static Long count = 0L;
@GetMapping("/jj")
public String test(WebRequest request) {
if(request.checkNotModified(count)) {
return null;
}
System.out.println("******************************8");
count = System.currentTimeMillis();
return "hello";
}
}
为了找到对应的处理器和正确处理请求,handlerMapping和handlerAdapter的配置如上。
但是并没有实现LastModified接口,原因,请看源码RequestMappingHandlerAdapter(由于3.2版本之后,AnnotationMethodHandlerAdapter已经不被推荐使用,替代为RequestMappingHandlerAdapter)中的描述:
我们再看看 WebRequest中关于checkNotModified方法的说明:
/**
* Check whether the requested resource has been modified given the
* supplied last-modified timestamp (as determined by the application).
* This will also transparently set the "Last-Modified" response header
* and HTTP status when applicable.
*
Typical usage:
*
* public String myHandleMethod(WebRequest webRequest, Model model) {
* long lastModified = // application-specific calculation
* if (request.checkNotModified(lastModified)) {
* // shortcut exit - no further processing necessary
* return null;
* }
* // further request processing, actually building content
* model.addAttribute(...);
* return "myViewName";
* }
* This method works with conditional GET/HEAD requests, but
* also with conditional POST/PUT/DELETE requests.
*
Note: you can use either
* this {@code #checkNotModified(long)} method; or
* {@link #checkNotModified(String)}. If you want enforce both
* a strong entity tag and a Last-Modified value,
* as recommended by the HTTP specification,
* then you should use {@link #checkNotModified(String, long)}.
*
If the "If-Modified-Since" header is set but cannot be parsed
* to a date value, this method will ignore the header and proceed
* with setting the last-modified timestamp on the response.
* @param lastModifiedTimestamp the last-modified timestamp in
* milliseconds that the application determined for the underlying
* resource
* @return whether the request qualifies as not modified,
* allowing to abort request processing and relying on the response
* telling the client that the content has not been modified
*/
boolean checkNotModified(long lastModifiedTimestamp);
大意就是注解方式中,一个controller会有多个方法,我们只能给每个@requestMapping的方法进行一次判断,只要传入WebRequest参数,并调用其checkNotModified(lastModified)方法,为true则return null,表示内容没有被更改过,不需要重新查询。这个方法只能是在Get或者Head请求中适用。其中的例子代码如下:
public String myHandleMethod(WebRequest webRequest, Model model) {
long lastModified = // application-specific calculation
if (request.checkNotModified(lastModified)) {
// shortcut exit - no further processing necessary
return null;
}
// further request processing, actually building content
model.addAttribute(...);
return "myViewName";
}