1.首先利用maven压缩js 和css 等资源文件



maven使用fastjson maven jsch_maven使用fastjson



1. <build>
2. <plugin>
3. <groupId>net.alchim31.maven</groupId>
4. <artifactId>yuicompressor-maven-plugin</artifactId>
5. <version>1.4.0</version>
6. <executions>
7. <execution>
8. <!-- 在真正的打包之前,执行一些准备打包压缩操作的操作  -->
9. <phase>prepare-package</phase>
10. <goals>
11. <goal>compress</goal>
12. </goals>
13. </execution>
14. </executions>
15. <configuration>
16. <encoding>UTF-8</encoding>
17. <!-- 忽视 js 错误警告 -->
18. <jswarn>false</jswarn>
19. <nosuffix>true</nosuffix>
20. <linebreakpos>-1</linebreakpos>
21. <!-- 压缩的文件 工程里面所有的 js css 后缀的都会压缩 -->
22. <includes>
23. <include>**/*.js</include>
24. <include>**/*.css</include>
25. </includes>
26. <!-- 不需要压缩的文件 -->
27. <excludes>
28. <exclude>**/style.css</exclude>
29. </excludes>
30. <failOnWarning>false</failOnWarning>
31. </configuration>
32. </plugin>
33. <!-- 当压缩没有填写输出目录 或者 输出目录和压缩目录是同一路径时 一定要配合下面的使用  -->
34. <plugin>
35. <groupId>org.apache.maven.plugins</groupId>
36. <artifactId>maven-war-plugin</artifactId>
37. <configuration>
38.                         <!--   
39.                             如果不增加此配置   src/main/webapp 下面的内容 会重新复制到target输出目录 覆盖掉编译后的内容  
40.                             这样编译的还是未压缩过的内容,增加上此过滤  打war包就不会内容覆盖  
41. >
42. <warSourceExcludes>**/*.js,**/*.css</warSourceExcludes>
43. </configuration>
44. </plugin>
45. </plugins>
46. </build>



 2.通过SpringMvc扩展通过一个请求获取多个JS文件的功能

    2.1 spring MVC 配置



