SpringMVC源码(四)Controller控制器2-AbstractController

Controller 重要的子类 AbstractControlle

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>
-----------------------------------------------------------------------------------------------------------------------------------------------




引用文章:

http://www.bubuko.com/infodetail-1176622.html

http://jinnianshilongnian.iteye.com/blog/1608234

猜你喜欢

转载自blog.csdn.net/superpojo/article/details/72903083