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;
}
SpringMVC源码阅读(二)的更多相关文章
- SpringMVC源码阅读:过滤器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读系列汇总
1.前言 1.1 导入 SpringMVC是基于Servlet和Spring框架设计的Web框架,做JavaWeb的同学应该都知道 本文基于Spring4.3.7源码分析,(不要被图片欺骗了,手动滑稽 ...
- SpringMVC源码阅读:属性编辑器、数据绑定
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读:拦截器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读:核心分发器DispatcherServlet
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将介绍SpringMVC的核 ...
- SpringMVC源码阅读:定位Controller
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码分析,弄清楚Spr ...
- SpringMVC源码阅读:Controller中参数解析
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读:Json,Xml自动转换
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读:视图解析器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- SpringMVC源码阅读:异常解析器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
随机推荐
- Nginx平台构架 分类: Nginx 2015-07-13 10:55 205人阅读 评论(0) 收藏
深入理解Nginx模块发开与架构解析读书笔记. nginx在启动后,在unix系统中会以daemon的方式(可以手动关闭 nginx.conf daemon off)在后台运行,后台进程包含一个mas ...
- mysql in 的两种使用方法
简述MySQL 的in 的两种使用方法: 他们各自是在 in keyword后跟一张表(记录集).以及在in后面加上字符串集. 先讲后面跟着一张表的. 首先阐述三张表的结构: s(sno,sname. ...
- extern用法总结!
extern 在源文件A里定义的函数,在其他源文件中是看不见的(即不能訪问).为了在源文件B里能调用这个函数,应该在B的头部加上一个外部声明: extern 函数原型: 这样,在源文件B里也能够调 ...
- 第一个Android项目——计算器
第一个Android项目——计算器 效果 开始学Android一两个星期了,学习了一下基本的Activity.简单控件及几个简单布局,打算找个东西来练练手,于是就选择发计算器.关于计算器中用到的四则运 ...
- 【转】iOS应用崩溃日志揭秘
这篇文章还可以在这里找到 英语 If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter ...
- 介绍 JSON
出自官网:http://www.json.org/json-zh.html JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于 ...
- 使用CSS的类名交集复合选择器
首先先看一下基本定义: 复合选择器就是两个或多个基本选择器,通过不同方式连接而成的选择器,主要包括“交集”选择器.“并集”选择器.“后代”选择器. 交集选择器 “交集”复合选择器是由两个选择器直接连接 ...
- codeforces 132C Logo Turtle(dp)
可以用三维dp来保存状态, dp[i][j][k]表示在前i个字符变换了j步之后方向为k(k = 1 or k = 0)的最优解,也就是离原点的最大距离.这里规定0方向为正方向,1位负方向,表示的是当 ...
- 2015前端各大框架比较(angular,vue,react,ant)
前端流行框架大比拼 angular vue react ant-design angularjs angular是个MVVM的框架.针对的是MVVM这整个事.angular的最主要的场景就是单页应用, ...
- 什么是WordPress?
(今天由于好友 肖知虎的 的需求 , 我开始了帮助小虎建站的需求, 就这样开始学习了Wordpress. 这些文章就是为了记录这些我在学习过程当中的心得,和记录下来的文字而已) 什么是WordPre ...