Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug

12,728 views

Published on

SpringOne 2gx 2014の参加報告とSpring 4.1の新機能解説

Published in: Technology
  • Be the first to comment

SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug

  1. 1. SpringOne 2GX 2014 参加報告 & Spring 4.1について JSUG勉強会 #jsug 2014-12-11 Toshiaki Maki (@making)
  2. 2. 自己紹介 • @making • http://blog.ik.am • 公私ともにSpringヘービーユーザー • 日本Javaユーザーグループ幹事
  3. 3. 祝「はじめてのSpring Boot」出版 http://bit.ly/hajiboot
  4. 4. 今日のコンテンツ • SpringOne 2gx 2014の様子 (5分) • Spring 4.1の新機能紹介 (45分)
  5. 5. 今日話さないこと
  6. 6. SpringOne 2gx 2014の様子
  7. 7. SpringOne 2gx 2014 • 2014/09/09~11 • ダラス
  8. 8. SpringOne 2gx 2014 • 5つのトラック約120セッション • Core Spring • Data & Integration •Web & JavaScript • Applied Spring • Big Data • http://www.slideshare.net/SpringCentral/tag/springone2gx2014
  9. 9. Dallas Omni Hotel
  10. 10. Food
  11. 11. Beers
  12. 12. 先週銀座で飲んだ(どうでもいい)
  13. 13. Talk with Pivotal guys
  14. 14. Josh Long (@starbuxman)
  15. 15. 効果 (1/2) http://spring.io/blog/2014/10/08/this-week-in-spring-october-7th-2014
  16. 16. 効果 (2/2) http://spring.io/blog/2014/10/29/this-week-in-spring-october-28-2014 !
  17. 17. 会場めっちゃ寒かった 景品のパーカー をもらうため会 場に散らばった 全てのバッジを 必死で探したw
  18. 18. SpringOne 2gx 2015 • 来年はワシントンで開催予定
  19. 19. Spring 4.1の新機能紹介
  20. 20. 紹介するセッション http://www.slideshare.net/SpringCentral/tag/springone2gx2014
  21. 21. Spring 4.1 • 2014年9月リリース • 現時点で4.1.3.RELEASE • メインストリームは4.2へ移行。 4.1はメンテナンスモードへ Spring Bootは1.2から対応
  22. 22. Spring 4.1の主な新機能・改善 Web機能の改善 JMS機能の改善 Cache機能の改善 WebSocketメッセージング(STOMP)の改善 Test機能の改善 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/new-in-4.1.html
  23. 23. Spring 4.1の主な新機能・改善 Web機能の改善 JMS機能の改善 Cache機能の改善 WebSocketメッセージング(STOMP)の改善 Test機能の改善 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/new-in-4.1.html
  24. 24. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  25. 25. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  26. 26. 静的リソースサポートの改善 Spring MVC 4.1 の目玉機能
  27. 27. 説明に時間がかかる ので最後にまわす
  28. 28. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  29. 29. Controller引数のOptionalサポート @RequestMapping(value = “/foo”) String foo(@RequestParam(required=false) String bar) { if (bar != null) { /* … */} } @RequestMapping(value = “/foo”) String foo(@RequestParam Optional<String> bar) { bar.map(value -> {/* … */}); } Before After
  30. 30. WebじゃないけどOptinal対応 Before @Autowired(required=false) FooService fooService; After @Autowired Optional<FooService> fooService;
  31. 31. Jacksonの@JsonViewサポート interface PublicView {}; class User { @PublicView private String username; private String password; // … } @RestController class UserController { @RequestMapping("/user") @JsonView(PublicView.class) User getUser() { return new User("demo", "password"); } }
  32. 32. Jacksonの@JsonViewサポート interface PublicView {}; class User { @PublicView private String username; private String password; // … } @RestController class UserController { @RequestMapping("/user") @JsonView(PublicView.class) User getUser() { {"username":"demo"} return new User("demo", "password"); } }
  33. 33. JSONPサポート @ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { super("callback"); } }
  34. 34. JSONPサポート @RestController class UserController { @RequestMapping("/user") User getUser() { return new User("demo", "password"); } } GET /user?callback=foo foo({"username":"demo", "password":"password"})
  35. 35. ResponseBodyAdvice • @ResponseBody/ResponseEntityメ ソッドへのコールバック • 2つの実装が組み込まれている • JsonViewResponseBodyAdvice • AbstractJsonpResponseBodyAdvice
  36. 36. 新しいHttpMessageConverter追加 GsonHttpMessageConverter 軽量なJSONライブラリGSONを使用してHTTP経由で JSONをやりとり(通常はJacksonを使用する) ProtobufHttpMessageConverter HTTP経由でGoogleのシリアライゼーションフォーマッ トProtocol Bufferをやりとり MappingJackson2XmlHttpMessageConverter Jackson XMLを使用してHTTP経由でXMLをやりとり(通 常はJAXBを使用する)
  37. 37. 使い方 従来のXMLの場合 <mvc:annotation-driven> <mvc:message-converters> <bean class=“….GsonHttpMessageConverter” /> </mvc:message-converters> </mvc:annotation-driven> Spring Bootの場合 @Configuration class AppConfig { @Bean HttpMessageConverter gsonHttpMessageConverter() { return new GsonHttpMessageConverter(); } }
  38. 38. ResponseEntityビルダーサポート Before public ResponseEntity<String> handle() { String body = "Hi!"; HttpHeaders headers = new HttpHeaders(); headers.setLocation(location); return new ResponseEntity(body, headers, HttpStatus.CREATED); } After public ResponseEntity<String> handle() { URI location = …; return ResponseEntity.created(location).body("Hi!"); }
  39. 39. RequestEntityビルダーサポート Before HttpHeaders headers = new HttpHeaders(); headers.setAccept(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity("Hi!", headers); restTemplate.exchange(uri, HttpMethod.POST, entity, String.class); After restTemplate.exchange(RequestEntity.post(uri) .accept(MediaType.APPLICATION_JSON) .body(Hi!), String.class);
  40. 40. EL関数 s:mvcUrl 追加 @Controller @RequestMapping("/hotels/{hotel}") public class BookingController { @RequestMapping("/bookings/{booking}") String getBooking(@PathVariable Long booking) {/*…*/} } Before <a href="${pageContext.request.contextPath}/hotels/ 21/42" /> After <a href="${s:mvcUrl('BC#getBooking').arg(0, 42).buildAndExpand(21)}" />
  41. 41. URI逆引き static import MvcUriComponentsBuilder.*; UriComponents uriComponents = fromMethodCall( on(BookingController.class).getBooking(21) ).buildAndExpand(42); URI uri = uriComponents.encode().toUri(); OR UriComponents uriComponents = fromMappingName("BC#getBooking") .arg(0, 21) .buildAndExpand(42); URI uri = uriComponents.encode().toUri();
  42. 42. Cacheの改善JMSの改善 @JmsListenerサポート spring-messagingサポート JCache(JSR-107) サポート
  43. 43. Cacheの改善JMSの改善 @JmsListenerサポート spring-messagingサポート JCache(JSR-107) サポート
  44. 44. @JmsListener Before (Spring 2~) @Component public class OrderMsgHandler { public void handleMsg(Order order) { /**/ } } <jms:listener-container …> <jms:listener destination="order" ref="orderMsgHandler" method="handleMsg" /> </jms:listener-container>
  45. 45. @JmsListener After (Spring 4.1~) @Component public class OrderMsgHandler { @JmsListener(destination = "order") public void handleMsg(Order order) { /**/ } } <jms:annotation-driven /> <jms:listener-container … />
  46. 46. JavaConfigの場合 @Configuration @EnableJms public class AppConfig { @Bean JmsListenerContainerFactory jmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setDestinationResolver(destinationResolver()); factory.setConcurrency("3-10"); return factory; } // … }
  47. 47. JavaConfigの場合 @Configuration @EnableJms public class AppConfig { @Bean JmsListenerContainerFactory jmsListenerContainerFactory() { Spring Bootなら設定不要 DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setDestinationResolver(destinationResolver()); factory.setConcurrency("3-10"); return factory; } // … }
  48. 48. 柔軟なメソッドシグニチャ対応 @JmsListener(destination = "order") public void handleMsg(Order order) {} ! @JmsListener(destination = “order") public void handleMsg(Session session, TextMessage message) {} ! @JmsListener(destination = "order") public void handleMsg(@Valid Order order) {} ! @JmsListener(destination = "order") public void handleMsg(Order order, @Header String orderType) {} ! @JmsListener(destination = “order") @SendTo("orderStatus") public OrderStatus handleMsg(Order order) {}
  49. 49. ちなみにJMS 2.0の場合 @MessageDriven(…) public class OrderMsgHandler implements MessageListener { @Override public void onMessage(Message message) { try { Order order = message.getBody(Order.class); // … } catch (JMSException e) {/**/} } }
  50. 50. ちなみにJMS 2.0の場合 @MessageDriven(…) public class OrderMsgHandler implements MessageListener { @Inject JmsContext jmsContext; @Override public void onMessage(Message message) { try { Order order = message.getBody(Order.class); // … OrderType orderType = …; jmsContext.createProducer() .setJMSCorrelationID(message.getJMSMessageID()) .send(message.getJMSReplyTo(), orderType); } catch (JMSException e) {/**/} } }
  51. 51. spring-messagingサポート • spring-messagingはSpring 4.0から導入さ れたメッセージング抽象化プロジェクト org.springframework.messaging.Message<T> T getPayload() MessageHeaders getHeaders() @JmsListener(destination = "order") @SendTo(“orderStatus") public Message<OrderStatus> handleMsg(Message<Order> order)
  52. 52. spring-messaging spring-messaging STOMP TCP JMS SQS SNS WebSocket Reactor AWS SDK for Java 4.0~ 4.1~ Spring Cloud for AWS
  53. 53. spring-messaging spring-messaging STOMP Spring TCP Integrationでも 使JMS 用されている SQS SNS WebSocket Reactor AWS SDK for Java 4.0~ 4.1~ Spring Cloud for AWS
  54. 54. JmsMessagingTemplate • spring-messagingのインタフェースを実装 • MessagingSendingOperations • MessagingRecevingOperations • MessagingRequestReplyOperations • もともとあるJmsTemplateをラップ • 例外変換サポート
  55. 55. JmsMessagingTemplate Message<Order> msg = MessageBuilder .withPayload(order) .setHeader("orderType", "sell") .build(); ! messageTemplate.send("order", msg);
  56. 56. JCache(JSR-107)サポート • JCacheによる宣言的キャッ シュに対応 • JCacheに対応したキャッシュ 製品を透過的に扱える
  57. 57. Springのキャッシュサポート Before (Spring 3.1~) org.springframework.cache.annotation.* public class BookService { @Cacheable("books") public Book findById(String id) {/**/} @Cacheable(value="books",key= "T(com.example.BookIdResolver).resolve(#isbn)") public Book findByIsbn(ISBN isbn) {/**/} @CachePut(value="books",key="#book.id") public void update(Book book) {/**/} @CacheEvict("books") public void delete(String id) {/**/} }
  58. 58. Springのキャッシュサポート Before (Spring 4.1の改善) @CacheConfig("books") public class BookService { @Cacheable public Book findById(String id) {/**/} @Cacheable(key="T(com.example.BookIdResolver).resolve(#isbn)") public Book findByIsbn(ISBN isbn) {/**/} @CachePut(key="#book.id") public void update(Book book) {/**/} @CacheEvict public void delete(String id) {/**/} } org.springframework.cache.annotation.*
  59. 59. JCacheサポート After javax.cache.annotation.* @CacheDefaults(cacheName = "books") public class BookService { @CacheResult public Book findById(String id) {/**/} @CacheResult(cacheKeyGenerator = IsbnCacheKeyGenerator.class) public Book findByIsbn(ISBN isbn) {/**/} @CachePut public void update(String id, @CacheValue Book book) {/**/} @CacheRemove public void delete(String id) {/**/}}
  60. 60. Configuration @Configuration @EnableCaching public class AppConfig { @Value("classpath:my-ehcache.xml") Resource ehCacheConfig; @Bean CacheManager cacheManager() { return new EhCacheManager(EhCacheManagerUtils .buildCacheManager(ehCacheConfig)); } // … } Before
  61. 61. Configuration Before @Configuration @EnableCaching public class AppConfig { @Bean CacheManager cacheManager() { return new JCacheManager(); } // … }
  62. 62. Configuration Before @Configuration @EnableCaching public class AppConfig { @Bean CacheManager cacheManager() { javax.cache.CacheManager cacheManager = Caching.getCachingProvider() .getCacheManager(); // JCache standard configuration … return new JCacheManager(cacheManager); } }
  63. 63. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  64. 64. 静的リソースサポート < 4.1 • 静的リソースをSpringのResouceクラ スで表現できるパスから提供 • classpath, filesystem, servlet context • 基本的なHTTPキャッシュ機構 • Expires, Cache-Control, Last- Modified
  65. 65. 静的リソースサポート < 4.1 <mvc:resources mapping="/resources/**" location="classpath:META-INF/resources/" cache-period="#{60 * 60}" /> OR @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/resources/**") .addResourceLocations("classpath:META-INF/resources/") .setCachePeriod(60 * 60); } }
  66. 66. 残る課題 • オプティマイゼーション(minify, 結合,など • 変換 (sass, less, gzipなど) • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性
  67. 67. 残る課題 • オプティマイゼーション(minify, 結合,など 変換 Ruby on Rails • (sass, のless, Asset gzipPipeline など) • 効率的のなよHTTPうなキャ機ッ能シがング欲(versioning) しい • 開発・デバッグ時の再読み込み(F5)容易性
  68. 68. 残る課題 • オプティマイゼーション(minify, 結合,など • 変換 (sass, だless, がgzip断など) る • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性
  69. 69. 最近のフロントエンド開発 •結合や変換はGulpやGrunt を使ってビルド時に解決
  70. 70. 残る課題 やらない (ビルドツール任せ) • オプティマイゼーション(minify, 結合,など • 変換 (sass, less, gzipなど) • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性 (ランタイムで本当に必要な場所のみ) やる
  71. 71. 2つのインタフェース追加 •ResourceResolver •ResourceTransformer
  72. 72. ResourceResolver •リクエストのURLからサー バー上のリソースを解決する •リソースのパブリックな URLを返す
  73. 73. ResourceResolver •PathResourceResolver •普通に存在するファイルを探して解決(これまでと同じ 挙動) •VersionResourceResolver •バージョン付きファイル名を解決。Cache Busting •GzipResourceResolver •"Accept-Encoding: gzip”でリクエストがきたら、.gz を探す •CachingResourceResolver • リソースをキャッシュする
  74. 74. 設定方法 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new VersionResourceResolver() .addContentVersionStrategy("/**")); } }
  75. 75. 設定方法 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new VersionResourceResolver() .addContentVersionStrategy("/**")); } } "/**"パターンに該当するリソースパス に対してコンテンツハッシュを使用し たバージョニングポリシーを設定
  76. 76. VersionStrategy • ContentVersionStrategy • ファイルコンテンツのmd5ハッシュ値をバージョンに使用 する • 頻繁に変更する可能性のあるファイルのバージョンに有効 • FixedVersionStrategy • プロパティファイルの値やGitのリビジョン等の固定値を バージョンに使用する • 3rdパーティライブラリファイルのバージョンに有効
  77. 77. 設定方法 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/resources/**") .addResourceLocations("classpath:META-INF/resources/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new VersionResourceResolver() .addFixedVersionStrategy("v1", "/**/hoge*.js") .addContentVersionStrategy("/**")); } }
  78. 78. org.springframework.web.servlet.resource.ResourceUrlEncodingFilter @Bean ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } HttpResponseWrapperを実装して、 HttpServletResponse#encodeURLで 変換後のパスを返す
  79. 79. function foo() { return "Hello World!"; } src/main/resources/public/foo.js
  80. 80. function foo() { return "Hello World!"; } src/main/resources/public/foo.js Thymeleaf JSP <script th:src="@{/public/foo.js}"></script> <script src="<c:url value="/public/foo.js" / >" ></script>
  81. 81. function foo() { return "Hello World!"; } src/main/resources/public/foo.js Thymeleaf JSP <script th:src="@{/public/foo.js}"></script> <script src="<c:url value="/public/foo.js" / >" ></script> <script src="/public/foo-c2efac2672ad1ab3753ae1902c0af8d3. js"></ script>
  82. 82. function foo() { return "Hello World!"; } src/main/resources/public/foo.js Thymeleaf JSP <script th:src="@{/public/foo.js}"></script> <script src="<c:url value="/public/foo.js" / >" ></script> <script src="/public/foo-c2efac2672ad1ab3753ae1902c0af8d3. js"></ script> 初回は200 OK 2回目以降は304 Not Modified が返り、クライアントでキャッシュ
  83. 83. function foo() { return "Hello World2!"; } src/main/resources/public/foo.js Thymeleaf JSP <script th:src="@{/public/foo.js}"></script> <script src="<c:url value="/public/foo.js" / >" ></script> <script src="/public/foo-b17a959b58873484644b5ff7161b6475. js"></ script>
  84. 84. function foo() { return "Hello World2!"; } src/main/resources/public/foo.js ファイル内容が代わり、 バージョン(ファイル名) Thymeleaf JSP <script th:src="@{/public/foo.js}"></script> <script src="<c:url value="/public/foo.js" / >" ></script> <script src="/public/foo-b17a959b58873484644b5ff7161b6475. js"></ script> が変わったので 再度200 OKでキャッシュ破棄
  85. 85. function foo() { return "Hoge!"; } src/main/resources/public/hoge.js Thymeleaf <script th:src="@{/public/hoge.js}"></ script> JSP <script src="<c:url value="/public/ hoge.js" />" ></script> <script src="/public/v1/hoge.js"></script>
  86. 86. 設定方法(続き) @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addFixedVersionStrategy("v1", "/**/hoge*.js") .addContentVersionStrategy("/**")); } }
  87. 87. 設定方法(続き) ここをtrueにする @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addFixedVersionStrategy("v1", "/**/hoge*.js") .addContentVersionStrategy("/**")); } } と自動で CacheResolverも 追加される
  88. 88. 設定方法(続き) ここをtrueにする @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addFixedVersionStrategy("v1", "/**/hoge*.js") .addContentVersionStrategy("/**")); } } と自動で CacheResolverも 追加される 最後にPathResolver も自動で追加される
  89. 89. ResourceTransformer •CssLinkResourceTransformer •CSSコンテンツ中のパスを書き換える •AppCacheManifestResourceTransformer • HTML5のAppCache manifestファイル中のパ スを書き換える • manifestファイルのコメントにコンテンツの ハッシュ値を挿入する •CachingResourceTransformer •キャッシュ済みコンテンツを返す
  90. 90. 設定方法 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addContentVersionStrategy("/**")) .addTransformer(new AppCacheManifestTransformer()); } }
  91. 91. 設定方法 ここをtrueにする @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addContentVersionStrategy("/**")) .addTransformer(new AppCacheManifestTransformer()); } } と自動で CacheTransformer も追加される
  92. 92. 設定方法 ここをtrueにする @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(true /* cacheするかどうか */) .addResolver(new GzipResourceResolver()) .addResolver(new VersionResourceResolver() .addContentVersionStrategy("/**")) .addTransformer(new AppCacheManifestTransformer()); } } と自動で CacheTransformer も追加される VersionResolverを 登録すると CssLinkTransformer も自動で追加される
  93. 93. src/main/resources/public/app.css @import url('bar.css'); src/main/resources/public/bar.css strong {color : red;} Thymeleaf <link rel="stylesheet" th:href="@{/public/app.css}"/> JSP <link rel="stylesheet" href="<c:url value="/public/app.css" />" />
  94. 94. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" />
  95. 95. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" /> app-76f48a0aee85c84475a90ce82c7e610c.css @import url('bar-dc1a9a1dc7a9264c8db2e66898f4759a. css');
  96. 96. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" /> app-76f48a0aee85c84475a90ce82c7e610c.css @import url('bar-dc1a9a1dc7a9264c8db2e66898f4759a. css'); CssLinkResourceTransformerによっ てcssの中のリンクもバージョン付き に変換される
  97. 97. @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Autowired Environment env; @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ boolean devMode = this.env.acceptsProfiles("dev"); boolean useResourceCache = !devMode; registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(useResourceCache) …; } }
  98. 98. @Configuration @EnableWebMvc profileでキャッシュするか public class WebConfig @Autowired どextends うかWebMvcConfigurerAdapter 切り替えると良い { Environment env; @Override public void addResourceHandlers(ResourceHandlerRegistry registry){ boolean devMode = this.env.acceptsProfiles("dev"); boolean useResourceCache = !devMode; registry.addResourceHandler("/public/**") .addResourceLocations("classpath:/public/") .setCachePeriod(60 * 60 * 24 * 365 /* 1年 */); .resourceChain(useResourceCache) …; } }
  99. 99. その他のURL取得方法・・・ JSP <%=((ResourceUrlProvider) request .getAttribute("org.springframework.web.servlet.resource.ResourceUrlProvider")) .getForLookupPath("/public/app.css")%>
  100. 100. XMLによる定義 <mvc:resources mapping="/public/**" location="classpth:/public/" cache-period="#{60 * 60 * 24 * 365}"> <mvc:resource-chain> <mvc:resource-cache /> <mvc:resolvers> <mvc:version-resolver> <mvc:content-version-strategy patterns="/**"/> </mvc:version-resolver> </mvc:resolvers> </mvc:resource-chain> </mvc:resources>
  101. 101. XMLによる定義 そろそろXML辛い・・・ <mvc:resources mapping="/public/**" location="classpth:/public/" cache-period="#{60 * 60 * 24 * 365}"> <mvc:resource-chain> <mvc:resource-cache /> <mvc:resolvers> <mvc:version-resolver> <mvc:content-version-strategy patterns="/**"/> </mvc:version-resolver> </mvc:resolvers> </mvc:resource-chain> </mvc:resources>
  102. 102. フルセットなAsset Pipelineが欲 しい場合 • http://wuic.github.io/
  103. 103. http://wuic.github.io/project.html#roadmap
  104. 104. ResourceResolverと VersionStrategyが提供されている @Autowired WuicFacade wiucFacade; ! @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/wuic/**") .resourceChain(true) .addResolver(new VersionResourceResolver() .addVersionStrategy(new WuicVersionStrategy(), "/**/*")) .addResolver(new WuicPathResourceResolver(wuicFacade)); }
  105. 105. Spring 4.1を始めましょう
  106. 106. まとめ • SpringOne 2gx • 参加してコネクションを作ろう • 来年はワシントン • Spring 4.1の新機能 • Web機能の改善 • JMS機能の改善 • Cache機能の改善http://bit.ly/hajiboot

×