• Like
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
Upcoming SlideShare
Loading in...5
×

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

  • 0 views
Uploaded on

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
0
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
0
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. SpringOne 2GX 2014 参加報告 & Spring 4.1について JSUG勉強会 #jsug 2014-12-11 Toshiaki Maki (@making)
  • 2. 自己紹介 • @making • http://blog.ik.am • 公私ともにSpringヘービーユーザー • 日本Javaユーザーグループ幹事
  • 3. 祝「はじめてのSpring Boot」出版 http://bit.ly/hajiboot
  • 4. 今日のコンテンツ • SpringOne 2gx 2014の様子 (5分) • Spring 4.1の新機能紹介 (45分)
  • 5. 今日話さないこと
  • 6. SpringOne 2gx 2014の様子
  • 7. SpringOne 2gx 2014 • 2014/09/09~11 • ダラス
  • 8. SpringOne 2gx 2014 • 5つのトラック約120セッション • Core Spring • Data & Integration •Web & JavaScript • Applied Spring • Big Data • http://www.slideshare.net/SpringCentral/tag/springone2gx2014
  • 9. Dallas Omni Hotel
  • 10. Food
  • 11. Beers
  • 12. 先週銀座で飲んだ(どうでもいい)
  • 13. Talk with Pivotal guys
  • 14. Josh Long (@starbuxman)
  • 15. 効果 (1/2) http://spring.io/blog/2014/10/08/this-week-in-spring-october-7th-2014
  • 16. 効果 (2/2) http://spring.io/blog/2014/10/29/this-week-in-spring-october-28-2014 !
  • 17. 会場めっちゃ寒かった 景品のパーカー をもらうため会 場に散らばった 全てのバッジを 必死で探したw
  • 18. SpringOne 2gx 2015 • 来年はワシントンで開催予定
  • 19. Spring 4.1の新機能紹介
  • 20. 紹介するセッション http://www.slideshare.net/SpringCentral/tag/springone2gx2014
  • 21. Spring 4.1 • 2014年9月リリース • 現時点で4.1.3.RELEASE • メインストリームは4.2へ移行。 4.1はメンテナンスモードへ Spring Bootは1.2から対応
  • 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. 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. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  • 25. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  • 26. 静的リソースサポートの改善 Spring MVC 4.1 の目玉機能
  • 27. 説明に時間がかかる ので最後にまわす
  • 28. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  • 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. WebじゃないけどOptinal対応 Before @Autowired(required=false) FooService fooService; After @Autowired Optional<FooService> fooService;
  • 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. 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. JSONPサポート @ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { super("callback"); } }
  • 34. JSONPサポート @RestController class UserController { @RequestMapping("/user") User getUser() { return new User("demo", "password"); } } GET /user?callback=foo foo({"username":"demo", "password":"password"})
  • 35. ResponseBodyAdvice • @ResponseBody/ResponseEntityメ ソッドへのコールバック • 2つの実装が組み込まれている • JsonViewResponseBodyAdvice • AbstractJsonpResponseBodyAdvice
  • 36. 新しいHttpMessageConverter追加 GsonHttpMessageConverter 軽量なJSONライブラリGSONを使用してHTTP経由で JSONをやりとり(通常はJacksonを使用する) ProtobufHttpMessageConverter HTTP経由でGoogleのシリアライゼーションフォーマッ トProtocol Bufferをやりとり MappingJackson2XmlHttpMessageConverter Jackson XMLを使用してHTTP経由でXMLをやりとり(通 常はJAXBを使用する)
  • 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. 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. 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. 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. 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. Cacheの改善JMSの改善 @JmsListenerサポート spring-messagingサポート JCache(JSR-107) サポート
  • 43. Cacheの改善JMSの改善 @JmsListenerサポート spring-messagingサポート JCache(JSR-107) サポート
  • 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. @JmsListener After (Spring 4.1~) @Component public class OrderMsgHandler { @JmsListener(destination = "order") public void handleMsg(Order order) { /**/ } } <jms:annotation-driven /> <jms:listener-container … />
  • 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. 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. 柔軟なメソッドシグニチャ対応 @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. ちなみに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. ちなみに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. 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. spring-messaging spring-messaging STOMP TCP JMS SQS SNS WebSocket Reactor AWS SDK for Java 4.0~ 4.1~ Spring Cloud for AWS
  • 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. JmsMessagingTemplate • spring-messagingのインタフェースを実装 • MessagingSendingOperations • MessagingRecevingOperations • MessagingRequestReplyOperations • もともとあるJmsTemplateをラップ • 例外変換サポート
  • 55. JmsMessagingTemplate Message<Order> msg = MessageBuilder .withPayload(order) .setHeader("orderType", "sell") .build(); ! messageTemplate.send("order", msg);
  • 56. JCache(JSR-107)サポート • JCacheによる宣言的キャッ シュに対応 • JCacheに対応したキャッシュ 製品を透過的に扱える
  • 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. 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. 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. Configuration @Configuration @EnableCaching public class AppConfig { @Value("classpath:my-ehcache.xml") Resource ehCacheConfig; @Bean CacheManager cacheManager() { return new EhCacheManager(EhCacheManagerUtils .buildCacheManager(ehCacheConfig)); } // … } Before
  • 61. Configuration Before @Configuration @EnableCaching public class AppConfig { @Bean CacheManager cacheManager() { return new JCacheManager(); } // … }
  • 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. Web機能の改善 静的リソース制御の改善 Controller引数のOptionalサポート Controllerの返値のListenableFutureサポート Jacksonの@JsonViewサポート JSONPサポート ResponseBodyAdvice追加 新しいHttpMessageConverter追加 EL関数 s:mvcUrl 追加 ResponseEntityビルダーサポート GroovyMarkupTemplateサポート
  • 64. 静的リソースサポート < 4.1 • 静的リソースをSpringのResouceクラ スで表現できるパスから提供 • classpath, filesystem, servlet context • 基本的なHTTPキャッシュ機構 • Expires, Cache-Control, Last- Modified
  • 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. 残る課題 • オプティマイゼーション(minify, 結合,など • 変換 (sass, less, gzipなど) • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性
  • 67. 残る課題 • オプティマイゼーション(minify, 結合,など 変換 Ruby on Rails • (sass, のless, Asset gzipPipeline など) • 効率的のなよHTTPうなキャ機ッ能シがング欲(versioning) しい • 開発・デバッグ時の再読み込み(F5)容易性
  • 68. 残る課題 • オプティマイゼーション(minify, 結合,など • 変換 (sass, だless, がgzip断など) る • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性
  • 69. 最近のフロントエンド開発 •結合や変換はGulpやGrunt を使ってビルド時に解決
  • 70. 残る課題 やらない (ビルドツール任せ) • オプティマイゼーション(minify, 結合,など • 変換 (sass, less, gzipなど) • 効率的なHTTPキャッシング(versioning) • 開発・デバッグ時の再読み込み(F5)容易性 (ランタイムで本当に必要な場所のみ) やる
  • 71. 2つのインタフェース追加 •ResourceResolver •ResourceTransformer
  • 72. ResourceResolver •リクエストのURLからサー バー上のリソースを解決する •リソースのパブリックな URLを返す
  • 73. ResourceResolver •PathResourceResolver •普通に存在するファイルを探して解決(これまでと同じ 挙動) •VersionResourceResolver •バージョン付きファイル名を解決。Cache Busting •GzipResourceResolver •"Accept-Encoding: gzip”でリクエストがきたら、.gz を探す •CachingResourceResolver • リソースをキャッシュする
  • 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. 設定方法 @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. VersionStrategy • ContentVersionStrategy • ファイルコンテンツのmd5ハッシュ値をバージョンに使用 する • 頻繁に変更する可能性のあるファイルのバージョンに有効 • FixedVersionStrategy • プロパティファイルの値やGitのリビジョン等の固定値を バージョンに使用する • 3rdパーティライブラリファイルのバージョンに有効
  • 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. org.springframework.web.servlet.resource.ResourceUrlEncodingFilter @Bean ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } HttpResponseWrapperを実装して、 HttpServletResponse#encodeURLで 変換後のパスを返す
  • 79. function foo() { return "Hello World!"; } src/main/resources/public/foo.js
  • 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. 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. 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. 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. 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. 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. 設定方法(続き) @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. 設定方法(続き) ここを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. 設定方法(続き) ここを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. ResourceTransformer •CssLinkResourceTransformer •CSSコンテンツ中のパスを書き換える •AppCacheManifestResourceTransformer • HTML5のAppCache manifestファイル中のパ スを書き換える • manifestファイルのコメントにコンテンツの ハッシュ値を挿入する •CachingResourceTransformer •キャッシュ済みコンテンツを返す
  • 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. 設定方法 ここを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. 設定方法 ここを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. 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. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" />
  • 95. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" /> app-76f48a0aee85c84475a90ce82c7e610c.css @import url('bar-dc1a9a1dc7a9264c8db2e66898f4759a. css');
  • 96. <link rel="stylesheet" href="/public/ app-76f48a0aee85c84475a90ce82c7e610c.css" /> app-76f48a0aee85c84475a90ce82c7e610c.css @import url('bar-dc1a9a1dc7a9264c8db2e66898f4759a. css'); CssLinkResourceTransformerによっ てcssの中のリンクもバージョン付き に変換される
  • 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. @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. その他のURL取得方法・・・ JSP <%=((ResourceUrlProvider) request .getAttribute("org.springframework.web.servlet.resource.ResourceUrlProvider")) .getForLookupPath("/public/app.css")%>
  • 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. 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. フルセットなAsset Pipelineが欲 しい場合 • http://wuic.github.io/
  • 103. http://wuic.github.io/project.html#roadmap
  • 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. Spring 4.1を始めましょう
  • 106. まとめ • SpringOne 2gx • 参加してコネクションを作ろう • 来年はワシントン • Spring 4.1の新機能 • Web機能の改善 • JMS機能の改善 • Cache機能の改善http://bit.ly/hajiboot