maven使用fastjson maven jsch_maven使用fastjson



    1. <bean id="simpleUrlHandlerMapping"
    2. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    3. <property name="urlMap">
    4. <map>
    5. <!-- 静态资源处理器 -->
    6. <entry key="/r/**/**">
    7. <!-- 自己扩展的SpingMVC ResourceHttpRequestHandler 类,增加了类是与淘宝CDN通过逗号(,)隔开      
    8. 访问多个js的效果 此功能不能压缩JS 如果想实现压缩功能可通过maven 或者 ant 在编译的时候进行压缩 -->
    9. <bean class="com.yoro.core.springmvc.ResourceHttpRequestHandler">
    10. <property name="locations">
    11. <list>
    12. <!-- 只有相同目录的JS文件才能实现淘宝CDN通过逗号(,)隔开 访问多个js的效果 如 /r/ 目录下的js|css 文件      
    13. 就能实现 /r/js/ 目录下的js文件也可以有同样的效果 但 /a/css 下面的文件 和 /r/css 就不能实现 有点小遗憾,因为时间关系待以后升级 -->
    14. <value>/r/</value>
    15. </list>
    16. </property>
    17. <!-- 启用静态资源浏览器缓存一个月 -->
    18. <!-- 通过浏览器进行的缓存 根据可浏览器实现方式不同有所差异 按刷新按扭缓存不会起 当是页面跳转或者地址栏输入则缓存会起作用 -->
    19. <!-- 更 过浏览器缓存的资料和特效 可 搜索 cachecontrol 设置   cacheSeconds 缓存时间单位是秒  2592000 表示缓存 30天 因为我自己每次新版本发布都会都js css 文件增加版本号 所以缓存时间我设置的比较长 -->
    20. <property name="cacheSeconds" value="2592000"></property>
    21. <property name="useExpiresHeader" value="true"></property>
    22. <property name="useCacheControlNoStore" value="true"></property>
    23. </bean>
    24. </entry>
    25. <entry key="/thirdparty/**/**">
    26. <bean class="com.yoro.core.springmvc.ResourceHttpRequestHandler">
    27. <property name="locations">
    28. <list>
    29. <value>/thirdparty/</value>
    30. </list>
    31. </property>
    32. <!-- 启用静态资源浏览器缓存一个月 -->
    33. <property name="cacheSeconds" value="2592000"></property>
    34. <property name="useExpiresHeader" value="true"></property>
    35. <property name="useCacheControlNoStore" value="true"></property>
    36. </bean>
    37. </entry>
    38. </map>
    39. </property>
    40. <property name="order" value="1"></property>
    41. </bean>



     2.2 ResourceHttpRequestHandler  扩展类代码

     



    maven使用fastjson maven jsch_maven使用fastjson



      1. package
      2.     
      3. import
      4. import
      5. import
      6. import
      7. import
      8. import
      9.     
      10. import
      11. import
      12. import
      13. import
      14. import
      15.     
      16. import
      17. import
      18. import
      19. import
      20. import
      21. import
      22. import
      23. import
      24. import
      25. import
      26. import
      27. import
      28. import
      29. import
      30. import
      31.     
      32. public class
      33. extends WebContentGenerator implements
      34.     
      35.          
      36. private static final boolean
      37. "javax.activation.FileTypeMap", ResourceHttpRequestHandler.class.getClassLoader());     
      38.     
      39. private final static Log logger = LogFactory.getLog(ResourceHttpRequestHandler.class);     
      40.     
      41.     
      42. private
      43.     
      44.     
      45. public
      46. super(METHOD_GET, METHOD_HEAD);     
      47.     }     
      48.     
      49. /**  
      50.      * Set a {@code List} of {@code Resource} paths to use as sources  
      51.      * for serving static resources.  
      52.      */
      53. public void
      54. "Locations list must not be empty");     
      55. this.locations = locations;     
      56.     }     
      57.     
      58. @Override
      59. public void afterPropertiesSet() throws
      60. if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {     
      61. "Locations list is empty. No resources will be served");     
      62.         }     
      63.     }     
      64.     
      65. @Override
      66. public void
      67. throws
      68.     
      69. true);     
      70.     
      71. // check whether a matching resource exists   
      72.         List<Resource> resources = getResources(request);     
      73. if (resources == null
      74. "No matching resource found - returning 404");     
      75.             response.sendError(HttpServletResponse.SC_NOT_FOUND);     
      76. return;     
      77.         }     
      78.     
      79. // check the resource's media type   
      80.         MediaType mediaType = getMediaType((String)request     
      81.                 .getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));     
      82. if (mediaType != null) {     
      83. if
      84. "Determined media type '" + mediaType + "' for "
      85. 0));     
      86.             }     
      87. else
      88. if
      89. "No media type found for " + resources.get(0)     
      90. " - not sending a content-type header");     
      91.             }     
      92.         }     
      93.     
      94. for
      95. // header phase   
      96. if (!new
      97.                     .checkNotModified(resource.lastModified())) {     
      98. "Resource not modified - returning 304");     
      99. break;     
      100.             }     
      101. return;     
      102.         }     
      103.     
      104.         setHeaders(response, resources, mediaType);     
      105.     
      106. // content phase   
      107. if
      108. "HEAD request - skipping content");     
      109. return;     
      110.         }     
      111.         writeContent(response, resources);     
      112.     }     
      113.          
      114. protected
      115. null;     
      116.         String mimeType = getServletContext().getMimeType(filename);     
      117. if
      118.             mediaType = MediaType.parseMediaType(mimeType);     
      119.         }     
      120. if (jafPresent && (mediaType == null
      121.             MediaType jafMediaType = ActivationMediaTypeFactory.getMediaType(filename);     
      122. if (jafMediaType != null
      123.                 mediaType = jafMediaType;     
      124.             }     
      125.         }     
      126. return
      127.     }     
      128.     
      129. protected void
      130. throws
      131. long length = 0;     
      132. //Calculation of multiple file length   
      133.         Iterator<Resource> iter = resources.iterator();     
      134. while
      135.             length += iter.next().contentLength();     
      136.         }     
      137. if
      138. throw new
      139. "Resource content too long (beyond Integer.MAX_VALUE)");     
      140.         }     
      141. int) length);     
      142. if (mediaType != null) {     
      143.             response.setContentType(mediaType.toString());     
      144.         }     
      145.     }     
      146.     
      147. protected void
      148. throws
      149.         OutputStream out = response.getOutputStream();     
      150. null;     
      151. try
      152. for
      153. try
      154.                     in = resource.getInputStream();     
      155.                     StreamUtils.copy(in, out);     
      156. finally
      157. try
      158.                         in.close();     
      159. catch
      160.                     }     
      161.                 }     
      162.             }     
      163. finally
      164. try
      165.                 out.close();     
      166. catch
      167.             }     
      168.         }     
      169.     }     
      170.     
      171. protected
      172.         String path = (String) request     
      173.                 .getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);     
      174. if (path == null) {     
      175. throw new IllegalStateException("Required request attribute '"
      176.                     + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE     
      177. "' is not set");     
      178.         }     
      179.     
      180. if
      181. if
      182. "Ignoring invalid resource path [" + path + "]");     
      183.             }     
      184. return null;     
      185.         }     
      186.     
      187. for (Resource location : this.locations) {     
      188. try
      189. if
      190. "Trying relative path ["
      191. "] against base location: "
      192.                 }     
      193. new
      194. ",");     
      195. for
      196.                     Resource resource = location.createRelative(url);     
      197. if
      198.                         rs.add(resource);     
      199.                     }     
      200.                 }     
      201. return
      202. catch
      203.                 logger.debug(     
      204. "Failed to create relative resource - trying next resource location",     
      205.                         ex);     
      206.             }     
      207.         }     
      208. return null;     
      209.     }     
      210.          
      211. /**  
      212.      * Validates the given path: returns {@code true} if the given path is not a valid resource path.  
      213.      * <p>The default implementation rejects paths containing "WEB-INF" or "META-INF" as well as paths  
      214.      * with relative paths ("../") that result in access of a parent directory.  
      215.      * @param path the path to validate  
      216.      * @return {@code true} if the path has been recognized as invalid, {@code false} otherwise  
      217.      */
      218. protected boolean
      219. return (path.contains("WEB-INF") || path.contains("META-INF") || StringUtils.cleanPath(path).startsWith(".."));     
      220.     }     
      221.     
      222. /**  
      223.      * Inner class to avoid hard-coded JAF dependency.  
      224.      */
      225. private static class
      226.     
      227. private static final
      228.     
      229. static
      230.             fileTypeMap = loadFileTypeMapFromContextSupportModule();     
      231.         }     
      232.     
      233. private static
      234. // see if we can find the extended mime.types from the context-support module   
      235. new ClassPathResource("org/springframework/mail/javamail/mime.types");     
      236. if
      237. null;     
      238. try
      239.                     inputStream = mappingLocation.getInputStream();     
      240. return new
      241.                 }     
      242. catch
      243. // ignore   
      244.                 }     
      245. finally
      246. if (inputStream != null) {     
      247. try
      248.                             inputStream.close();     
      249.                         }     
      250. catch
      251. // ignore   
      252.                         }     
      253.                     }     
      254.                 }     
      255.             }     
      256. return
      257.         }     
      258.     
      259. public static
      260.             String mediaType = fileTypeMap.getContentType(filename);     
      261. return (StringUtils.hasText(mediaType) ? MediaType.parseMediaType(mediaType) : null);     
      262.         }     
      263.     }     
      264. }


       2.3 资源文件目录结构

      maven使用fastjson maven jsch_spring_04


       2.4  浏览器缓存效果

       

      maven使用fastjson maven jsch_css_05


       2.5

       5.实现淘宝CDN JS 请求例子

      JS例子:http://127.0.0.1/r/js/alert.js,/js/application.js,/js/bootstrap.js

      CSS例子:http://127.0.1.1/r/css/activity_style.css,/css/bootstrap_responsive.css

      通过逗号(,)分割他们现在就实现了通过一个请求加载多个资源文件的效果了