zoukankan      html  css  js  c++  java
  • SpringMVC源码阅读(二)

    今天分析下ViewResolver和View的实现  下面是ModelAndView的实现

    package org.springframework.web.servlet;
    
    import java.util.Map;
    
    import org.springframework.ui.ModelMap;
    import org.springframework.util.CollectionUtils;
    
     
    public class ModelAndView {
    
    	/** View instance or view name String */
    	private Object view;
    
    	/** Model Map */
    	private ModelMap model;
    
    	/** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
    	private boolean cleared = false;
    
    
    	/**
    	 * Default constructor for bean-style usage: populating bean
    	 * properties instead of passing in constructor arguments.
    	 * @see #setView(View)
    	 * @see #setViewName(String)
    	 */
    	public ModelAndView() {
    	}
    
    	public ModelAndView(String viewName) {
    		this.view = viewName;
    	}
    
    	public ModelAndView(View view) {
    		this.view = view;
    	}
    
    	public ModelAndView(String viewName, Map<String, ?> model) {
    		this.view = viewName;
    		if (model != null) {
    			getModelMap().addAllAttributes(model);
    		}
    	}
    
    	public ModelAndView(View view, Map<String, ?> model) {
    		this.view = view;
    		if (model != null) {
    			getModelMap().addAllAttributes(model);
    		}
    	}
    
    	public ModelAndView(String viewName, String modelName, Object modelObject) {
    		this.view = viewName;
    		addObject(modelName, modelObject);
    	}
    
    	public ModelAndView(View view, String modelName, Object modelObject) {
    		this.view = view;
    		addObject(modelName, modelObject);
    	}
    
    	public void setViewName(String viewName) {
    		this.view = viewName;
    	}
    
    	/**
    	 * Return the view name to be resolved by the DispatcherServlet
    	 * via a ViewResolver, or <code>null</code> if we are using a View object.
    	 */
    	public String getViewName() {
    		return (this.view instanceof String ? (String) this.view : null);
    	}
    
    	/**
    	 * Set a View object for this ModelAndView. Will override any
    	 * pre-existing view name or View.
    	 */
    	public void setView(View view) {
    		this.view = view;
    	}
    
    	/**
    	 * Return the View object, or <code>null</code> if we are using a view name
    	 * to be resolved by the DispatcherServlet via a ViewResolver.
    	 */
    	public View getView() {
    		return (this.view instanceof View ? (View) this.view : null);
    	}
    
    	/**
    	 * Indicate whether or not this <code>ModelAndView</code> has a view, either
    	 * as a view name or as a direct {@link View} instance.
    	 */
    	public boolean hasView() {
    		return (this.view != null);
    	}
    
    	/**
    	 * Return whether we use a view reference, i.e. <code>true</code>
    	 * if the view has been specified via a name to be resolved by the
    	 * DispatcherServlet via a ViewResolver.
    	 */
    	public boolean isReference() {
    		return (this.view instanceof String);
    	}
    
    	protected Map<String, Object> getModelInternal() {
    		return this.model;
    	}
    
    	public ModelMap getModelMap() {
    		if (this.model == null) {
    			this.model = new ModelMap();
    		}
    		return this.model;
    	}
    
    	public Map<String, Object> getModel() {
    		return getModelMap();
    	}
    
    	public ModelAndView addObject(String attributeName, Object attributeValue) {
    		getModelMap().addAttribute(attributeName, attributeValue);
    		return this;
    	}
    
    	public ModelAndView addObject(Object attributeValue) {
    		getModelMap().addAttribute(attributeValue);
    		return this;
    	}
    
    	public ModelAndView addAllObjects(Map<String, ?> modelMap) {
    		getModelMap().addAllAttributes(modelMap);
    		return this;
    	}
    
    	public void clear() {
    		this.view = null;
    		this.model = null;
    		this.cleared = true;
    	}
    
    	public boolean isEmpty() {
    		return (this.view == null && CollectionUtils.isEmpty(this.model));
    	}
    
    	public boolean wasCleared() {
    		return (this.cleared && isEmpty());
    	}
    
    	@Override
    	public String toString() {
    		StringBuilder sb = new StringBuilder("ModelAndView: ");
    		if (isReference()) {
    			sb.append("reference to view with name '").append(this.view).append("'");
    		}
    		else {
    			sb.append("materialized View is [").append(this.view).append(']');
    		}
    		sb.append("; model is ").append(this.model);
    		return sb.toString();
    	}
    
    }
    

    与逻辑视图紧紧相连的View

    package org.springframework.web.servlet;
    
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    public interface View {
    
    	 
    	String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
    
    
    	 
    	String getContentType();
    
    	 
    	void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
    
    }
    

    ViewResolver的一个实现类

    package org.springframework.web.servlet.view;
    
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Map;
    import java.util.Properties;
    
    import org.springframework.beans.BeanUtils;
    import org.springframework.core.Ordered;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.PatternMatchUtils;
    import org.springframework.web.servlet.View;
    
    
    public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
    
    	 
    	public static final String REDIRECT_URL_PREFIX = "redirect:";
     
    	public static final String FORWARD_URL_PREFIX = "forward:";
    
    
    	private Class viewClass;
    
    	private String prefix = "";
    
    	private String suffix = "";
    
    	private String[] viewNames = null;
    
    	private String contentType;
    
    	private boolean redirectContextRelative = true;
    
    	private boolean redirectHttp10Compatible = true;
    
    	private String requestContextAttribute;
    
    	private int order = Integer.MAX_VALUE;
    
    	 
    	private final Map<String, Object> staticAttributes = new HashMap<String, Object>();
    
    
    	 
    	public void setViewClass(Class viewClass) {
    		if (viewClass == null || !requiredViewClass().isAssignableFrom(viewClass)) {
    			throw new IllegalArgumentException(
    					"Given view class [" + (viewClass != null ? viewClass.getName() : null) +
    					"] is not of type [" + requiredViewClass().getName() + "]");
    		}
    		this.viewClass = viewClass;
    	}
    
    	 
    	protected Class getViewClass() {
    		return this.viewClass;
    	}
    
    	 
    	protected Class requiredViewClass() {
    		return AbstractUrlBasedView.class;
    	}
    
    	 
    	public void setPrefix(String prefix) {
    		this.prefix = (prefix != null ? prefix : "");
    	}
    
    	 
    	protected String getPrefix() {
    		return this.prefix;
    	}
    
    	 
    	public void setSuffix(String suffix) {
    		this.suffix = (suffix != null ? suffix : "");
    	}
    
    	 
    	protected String getSuffix() {
    		return this.suffix;
    	}
    
    	 
    	public void setContentType(String contentType) {
    		this.contentType = contentType;
    	}
    
    	 
    	protected String getContentType() {
    		return this.contentType;
    	}
    
    	 
    	public void setRedirectContextRelative(boolean redirectContextRelative) {
    		this.redirectContextRelative = redirectContextRelative;
    	}
    
    	 
    	protected boolean isRedirectContextRelative() {
    		return this.redirectContextRelative;
    	}
    
    	 
    	public void setRedirectHttp10Compatible(boolean redirectHttp10Compatible) {
    		this.redirectHttp10Compatible = redirectHttp10Compatible;
    	}
    
    	 
    	protected boolean isRedirectHttp10Compatible() {
    		return this.redirectHttp10Compatible;
    	}
    
    	 
    	public void setRequestContextAttribute(String requestContextAttribute) {
    		this.requestContextAttribute = requestContextAttribute;
    	}
    
    	 
    	protected String getRequestContextAttribute() {
    		return this.requestContextAttribute;
    	}
    
    	 
    	public void setAttributes(Properties props) {
    		CollectionUtils.mergePropertiesIntoMap(props, this.staticAttributes);
    	}
    
    	 
    	public void setAttributesMap(Map<String, ?> attributes) {
    		if (attributes != null) {
    			this.staticAttributes.putAll(attributes);
    		}
    	}
    
    	 
    	public Map<String, Object> getAttributesMap() {
    		return this.staticAttributes;
    	}
    
    	 
    	public void setViewNames(String[] viewNames) {
    		this.viewNames = viewNames;
    	}
    
    	 
    	protected String[] getViewNames() {
    		return this.viewNames;
    	}
     
    	public void setOrder(int order) {
    		this.order = order;
    	}
     
    	public int getOrder() {
    		return this.order;
    	}
    
    	@Override
    	protected void initApplicationContext() {
    		super.initApplicationContext();
    		if (getViewClass() == null) {
    			throw new IllegalArgumentException("Property 'viewClass' is required");
    		}
    	}
    
    
    	 
    	@Override
    	protected Object getCacheKey(String viewName, Locale locale) {
    		return viewName;
    	}
    
    	 
    	@Override
    	protected View createView(String viewName, Locale locale) throws Exception {
    		// If this resolver is not supposed to handle the given view,
    		// return null to pass on to the next resolver in the chain.
    		if (!canHandle(viewName, locale)) {
    			return null;
    		}
    		// Check for special "redirect:" prefix.
    		if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
    			String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
    			return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
    		}
    		// Check for special "forward:" prefix.
    		if (viewName.startsWith(FORWARD_URL_PREFIX)) {
    			String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
    			return new InternalResourceView(forwardUrl);
    		}
    		// Else fall back to superclass implementation: calling loadView.
    		return super.createView(viewName, locale);
    	}
    
    	/**
    	 
    	protected boolean canHandle(String viewName, Locale locale) {
    		String[] viewNames = getViewNames();
    		return (viewNames == null || PatternMatchUtils.simpleMatch(viewNames, viewName));
    	}
    
    	 
    	@Override
    	protected View loadView(String viewName, Locale locale) throws Exception {
    		AbstractUrlBasedView view = buildView(viewName);
    		View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
    		return (view.checkResource(locale) ? result : null);
    	}
    
    	 
    	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    		AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
    		view.setUrl(getPrefix() + viewName + getSuffix());
    		String contentType = getContentType();
    		if (contentType != null) {
    			view.setContentType(contentType);
    		}
    		view.setRequestContextAttribute(getRequestContextAttribute());
    		view.setAttributesMap(getAttributesMap());
    		return view;
    	}
    
    }
    

    JSTLView

    package org.springframework.web.servlet.view;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import org.springframework.context.MessageSource;
    import org.springframework.web.servlet.support.JstlUtils;
    import org.springframework.web.servlet.support.RequestContext;
    
    public class JstlView
      extends InternalResourceView
    {
      private MessageSource messageSource;
      
      public JstlView() {}
      
      public JstlView(String url)
      {
        super(url);
      }
      
      public JstlView(String url, MessageSource messageSource)
      {
        this(url);
        this.messageSource = messageSource;
      }
      
      protected void initServletContext(ServletContext servletContext)
      {
        if (this.messageSource != null) {
          this.messageSource = JstlUtils.getJstlAwareMessageSource(servletContext, this.messageSource);
        }
        super.initServletContext(servletContext);
      }
      
      protected void exposeHelpers(HttpServletRequest request)
        throws Exception
      {
        if (this.messageSource != null) {
          JstlUtils.exposeLocalizationContext(request, this.messageSource);
        }
        else {
          JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
        }
      }
    }
    

      

    package org.springframework.web.servlet.view;
    
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Map;
    
    import org.springframework.web.context.support.WebApplicationObjectSupport;
    import org.springframework.web.servlet.View;
    import org.springframework.web.servlet.ViewResolver;
    
    public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver {
    
    	/** Whether we should cache views, once resolved */
    	private boolean cache = true;
    
    	/** Map from view key to View instance */
    	private final Map<Object, View> viewCache = new HashMap<Object, View>();
    
    
    	/**
    	 * Enable or disable caching.
    	 * <p>Default is "true": caching is enabled.
    	 * Disable this only for debugging and development.
    	 * <p><b>Warning: Disabling caching can severely impact performance.</b>
    	 */
    	public void setCache(boolean cache) {
    		this.cache = cache;
    	}
    
    	/**
    	 * Return if caching is enabled.
    	 */
    	public boolean isCache() {
    		return this.cache;
    	}
    
    
    	public View resolveViewName(String viewName, Locale locale) throws Exception {
    		if (!isCache()) {
    			return createView(viewName, locale);
    		}
    		else {
    			Object cacheKey = getCacheKey(viewName, locale);
    			synchronized (this.viewCache) {
    				View view = this.viewCache.get(cacheKey);
    				if (view == null) {
    					// Ask the subclass to create the View object.
    					view = createView(viewName, locale);
    					this.viewCache.put(cacheKey, view);
    					if (logger.isTraceEnabled()) {
    						logger.trace("Cached view [" + cacheKey + "]");
    					}
    				}
    				return view;
    			}
    		}
    	}
    
    	 
    	protected Object getCacheKey(String viewName, Locale locale) {
    		return viewName + "_" + locale;
    	}
    
    	 
    	public void removeFromCache(String viewName, Locale locale) {
    		if (!this.cache) {
    			logger.warn("View caching is SWITCHED OFF -- removal not necessary");			
    		}
    		else {
    			Object cacheKey = getCacheKey(viewName, locale);
    			Object cachedView;
    			synchronized (this.viewCache) {
    				cachedView = this.viewCache.remove(cacheKey);
    			}
    			if (cachedView == null) {
    				// Some debug output might be useful...
    				if (logger.isDebugEnabled()) {
    					logger.debug("No cached instance for view '" + cacheKey + "' was found");
    				}
    			} 
    			else {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Cache for view " + cacheKey + " has been cleared");
    				}
    			}
    		}
    	}
    
    	/**
    	 * Clear the entire view cache, removing all cached view objects.
    	 * Subsequent resolve calls will lead to recreation of demanded view objects.
    	 */
    	public void clearCache() {
    		logger.debug("Clearing entire view cache");
    		synchronized (this.viewCache) {
    			this.viewCache.clear();
    		}
    	}
    
    
    	 
    	protected View createView(String viewName, Locale locale) throws Exception {
    		return loadView(viewName, locale);
    	}
    
    	protected abstract View loadView(String viewName, Locale locale) throws Exception;
    
    }
    
    package org.springframework.web.servlet;
    
    import java.util.Locale;
    
    public abstract interface ViewResolver
    {
      public abstract View resolveViewName(String paramString, Locale paramLocale)
        throws Exception;
    }
    

      

  • 相关阅读:
    单位根反演学习笔记
    省选模拟测试17
    省选模拟测试16
    省选模拟测试15
    省选模拟测试14
    省选模拟测试13
    P4491 [HAOI2018]染色
    省选模拟测试12
    P4389 付公主的背包
    洛谷P3403
  • 原文地址:https://www.cnblogs.com/wuxinliulei/p/5065345.html
Copyright © 2011-2022 走看看