zoukankan      html  css  js  c++  java
  • 深入SpringMVC视图解析器

        ViewResolver的主要职责是根据Controller所返回的ModelAndView中的逻辑视图名,为DispatcherServlet返回一个可用的View实例。SpringMVC中用于把View对象呈现给客户端的是View对象本身,而ViewResolver只是把逻辑视图名称解析为对象的View对象。因此,通常在接口层中,只需要返回一个view名称的字符串,ViewResolver就可以自动将字符串名称映射成对应的view进行输出。

        首先,我们先看看ViewResolver的顶层抽象接口:

    1 public interface ViewResolver {
    2 
    3     /**
    4      * Resolve the given view by name.
    5      */
    6     View resolveViewName(String viewName, Locale locale) throws Exception;
    7 
    8 }

    其中,参数viewName表示待解析的视图名称,参数locale表示解析视图的区域,如果要实现国际化,就要注意该参数。

    再看一下这个公共接口有哪些实现:

         (1)AbstractCachingViewResolver是一个抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。可以查看下其源码:

     1 //默认的缓存大小
     2 public static final int DEFAULT_CACHE_LIMIT = 1024;
     3 
     4 //标志实际缓存大小
     5 private volatile int cacheLimit = DEFAULT_CACHE_LIMIT;
     6 
     7 //缓存页面存放的集合,可以不加锁的获取已经缓存的views,主要用于高并发访问。
     8 private final Map<Object, View> viewAccessCache = new ConcurrentHashMap<Object, View>(DEFAULT_CACHE_LIMIT);
     9 
    10 //存放已经创建的views集合,主要用来统计淘汰策略
    11 private final Map<Object, View> viewCreationCache =
    12             new LinkedHashMap<Object, View>(DEFAULT_CACHE_LIMIT, 0.75f, true) {
    13                 @Override
    14                 protected boolean removeEldestEntry(Map.Entry<Object, View> eldest) {
    15                     if (size() > getCacheLimit()) {
    16                         viewAccessCache.remove(eldest.getKey());
    17                         return true;
    18                     }
    19                     else {
    20                         return false;
    21                     }
    22                 }
    23             };
    24 
    25 
    26 //实现接口的方法
    27 @Override
    28     public View resolveViewName(String viewName, Locale locale) throws Exception {
    29              //没有开启缓存,创建views返回
    30         if (!isCache()) {
    31             return createView(viewName, locale);
    32         }
    33         else {//先从viewAccessCache中获取缓存
    34             Object cacheKey = getCacheKey(viewName, locale);
    35             View view = this.viewAccessCache.get(cacheKey);
    36             //viewAccessCache中没有,去viewCreationCache中获取
    37             if (view == null) { //
    38                 synchronized (this.viewCreationCache) {
    39                     view = this.viewCreationCache.get(cacheKey);
    40                     if (view == null) {
    41                         // 首先让子类去创建view
    42                         view = createView(viewName, locale);
    43                         if (view == null && this.cacheUnresolved) {
    44                             view = UNRESOLVED_VIEW;
    45                         }
    46                         //缓存创建的view
    47                         if (view != null) {
    48                             this.viewAccessCache.put(cacheKey, view);
    49                             this.viewCreationCache.put(cacheKey, view);
    50                         
    51                             }
    52                         }
    53                     }
    54                 }
    55             }
    56                         //存在缓存,直接返回
    57             return (view != UNRESOLVED_VIEW ? view : null);
    58         }
    59     }

    至于这里为什么使用viewAccessCache和viewCreationCache两个缓存,viewAccessCache可以在不添加锁的情况下实现高并发获取已经缓存的views,后者存储的views和前者一样,方便用来制定缓存淘汰策略。

        (2)UrlBasedViewResolver是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL。

  • 相关阅读:
    Java后端WebSocket的Tomcat实现
    Swift学习资源
    jwplayer 隐藏属性方法记载
    简单的java socket 示例
    SQL SERVER 2008/2012/2012R2/2014 设置开启远程连接(sa配置)
    JS原型继承和类式继承
    理解js中的原型链,prototype与__proto__的关系
    C# 事件(Event)
    Java 与 JavaScript 对websocket的使用
    C# 版dll 程序集合并工具
  • 原文地址:https://www.cnblogs.com/jy107600/p/10769595.html
Copyright © 2011-2022 走看看