Controller 重要的子类 AbstractController
public abstract class AbstractController extends WebContentGenerator implements Controller
在实现Controller的同时又继承了WebContentGenerator,看一下这个WebContentGenerator类有哪些作用:
WebContentGenerator作为web内容生成器的超类,可以自定义处理器(handler),提供了浏览器缓存控制,是否由session的必须开启
浏览器的请求方式(GET、HEAD、POST等),同时缓存的控制还提供了对HTTP1.0和HTTP1.1的支持。 WebContentGenerator 中的
supportedMethods、requireSession、useExpiresHeader、useCacheControlHeader、useCacheControlNoStore、cacheSeconds、
alwaysMustRevalidate都是可以在xml的bean中进行配置。
源码:
/** HTTP method "GET" */
public static final String METHOD_GET = "GET";
/** HTTP method "HEAD" */
public static final String METHOD_HEAD = "HEAD";
/** HTTP method "POST" */
public static final String METHOD_POST = "POST";
private static final String HEADER_PRAGMA = "Pragma";
private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
/** Set of supported HTTP methods */
private Set<String> supportedMethods;
private boolean requireSession = false;
/** Use HTTP 1.0 expires header? */
private boolean useExpiresHeader = true;
/** Use HTTP 1.1 cache-control header? */
private boolean useCacheControlHeader = true;
/** Use HTTP 1.1 cache-control header value "no-store"? */
private boolean useCacheControlNoStore = true;
private int cacheSeconds = -1;
private boolean alwaysMustRevalidate = false;
后面可配置的属性,分析它们的主要作用:
supportedMethods:设置支持的请求方式,默认是上面的三种,如果是其他的请求方式,可以通过bean注入加入集合。
requireSession :判断浏览器是否必须含有session,如果设置为true必须,浏览器没有session则会报错(HttpSessionRequiredException异常)
useExpiresHeader:是否使用HTTP1.0协议缓存控制响应头, 配合cacheSeconds使用。 为true添加"Expires"响应头,本地副本缓存过期时间
useCacheControlHeader :是否使用HTTP1.1协议缓存控制响应头,配合cacheSeconds使用。
useCacheControlNoStore :是否使用HTTP1.1协议缓存控制响应头,配合cacheSeconds使用。
cacheSeconds :缓存过期时间,正数表示需要缓存,负数表示不做任何事情。
alwaysMustRevalidate :处理器实现LastModified接口,服务器会添加“Last-Modified”响应头,表示服务器最后修改的时间。
AbstractController 继承了 WebContentGenerator 拥有了该类的所有属性,最重要的是实现了Controller,实现了串行化访问方式,并由模板设计模式来设计。通过继承关系可以发现,所有具体Controller类都继承了AbstractController 来完成的,即AbstractController 是Controller里最重要的一个类,它可以控制头部缓存的生成并且决定是否支持了GEP\POST请求方法。
具体代码:
public abstract class AbstractController extends WebContentGenerator implements Controller {
private boolean synchronizeOnSession = false;//该控制器执行时是否同步session,
public final void setSynchronizeOnSession(boolean synchronizeOnSession) {
this.synchronizeOnSession = synchronizeOnSession;
}
public final boolean isSynchronizeOnSession() {
return this.synchronizeOnSession;
}
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 委托给WebContentGenerator 来进行缓存设置
checkAndPrepare(request, response, this instanceof LastModified);
// 判断是否串行化
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
//调用子类 handleRequestInternal()方法返回 ModelAndView
return handleRequestInternal(request, response);
}
}
}
return handleRequestInternal(request, response);
}
protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
AbstractController 总共做了两件时期,一是委托给WebContentGenerator 来进行缓存设置,二是判断是否串行化,提供了handleRequestInternal 抽象方法供子类去实现,所以在具体实现Controller类里面,需要完成
handleRequestInternal()方法,而不再需要实现handleRequest()方法。
具体实现方法:
public static class test2 extends AbstractController{
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
ModelAndView modelAndView = new ModelAndView();
//设置视图名称
modelAndView.setViewName("springmvc2");
return modelAndView;
}
}
在springmvc.xml中配置处理器,同时还可以设置它的属性:
<bean name="/spring2" class="com.core.Test.test2">
<!-- 指定put请求 -->
<property name="supportedMethods" value="PUT"/>
<!-- 制定客户端有session -->
<property name="requireSession" value="true"/>
<!-- 客户端缓存5秒 -->
<property name="cacheSeconds" value="5"/>
</bean>
----------------------------------------------------------------------------------------------------------------------------------------------
题外话:
上面的用法已经过时,现在都使用注解方式和直接扫描处理器包:
<!-- 不再配置Controller的Bean了,直接配置包扫描 -->
<context:component-scan base-package="com.core" />
直接扫描包下的所有Controller,但是要把springmvc.xml放入到web.xml中的DispatherServlet中去,由DispatcherServlet初始化的children webApplicationContext来管理,在DispatcherServlet初始化的context中会扫描当前容器所有的bean实例,根据类级别以及方法级别的映射信息注解组装成对应的HandleMappering信息,但是ContextLoaderListener是不具备这个功能的。
web.xml:
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
-----------------------------------------------------------------------------------------------------------------------------------------------
引用文章: