Spring mvc的源码分析4
Controller
使用继承Controller接口实现方式,已经不推荐使用了,解耦!
Controller接口
package org.springframework.web.servlet.mvc;
public interface Controller {
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

WebContentGenerator的作用:
用于提供如浏览器缓存控制、是否必须有session开启、支持的请求方法类型(GET、POST等)等,该类主要有如下属性:
Set<String> supportedMethods:设置支持的请求方法类型,默认支持“GET”、“POST”、“HEAD”,如果我们想支持“PUT”,则可以加入该集合“PUT”。
boolean requireSession = false:是否当前请求必须有session,如果此属性为true,但当前请求没有打开session将抛出HttpSessionRequiredException异常;
boolean useExpiresHeader = true:是否使用HTTP1.0协议过期响应头:如果true则会在响应头添加:“Expires:”;需要配合cacheSeconds使用;
boolean useCacheControlHeader = true:是否使用HTTP1.1协议的缓存控制响应头,如果true则会在响应头添加;需要配合cacheSeconds使用;
boolean useCacheControlNoStore = true:是否使用HTTP 1.1协议的缓存控制响应头,如果true则会在响应头添加;需要配合cacheSeconds使用;
private int cacheSeconds = -1:缓存过期时间,正数表示需要缓存,负数表示不做任何事情(也就是说保留上次的缓存设置),
HTTP1.0缓存控制响应头
Pragma:no-cache:表示防止客户端缓存,需要强制从服务器获取最新的数据;
Expires:HTTP1.0响应头,本地副本缓存过期时间,如果客户端发现缓存文件没有过期则不发送请求,HTTP的日期时间必须是格林威治时间(GMT), 如“Expires:Wed, 14 Mar 2012 09:38:32 GMT”;
HTTP1.1缓存控制响应头
Cache-Control :no-cache 强制客户端每次请求获取服务器的最新版本,不经过本地缓存的副本验证;
Cache-Control :no-store 强制客户端不保存请求的副本,该设置是防止Firefox缓存
Cache-Control:max-age=[秒] 客户端副本缓存的最长时间,类似于HTTP1.0的Expires,只是此处是基于请求的相对时间间隔来计算,而非绝对时间。
还有相关缓存控制机制如Last-Modified(最后修改时间验证,客户端的上一次请求时间 在 服务器的最后修改时间 之后,说明服务器数据没有发生变化 返回304状态码)、ETag(没有变化时不重新下载数据,返回304)
根据代码讲故事
使用继承Controller的方式,写控制器,这种方法一般被注解的方式替代了
public class HelloWorldController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp)
throws Exception {
//1、收集参数
//2、绑定参数到命令对象
//3、调用业务对象
//4、选择下一个页面
ModelAndView mv = new ModelAndView();
//添加模型数据 可以是任意的POJO对象
mv.addObject("message", "Hello World!");
//设置逻辑视图名,视图解析器会根据该名字解析到具体的视图页面
mv.setViewName("hello");
return mv;
}
}
强制请求方法类型:
<bean name="/helloWithPOST" class="cn.javass.chapter4.web.controller.HelloWorldController">
<property name="supportedMethods" value="POST"></property> //这个参数在WebContentGenerator
</bean>
以上配置表示只支持POST请求,如果是GET请求客户端将收到“HTTP Status 405 - Request method 'GET' not supported”。
比如注册/登录可能只允许POST请求。
当前请求的session前置条件检查,如果当前请求无session将抛出HttpSessionRequiredException异常:
<property name="requireSession" value="true"/> //这个参数在WebContentGenerator
客户端端缓存控制:
1、缓存5秒,cacheSeconds=5
<property name="cacheSeconds" value="5"/>
下面提到一些关于缓存控制的一些特殊情况:
1、对于一般的页面跳转(如超链接点击跳转、通过js调用window.open打开新页面都是会使用浏览器缓存的,在未过期情况下会直接使用浏览器缓存的副本,在未过期情况下一次请求也不发送);
2、对于刷新页面(如按F5键刷新),会再次发送一次请求到服务器的;
不缓存,cacheSeconds=0
<property name="cacheSeconds" value="0"/>
Last-Modified缓存机制
(1、在客户端第一次输入url时,服务器端会返回内容和状态码200表示请求成功并返回了内容;同时会添加一个“Last-Modified”的响应头表示此文件在服务器上的最后更新时间,如“Last-Modified:Wed, 14 Mar 2012 10:22:42 GMT”表示最后更新时间为(2012-03-14 10:22);
(2、客户端第二次请求此URL时,客户端会向服务器发送请求头 “If-Modified-Since”,询问服务器该时间之后当前请求内容是否有被修改过,如“If-Modified-Since: Wed, 14 Mar 2012 10:22:42 GMT”,如果服务器端的内容没有变化,则自动返回 HTTP 304状态码
客户端强制缓存过期:
(1、可以按ctrl+F5强制刷新(会添加请求头 HTTP1.0 Pragma:no-cache和 HTTP1.1 Cache-Control:no-cache、If-Modified-Since请求头被删除)表示强制获取服务器内容,不缓存。
(2、在请求的url后边加上时间戳来重新获取内容
Spring也提供了Last-Modified机制的支持,只需要实现LastModified接口
public long getLastModified(HttpServletRequest request) {
if(lastModified == 0L) {
//TODO 此处更新的条件:如果内容有更新,应该重新返回内容最新修改的时间戳
lastModified = System.currentTimeMillis();
}
return lastModified;
}
ETag(实体标记)缓存机制
(1:浏览器第一次请求,服务器在响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式:“ETag:"0f8b0c86fe2c0c7a67791e53d660208e3"”
(2:浏览器第二次请求,客户端的查询更新格式是这样的:“If-None-Match:"0f8b0c86fe2c0c7a67791e53d660208e3"”,如果ETag没改变,表示内容没有发生改变,则返回状态304。

浙公网安备 33010602011771号