Spring Boot で Boot した後に作る Web アプリケーション基盤/spring-boot-application-infrastructure

Spring Boot で Boot した後に作る Web アプリケーション基盤/spring-boot-application-infrastructure

JJUG CCC 2016 Spring で発表した時の資料です。

422505eb0de893a7a3a21dd466e3b0ba?s=128

sinsengumi

May 21, 2016
Tweet

Transcript

  1. 2.

    > < 2 JJUG CCC 2016 Spring. 2016/05/21 • ໊લ

    : ٢ా ๎໵ / @sinsengumi • ৬ۀ : ιϑτ΢ΣΞΤϯδχΞ • ओʹαʔόʔαΠυΛ୲౰ • ࠷ॳ͸ Web σβΠφʔΛ͍ͯ͠·ͨ͠ • SIer ͔ΒΤϜεϦʔגࣜձࣾ΁స৬ • ॴଐ : ΤϜεϦʔגࣜձࣾ • 3೥໨ • Spring ྺ : 2 ೥͘Β͍ • JJUG ॳࢀՃʂ ࣗݾ঺հ
  2. 3.

    > < 3 JJUG CCC 2016 Spring. 2016/05/21 ձࣾ঺հʢΤϜεϦʔגࣜձࣾʣ •

    ೔ຊͷҩࢣ 8 ׂɺੈքͰ 350 ສਓͷҩࢣ޲͚αʔϏεΛӡӦ͢Δ
 ҩྍܥϕϯνϟʔاۀ • ϛογϣϯ : ΠϯλʔωοτͷྗͰҩྍΛมֵ͢Δ • ւ֎ల։ɺ࣏ݧɾήϊϜͳͲ৽ࣄۀ΋ੵۃత • JavaɺJVMʢScalaɾKotlinʣΛଟ਺ͷαʔϏεͰར༻ ΤϯδχΞ͸ৗʹืूதʂ https://jobs.m3.com/engineer Medicine − ҩྍ Media − ϝσΟΞ Metamorphosis − มֵ ϋοΧιϯͷ༷ࢠ
  3. 4.

    > < 4 JJUG CCC 2016 Spring. 2016/05/21 ໨࣍ 1.

    Spring Boot ʹ͍ͭͯ
 2. Boot ͨ͠ɺͦͷޙɾɾɾ 1. URL ઃܭ 2. ྫ֎ 3. τϥϯβΫγϣϯ 4. όον 5. ϓϩύςΟ 6. ϩΪϯά 7. ηΩϡϦςΟ 8. ͦͷଞ
 3. ·ͱΊ
  4. 6.

    > < 6 JJUG CCC 2016 Spring. 2016/05/21 • Java

    EE (JAX-RS, CDI, JPA, JSF) • Play Framework • Struts2 • Seasar2 • Dropwizard, Ninja etc • Spring (not Boot) օ͞Μ͸ɺ৽نʹ Java ͰΞϓϦέʔγϣϯΛ࡞Ζ͏ͱࢥͬͨ࣌ɺ ࠓʢ2016೥ݱࡏʣͳΒԿΛબͼ·͔͢ʁ Spring Boot ʹ͍ͭͯʢ1ʣ ͏ʔΜɾɾɾɾ ॏްա͗Δ͠ɺJava EE αʔόʔͷ४උ͕ɾɾ Java ൛αϙʔτ੾ΒΕͦ͏Ͱා͍ɾɾɾ ͳΜ͔੬ऑੑ͕ɾɾɾ 2016೥9݄ʹ EOL ۀ຿ͰऔΓ૊Ήʹ͸·ͩ·ͩރΕͯͳͦ͞͏ Spring Boot ͕͋Δࠓɾɾɾ
  5. 7.

    > < 7 JJUG CCC 2016 Spring. 2016/05/21 Spring Boot

    ʹ͍ͭͯʢ2ʣ ͦ͜ͰɺSpring Boot ʂ SPRING INITIALIZR Λ࢖͑͹ɺಈ͘ΞϓϦέʔγϣϯ͕͙͢Ͱ͖Δɻ https://start.spring.io/ 1. SPRING INITIALIZR ʹΞΫηε͠ɺ࢖͍͍ͨػೳΛબ୒͠ɺDLɻ 2. DL ͨ͠ Zip Λղౚ͢Δɻ 3. mvn spring-boot:run ͢Δɻ
 ʢ΋͘͠͸ IDE ͔Β main ϝιουΛୟ͘ʣ
  6. 8.

    > < 8 JJUG CCC 2016 Spring. 2016/05/21 Spring Boot

    ʹ͍ͭͯʢ3ʣ [demo] mvn spring-boot:run [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building demo 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> spring-boot-maven-plugin:1.3.3.RELEASE:run (default-cli) > test-compile @ demo >>> [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ demo --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ demo --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /Users/sinsengumi/Downloads/spring-init/demo/target/classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ demo --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory /Users/sinsengumi/Downloads/spring-init/demo/src/test/resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ demo --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /Users/sinsengumi/Downloads/spring-init/demo/target/test-classes [INFO] [INFO] <<< spring-boot-maven-plugin:1.3.3.RELEASE:run (default-cli) < test-compile @ demo <<< [INFO] [INFO] --- spring-boot-maven-plugin:1.3.3.RELEASE:run (default-cli) @ demo --- . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.3.RELEASE) ͓͓ʔײಈ
  7. 9.

    > < 9 JJUG CCC 2016 Spring. 2016/05/21 Boot ͸ૣ͍͕ɾɾɾʢ1ʣ

    ʮΑʔ͠ɺ͡Ό͋ૣ଎࡞Γ࢝ΊͪΌ͏ͧʔʯ ਺෼ޙɾɾɾɾ ʮ͑ʔͱɺྫ֎ॲཧ͸Ͳ͏͢Δͷ͕͍͍Μͩʁʯ ʮτϥϯβΫγϣϯ͔͚͍ͨΜ͚ͩͲɾɾɾʯ
  8. 12.

    > < 12 JJUG CCC 2016 Spring. 2016/05/21 Boot ͸ૣ͍͕ɾɾɾʢ4ʣ

    Boot ͸͔֬ʹૣ͍ʂ ͕ɺ͔ͦ͜Β͸΋͸΍ Spring ͷੈքɻࢼ͞ΕΔ Spring ྗɾɾɾʂ ʢ୔ࢁͷϥΠϒϥϦɺ૊Έ߹ΘͤɺSpring ͷ஌ࣝʣ ͦ͜ͰɺຊηογϣϯͰ͸ɺ Spring Boot Λ༻͍ͨී௨ͷ Web ΞϓϦέʔγϣϯΛ࡞੒͢Δࡍʹɺ ࠷ॳʹ΍Δ΂͖ΞϓϦέʔγϣϯج൫ͷߏஙΛ Spring ͰͲ͏͢Δͷ͔ʁ Λத৺ʹ͓࿩͠͠·͢ɻ ΰʔϧ͸ ʰػೳ։ൃ Readyʱͳঢ়ଶΛ࡞Δ͜ͱ
  9. 13.

    > < 13 JJUG CCC 2016 Spring. 2016/05/21 Boot ͸ૣ͍͕ɾɾɾʢ5ʣ

    େํ਑ • Spring ͷํ਑ʹै͏ʢRail ʹ৐Δతͳʣ
 @Controller, @Service, @Repository Λ࢖ͬͨجຊతͳϨΠϠʔߏ੒ • ίʔυΛͳΔ΂͘ॻ͔ͳ͍
 ॻ͔ͳ͍ͨΊʹϑϨʔϜϫʔΫΛ࢖͍ͬͯΔ • ۀ຿ػೳΛ࡞Δ࣌ʹɺ͸·Βͳ͍ɺ೰·ͳ͍Α͏ͳઃܭ
  10. 15.

    > < 15 JJUG CCC 2016 Spring. 2016/05/21 • Ͳ͏͍͏

    URL ମܥ͕͋Δ͔ʁ
 ݴ͍׵͑ΔͱɺʮαʔϏε෼ׂʯΛݕ౼͢Δͱ͍͏͜ͱ
 • ओʹɺϢʔβը໘ɺ؅ཧը໘ɺAPIʢ֎޲͖ɺ಺޲͖ʣ౳Λ
 ಉҰΞϓϦ্ʹࡌͤΔ͔ʁɺผΞϓϦʹ͢Δ͔ʁͱ͍͏࿩ɻ
 microservices తʹ͸෼ׂͨ͠΄͏͕ྑ͍͕ɺ
 Πϯϑϥίετͷ૿େ΍ɺΞϓϦɾϏδωεͷن໛ʹ΋ΑΔ͸ͣɻ ͍͖ͳΓ Spring ͱ͸ؔ܎ͳ͍࿩Ͱ͕͢ɺ Web ΞϓϦΛ࡞Δ্Ͱ؊৺ͳͱ͜ΖͳͷͰ·ͣ͸͡Ίʹݕ౼͠·͢ɻ ػೳ։ൃΛ͢Δલʹ URL ઃܭʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ
  11. 16.

    > < 16 JJUG CCC 2016 Spring. 2016/05/21 • Ϣʔβը໘

    [ / ] • ؅ཧը໘ [ /admin ] • API ֎޲͖ [ /api ] • API ಺޲͖ [ /api/internal ] ຊηογϣϯͰ͸ ಉҰΞϓϦ಺ʹ͜ΕΒΛڞଘͤ͞Δ͜ͱΛલఏͱͯ͠࿩Λ͠·͢ɻ ػೳ։ൃΛ͢Δલʹ URL ઃܭʹ͍ͭͯߟ͍͑ͨ͜ͱʢ2ʣ
  12. 17.

    > < 17 JJUG CCC 2016 Spring. 2016/05/21 URL ઃܭΛίʔυͰදݱ͓ͯ͘͠ʢ1ʣ

    Ϣʔβը໘ɺ؅ཧը໘ɺAPIʢ֎޲͖ɺ಺޲͖ʣΛ enum Ͱఆٛ͢Δɻ @AllArgsConstructor @Getter public enum Site { API_INTERNAL("APIʢ಺޲͖ʣ", "/api/internal", false), API_EXTERNAL("APIʢ֎޲͖ʣ", "/api", false), SCREEN_ADMIN("؅ཧը໘", "/admin", true), SCREEN_USER("Ϣʔβը໘", "", true); private String label; private String baseUrl; private boolean protectCsrf; // ྻڍࢠͷॱ൪Λม͑Δͱɺޡ൑ఆ͢ΔͷͰ஫ҙɻ public static Site of(String url) { if (url == null) { return SCREEN_USER; } for (Site location : values()) { if (url.startsWith(location.baseUrl)) { return location; } } return SCREEN_USER; } } enum Ͱ URL ମܥΛఆٛ͢Δ URL ͔ΒͲ͜ʹΞΫηε͍ͯ͠Δ͔ Λ൑ఆ͢ΔϝιουΛ༻ҙ͓ͯ͘͠
  13. 18.

    > < 18 JJUG CCC 2016 Spring. 2016/05/21 URL ઃܭΛίʔυͰදݱ͓ͯ͘͠ʢ2ʣ

    ίʔυͱͯ͠දݱ͢Δ͜ͱͰɺ͍ΖΜͳ৔໘Ͱ࢖͑ΔͷͰɺΦεεϝͰ͢ɻ ʢfilter, interceptor ͷఆٛΛ͢ΔࡍɺύεΛϋʔυίʔυ͠ͳ͍ͰࡁΉͳͲɻ ৄ͘͠͸ޙड़ʣ ΋ͪΖΜɺController Ϋϥεͷ package ΋ Site ຖʹ෼͚·͢ɻ src/main/java/com/example !"" Application.java !"" controller # !"" Site.java # !"" api # # !"" external # # # $"" HelloController.java # # $"" internal # # $"" HelloController.java # $"" screen # !"" admin # # $"" HelloController.java # $"" user # $"" HelloController.java
  14. 20.

    > < 20 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢Δલʹྫ֎ʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ •

    ྫ֎͕ى͖ͨ࣌ʹԿΛ͢Δ͔ʁʢϩΪϯάɺ௨஌ etcʣ • ྫ֎͕ى͖ͨ࣌ʹͲ͜΁ߦ͔͘ʁʢը໘ͷ৔߹ɺAPI ͷ৔߹ʣ • εςʔλείʔυ΋ͪΌΜͱઃఆ͍ͨ͠ • ݕࠪྫ֎ɺඇݕࠪྫ֎ͷ࢖༻ํ਑ • ͢΂ͯͷྫ֎Λิ଍͍ͨ͠ʢTomcat ͷΤϥʔը໘ग़Δͱ͔μα͍ʣ • ࢖͍ͬͯΔϑϨʔϜϫʔΫͰ͸ɺͲ͏ॲཧ͢΂͖͔ఆ͍ٛͯ͠Δ͔ʁ 
 ʢSpring తʹ͸ʁʣ
  15. 22.

    > < 22 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ • Filter • ˏController ͷ Interceptor • ݸผͷ @Controller ʹ @ExceptionHandler • @ResponseStatus Λ෇༩ͨ͠ྫ֎Λ Throw • @ControllerAdvice Ͱ @ExceptionHandler • Spring Boot ͷ ErrorController ΍Γํ͕ͨ͘͞Μ͋Γ·͢ɻ
  16. 23.

    > < 23 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ2ʣ • status code ͕ηοτ͞Ε͍ͯͳ͍ • ͢΂ͯͷྫ֎Λิ଍Ͱ͖ͳ͍ʢϓϨθϯςʔγϣϯ૚ɺ404 Τϥʔ౳ʣ άϩʔόϧͳྫ֎ॲཧͷํ๏ͱͯ͠ɺ άάΔͱΑ͘ग़ͯ͘Δ @ControllerAdvice ͸͍͔ͭ͘໰୊͕͋Δɻ @Slf4j @ControllerAdvice(“com.example.controller.admin") public class GlobalControllerAdvice { @ExceptionHandler(Exception.class) public String handleException(Exception e, HttpServletResponse response, Model model) { // status code ͸ઃఆ͞Εͯͳ͍ͷͰɺ͜͜Ͱઃఆ͢Δɻ // ͲΜͳ status code Λઃఆ͢Δ͔͸ Exception ͔Β൑ఆ͢Δඞཁ͕͋Δ͕ɺಠࣗྫ֎ͷ৔߹͸͍͍͕ɺ // Spring ͕౤͛ͯ͘Δྫ֎ʢMissingServletRequestParameterException ͱ͔ʣ͸ɾɾɾɾ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); log.error("Error!!", e); model.addAttribute("stackTrace", ExceptionUtils.getStackTrace(e)); return "admin/error"; } }
  17. 24.

    > < 24 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ 1. ExceptionHandlerExceptionResolver 2. ResponseStatusExceptionResolver 3. DefaultHandlerExceptionResolver Spring Boot Ͱ͸ɺErrorController Ͱ΍Δͷ͕Φεεϝɻ ErrorController ͸͜ΕΒ͕ద༻͞Εͨޙʹݺ͹ΕΔɺ web.xml ͷ error-page ૬౰ͷॲཧɻ ʢ͜Ε͸ Spring MVC Ͱ͸ͳ͘ɺ૊ΈࠐΈͷ ServletContainer ͕ॲཧ͍ͯ͠Δʣ σϑΥϧτͰ͸ɺʮWhitelabel Error PageʯΛදࣔ͢Δ BasicErrorController ͱ͍͏΋ͷ͕࣮૷͞Ε͍ͯΔɻ ͜ΕΛಠࣗͷ ErrorController ʹஔ͖׵͑Δɻ Spring MVC Ͱ͸ɺҎԼͷ HandlerExceptionResolver ͕ॱʹݺ͹ΕΔɻ @ExceptionHandler Λॲཧ͢Δ @ResponseStatus Λॲཧ͢Δ FWʢSpringMVCʣͰى͖ͨྫ֎ Λॲཧ͢Δ
  18. 25.

    > < 25 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ ϒϥ΢βʢAccept: text/htmlʣͰΞΫηε͢Δͱɺը໘Λฦ͢ɻ [~] curl http://localhost:8080/admin/hello { "timestamp" : 1462114091743, "status" : 400, "error" : "Bad Request", "exception" : "org.springframework.web.bind.MissingServletRequestParameterException", "message" : "Required String parameter 'name' is not present", "path" : "/admin/hello" } ϒϥ΢βҎ֎ͰΞΫηε͢ΔͱɺJSON Λฦ͢ɻ
  19. 26.

    > < 26 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ5ʣ 1. ΧελϜ ErrorController ͷ࣮૷ʢΤϥʔॲཧΛҰखʹҾ͖ड͚Δʣ 2. ֤ Site ຖͷΤϥʔॲཧͷ࣮૷ʢը໘ͳΒΤϥʔը໘ɺAPI ͳΒ JSONʣ 3. ಠࣗྫ֎ʹ͸ @ResponseStatus Λ͚ͭΔ ͢΂ͯͷΤϥʔΛิ଍ͭͭ͠ɺ͍͍ײ͡ʹΤϥʔΛॲཧ͢Δɻ application.properties # server.error.path Λઃఆ͢ΔʢσϑΥϧτ͸ /errorʣ server.error.path=/globalError # 404 ͷ࣌΋ྫ֎Λൃੜͤ͞Δ spring.mvc.throw-exception-if-no-handler-found=true ४උͱͯ͠ɺɺ
  20. 27.

    > < @Slf4j @Controller public class GlobalErrorController implements ErrorController {

    public static final String ERROR_EXCEPTION = "com.example.demo.error.exception"; @Value("${server.error.path:${error.path:/error}}") private String errorPath; @Autowired private ErrorAttributes errorAttributes; @Override public String getErrorPath() { return errorPath; } @RequestMapping(value = "${server.error.path:${error.path:/error}}") public String error(HttpServletRequest req) { Throwable error = errorAttributes.getError(new ServletRequestAttributes(req)); String requestURI = (String) req.getAttribute("javax.servlet.forward.request_uri"); Site site = Site.of(requestURI); req.setAttribute(ERROR_EXCEPTION, error); log.warn("Caught an error. site = {}, requestURI = {}", site, requestURI); return "forward:" + site.getBaseUrl() + "/error"; } } ΧελϜ ErrorController ͷ࣮૷ 27 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ6ʣ ErrorController ΠϯλϑΣʔεͷ࣮૷ @RequestMapping ʹΤϥʔ࣌ͷ ࣮ॲཧΛهड़͢Δ Ͳ͜ͰΤϥʔ͕ग़͔ͨΛ൑ఆ͢Δ Τϥʔ৘ใΛه࿥͠ɺ ֤ Site ͷΤϥʔॲཧʹ forward ͢Δ
  21. 28.

    > < 28 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ7ʣ @Slf4j @RestController public class ErrorController { @RequestMapping(value = "/api/internal/error") public ErrorResponse error(HttpServletRequest request) { Throwable e = (Throwable) request.getAttribute(GlobalErrorController.ERROR_EXCEPTION); String errorCode = RandomStringUtils.randomAlphabetic(15); log.error(e.getMessage(), e); return ErrorResponse.build(errorCode, e); } } API ͷΤϥʔॲཧ @Slf4j @Controller public class ErrorController { @RequestMapping("/admin/error") public String error(HttpServletRequest request, Model model) { Throwable e = (Throwable) request.getAttribute(GlobalErrorController.ERROR_EXCEPTION); String errorCode = RandomStringUtils.randomAlphabetic(15); log.error(e.getMessage(), e); model.addAttribute("errorCode", errorCode); model.addAttribute("stackTrace", ExceptionUtils.getStackTrace(e)); return "screen/admin/error"; } } ؅ཧը໘ͷΤϥʔॲཧ ϩάΛు͍ͨΓɺ௨஌Λͨ͠Γ ϩάΛు͍ͨΓɺ௨஌Λͨ͠Γ API ͳͷͰɺΤϥʔϨεϙϯεΛฦ͢ ը໘ͳͷͰɺΤϥʔը໘Λฦ͢
  22. 29.

    > < 29 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (MVC) Ͱ͸Ͳ͏͢Δ͔ʁʢ8ʣ // γεςϜΤϥʔ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public class ApplicationException extends RuntimeException { public ApplicationException(String message) { super(message); } } // ೝՄΤϥʔ @ResponseStatus(HttpStatus.FORBIDDEN) public class AuthorizationException extends RuntimeException { public AuthorizationException(String message) { super(message); } } // NotFound Τϥʔ @ResponseStatus(HttpStatus.NOT_FOUND) public class ItemNotFoundException extends RuntimeException { public ItemNotFoundException(String message) { super(message); } } @ResponseStatus Λ෇͚ͨྫ֎ΛϏδωεϩδοΫ͔Β Throw ͢Δ
  23. 30.

    > < 30 JJUG CCC 2016 Spring. 2016/05/21 ࣮ྫʢAPI ͷ৔߹ʣʢ1ʣ

    @RestController public class HelloController { @RequestMapping("/api/internal/hello") public String hello(@RequestParam("name") String name) { if (name.equals("yoshida")) { throw new AuthorizationException("AuthorizationException error."); } return "Hello. " + name + "͞Μ"; } } @ResponseStatus(HttpStatus.FORBIDDEN) ͷ͍ͭͨ ྫ֎Λ Throw ͢Δ name ͕ແ͍ͱ͖͸ Spring ͔Β MissingServletRequestParameterException ͕ Throw ͞ΕΔ
  24. 31.

    > < 31 JJUG CCC 2016 Spring. 2016/05/21 ࣮ྫʢAPI ͷ৔߹ʣʢ2ʣ

    [~] curl -v http://localhost:8080/api/internal/hello?name=yoshida ... < HTTP/1.1 403 Forbidden ... { "code" : "XNBzNfxhiJedzcj", "message" : "AuthorizationException error.", "errorClass" : "com.example.exception.AuthorizationException" } [~] curl -v http://localhost:8080/api/internal/hello ... < HTTP/1.1 400 Bad Request ... { "code" : "oQhiQAZUmIUMplO", "message" : "Required String parameter 'name' is not present", "errorClass" : "org.springframework.web.bind.MissingServletRequestParameterException" } 400 ͕ઃఆ͞Ε͍ͯΔ 403 ͕ઃఆ͞Ε͍ͯΔ
  25. 32.

    > < 32 JJUG CCC 2016 Spring. 2016/05/21 ࣮ྫʢը໘ͷ৔߹ʣʢ1ʣ @Controller

    public class HelloController { @RequestMapping("/admin/hello") public String hello(@RequestParam("name") String name, Model model) { if (name.equals("yoshida")) { throw new AuthorizationException("AuthorizationException error."); } model.addAttribute("name", name); return "screen/admin/hello"; } } @ResponseStatus(HttpStatus.FORBIDDEN) ͷ͍ͭͨ ྫ֎Λ Throw ͢Δ name ͕ແ͍ͱ͖͸ Spring ͔Β MissingServletRequestParameterException ͕ Throw ͞ΕΔ
  26. 35.

    > < 35 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    ྫ֎ @ResponseStatus Λ෇͚ͨඇݕࠪྫ֎Λ Throw ͢Δ͚ͩ ͜ΕͰɺྫ֎͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ
  27. 37.

    > < 37 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢ΔલʹτϥϯβΫγϣϯʹ͍ͭͯߟ͍͑ͨ͜ͱ ʢOR

    Ϛούʔ͸ɺ͓޷Έͷ΋ͷΛ࢖͍·͠ΐ͏ɻ ͪͳΈʹɺฐࣾͰ͸ MyBatis, Doma2 ͕Α͘࢖ΘΕΔʣ • τϥϯβΫγϣϯڥքΛͲ͜ʹ͢Δ͔ʁʢController ૚ or Service ૚ʣ • Controller ૚ʹ͢Δͱɺ
 ్தͰҰ౓ commit ͍ͨ͠৔߹ͳͲྫ֎ରԠ͕ΊΜͲ͍͘͞ • τϥϯβΫγϣϯ͸୹͚Ε͹୹͍΄͏͕Α͍
 • ϏδωεϩδοΫʹτϥϯβΫγϣϯॲཧͷίʔυΛೖΕͨ͘ͳ͍ • connection.commit, connection.rollback ͱ͔ɾɾɾ • ౷ҰతͳτϥϯβΫγϣϯॲཧΛ͍ͨ͠
  28. 38.

    > < 38 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (Tx) Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ @Service ͷϝιουʢ΋͘͠͸Ϋϥεʣʹ @Transactional Λ෇͚Δɻ @Service public class UserService { @Autowired private UserRepository repository; @Transactional public int create(User user) { return repository.create(user); } @Transactional public int update(User user) { return repository.update(user); } public User findById(int id) { return repository.findById(id); } } @Transactional ͷϝιου͕ݺ͹ΕͨΒɺ τϥϯβΫγϣϯ͕։࢝͞ΕΔɻ ϝιουΛൈ͚Ε͹ commit, ඇݕࠪྫ֎͕ൃੜͨ͠৔߹͸ rollback ɻ ࡉ͔͍ઃఆ͸ @Transactional ͷଐੑͰઃఆՄೳ
  29. 39.

    > < 39 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (Tx) Ͱ͸Ͳ͏͢Δ͔ʁʢ2ʣ ͔͠͠ɺຖճ @Transactional Λॻ͍͍ͯ͘ͷ͸ͩΔ͍ɻ ݸผʹ෇͚Δɾ෇͚ͳ͍ͷ൑அΛͨ͘͠ͳ͍ɻ ෇͚Δ΂͖ϝιουʹ෇͍͍ͯͳ͍΄͏͕໰୊ɻ ※ ͜ͷ෦෼͸͋Δఔ౓ׂΓ੾Γ τϥϯβΫγϣϯॲཧͷ։࢝ɾऴྃίετΛे෼ʹ௿͍ͷͰɺ select only Ͱ΋τϥϯβΫγϣϯॲཧΛ։࢝ͯ͠໰୊ͳ͍ͱ͍͏൑அɻ ͢΂ͯͷ Service ϝιουʹ @Transactional Λ͚ͭΔ
  30. 40.

    > < 40 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot (Tx) Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ AOP Λ࢖ͬͯɺ @Service ͷ͢΂ͯͷϝιουʹɺ@Transactional Λ෇༩͢Δɻ @SpringBootApplication @ImportResource("classpath:transaction-context.xml") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ※ Java Config Ͱ͸࣮ݱͰ͖ͳ͍Έ͍ͨɻ http://stackoverflow.com/questions/14068525/javaconfig-replacing- aopadvisor-and-txadvice http://qiita.com/ksby/items/2ea40c5455c31870bd7c
  31. 41.

    > < <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="লུ"> <tx:advice id="txAdvice" transaction-manager="transactionManager">

    <tx:attributes> <tx:method name=“*” isolation=“READ_COMMITTED" /> </tx:attributes> </tx:advice> <aop:config> <aop:advisor pointcut="execution(public * com.example.service.*.*(..)) and @target(org.springframework.stereotype.Service)" advice-ref="txAdvice" /> </aop:config> </beans> transaction-context.xml 41 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring Boot (Tx) Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ com.example.service ഑Լͷ @Service ͕෇͍͍ͯΔ৔ॴ ͢΂ͯͷϝιουʹ෇༩͢Δͷ͕໰୊͕͋Δ৔߹͸ɺ ໋໊ن໿ʢcreate*, update* ʹͷΈ෇༩ʣͰɺ෇༩ର৅ΛܾΊΔͷ΋͋Γɻ
  32. 42.

    > < 42 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    τϥϯβΫγϣϯ Service ૚͕τϥϯβΫγϣϯڥքʢࣗಈʣ ͜ΕͰɺτϥϯβΫγϣϯ͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ
  33. 44.

    > < 44 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢Δલʹόονʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ Web

    ΞϓϦͱ͸͍͑ɺಛఆͷ࣌ؒʹԿ͔Λ͍ͨ͠ͱ͏ཁ݅͸Α͋͘Δɻ • ձһͷ஀ੜ೔ʹ͓஀ੜ೔ϙΠϯτΛਐఄ͢Δ • ೔࣍Ͱɺ౷ܭ৘ใΛϝʔϧͰ୲౰ऀʹૹΓ͍ͨ • ΩϡʔΛॲཧ͢ΔʢCSV ΞοϓϩʔυͰେྔొ࿥ͳͲʣ • ΞΫηεͷগͳ͍ਂ໷ʹΩϟογϡΛΫϦΞ͍ͨ͠
  34. 45.

    > < 45 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢Δલʹόονʹ͍ͭͯߟ͍͑ͨ͜ͱʢ2ʣ δϣϒεέδϡʔϥΛݕ౼͢Δɻ

    • JP1 ౳ͷ঎༻੡඼࢖͏ • ͓ۚͳ͍͠ɾɾɾ • Rundeck ͱ͔ Azkaban ͋ͨΓͷ OSS Λ࢖͏ • ߏங͕ΊΜͲͦ͘͞͏ɾɾɾ • cron • όονͷ؅ཧ͕೉͍͠ • ݁ہ͸ Web ΞϓϦͷΤϯυϙΠϯτʹΞΫηε͢Δ͚ͩͰ͠ΐʁ • AWS ͷ Lambda Scheduled Event Ͱࠓ෩ͷδϣϒ؅ཧͩͥʔ • ݁ہ͸ Web ΞϓϦͷʢུ ΋ͬͱ؆୯ʹόονΛॻ͖͍ͨ
  35. 46.

    > < 46 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ Spring ͳΒ TaskScheduler ͕࢖͑Δɻ @SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } @Slf4j @Component public class SampleTask { @Scheduled(cron = "*/1 * * * * *") public void echo() { log.info("Do batch.. {}", new Date()); } } @Scheduled Ͱࢦఆ࣌ࠁʹॲཧΛ࣮ߦͰ͖Δɻ ࢦఆ࣌ࠁͷଞʹ΋׬ྃ࣌఺͔Βࢦఆ࣌ࠁޙʹىಈͱ͍ͬͨॻ͖ํ΋Ͱ͖Δɻ
  36. 47.

    > < 47 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ2ʣ 2016-04-24 15:18:20 INFO [pool-1-thread-1] SampleTask - Do batch.. Sun Apr 24 15:18:20 JST 2016 2016-04-24 15:18:21 INFO [pool-1-thread-1] SampleTask - Do batch.. Sun Apr 24 15:18:21 JST 2016 ؆୯ʂʂ ͱ͸ݴ͑ɺ࣮ۀ຿Ͱ࢖͏ͨΊʹɺ΋͏ͪΐͬͱ޻෉͠·͠ΐ͏ɻ • ෳ਺εϨουͰಈ͘Α͏ʹ͢Δ • ಛఆͷαʔόͷΈͰಈ͘Α͏ʹ͢Δ • όονͷ։࢝ɾऴྃ࣌ʹϩάΛग़͢ʢ࣮ߦ࣌ؒͱ͔ʣ • αʔόఀࢭ࣌ʹ଴ͭ
  37. 48.

    > < 48 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ @SpringBootApplication @EnableScheduling public class Application implements SchedulingConfigurer { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean(destroyMethod = "shutdown") public Executor taskScheduler() { ThreadPoolTaskScheduler threadPool = new ThreadPoolTaskScheduler(); threadPool.setPoolSize(5); // shutdown ࣌ʹ Task ͷ׬ྃΛ଴ͭʢ࠷େ10෼ؒʣ threadPool.setWaitForTasksToCompleteOnShutdown(true); threadPool.setAwaitTerminationSeconds(60 * 10); return threadPool; } } configureTasks ͷதͰɺExecutorService Λ࣮૷ͨ͠ΫϥεΛηοτ͢Δ Thread ͷ਺Λ૿΍͢ αʔόఀࢭ࣌ʹ଴ͭΑ͏ʹ͢Δ Scheduling ͷΧελϚΠζ͸ɺ SchedulingConfigurer ΠϯλϑΣʔεΛ࣮૷͢Δ͜ͱͰ࣮ݱՄೳɻ
  38. 49.

    > < 49 JJUG CCC 2016 Spring. 2016/05/21 @Slf4j @Aspect

    @Component public class TaskInterceptor { @Value(“${batch.exec.host}”) String batchExecHost; @Around("execution(* com.example.task..*.*(..)) && @annotation(org.springframework.scheduling.annotation.Scheduled)") public Object around(ProceedingJoinPoint pjp) throws Throwable { String methodName = pjp.getSignature().getName(); String currentThread = Thread.currentThread().getName(); // ࣮ߦνΣοΫ if (!allowedBatchExec()) { log.info("Skip batch ({}): {}", currentThread, methodName); return null; } log.info("Begin batch ({}): {}", currentThread, methodName); Stopwatch stopWatch = Stopwatch.createStarted(); try { return pjp.proceed(); } catch (Exception e) { log.error("batch error: {}", methodName, e); return null; } finally { log.info("End batch ({}): {}, elapsed = {} (ms)", currentThread, methodName, stopWatch.elapsed(TimeUnit.MILLISECONDS)); } } private boolean allowedBatchExec() { if (getHostName().equals(batchExecHost)) { return true; } return false; } } AOP Ͱόονͷ࣮ߦ੍ޚΛ࣮ݱ͢Δ ಛఆͷϗετͰ͔͠ಈ͔ͳ͍Α͏ʹ͢Δ ։࢝ɾऴྃɾܭଌϩάΛग़͢
  39. 50.

    > < 50 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    όον όονॲཧ͕େྔʹ͋Δɺ όονॲཧ͕Ϗδωε্ɺ݁ߏॏཁɺ౳ͷཁ͕݅͋Δ৔߹͸ɺ Spring ͳΒ Spring Batch ΍ Quartz Λݕ౼͢Δͷ΋͋Γɻ ಛఆʹύοέʔδ഑Լʹ @Scheduled Λ͚ͭͨϝιουΛ࣮૷͢Δ ͜ΕͰɺόονॲཧ͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ
  40. 52.

    > < 52 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢ΔલʹϓϩύςΟʹ͍ͭͯߟ͍͑ͨ͜ͱ •

    ຊ൪؀ڥ΍։ൃ؀ڥͳͲͰઃఆϑΝΠϧΛ෼͚͍ͨ • DB ͷ઀ଓઌΛม͍͑ͨ • ։ൃ࣌͸ messageSource ͷ cache ͸ແ͠ʹ͍ͨ͠౳ͳͲ • ֎෦ʢOS؀ڥม਺౳ʣ͔ΒઃఆΛ্ॻ͖Ͱ͖ΔΑ͏ʹ͍ͨ͠ • application.properties ͸όʔδϣϯ؅ཧର৅ʹ͍ͯ͠Δ͕ɺ
 DB ͷύεϫʔυ౳ͷػີ৘ใ͸ଞͷਓ͔ΒݟΒΕͳ͍Α͏ʹ͍ͨ͠ɻ • Twelve-Factor App ͷཁૉͱͯ͠΋ॏཁ
  41. 53.

    > < 53 JJUG CCC 2016 Spring. 2016/05/21 ຊ൪؀ڥ΍։ൃ؀ڥͳͲͰઃఆϑΝΠϧΛ෼͚͍ͨ Spring

    Boot Ͱ͸ɺProfile ͕࢖͑Δɻ mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=development" # application.properties, application-development.properties ͕ಡΈࠐ·ΕΔ mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=test" # application.properties, application-test.properties ͕ಡΈࠐ·ΕΔ jar ͷ৔߹͸ɺ java -jar -Dspring.profiles.active=production hoge.jar
  42. 54.

    > < 54 JJUG CCC 2016 Spring. 2016/05/21 ֎෦ʢOS؀ڥม਺౳ʣ͔ΒઃఆΛ্ॻ͖Ͱ͖ΔΑ͏ʹ͍ͨ͠ʢ1ʣ Spring

    Boot Ͱ͸ɺϓϩύςΟ͸ҎԼͷॱংͰಡΈࠐ·ΕΔʢ্ͷํ͕༏ઌʣ 1. Command line arguments. 2. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property) 3. ServletConfig init parameters. 4. ServletContext init parameters. 5. JNDI attributes from java:comp/env. 6. Java System properties (System.getProperties()). 7. OS environment variables. 8. A RandomValuePropertySource that only has properties in random.*. 9. Profile-specific application properties outside of your packaged jar (application- {profile}.properties and YAML variants) 10.Profile-specific application properties packaged inside your jar (application- {profile}.properties and YAML variants) 11.Application properties outside of your packaged jar (application.properties and YAML variants). 12.Application properties packaged inside your jar (application.properties and YAML variants). 13.@PropertySource annotations on your @Configuration classes. 14.Default properties (specified using SpringApplication.setDefaultProperties).
  43. 55.

    > < 55 JJUG CCC 2016 Spring. 2016/05/21 ֎෦ʢOS؀ڥม਺౳ʣ͔ΒઃఆΛ্ॻ͖Ͱ͖ΔΑ͏ʹ͍ͨ͠ʢ2ʣ application-production.properties

    spring.datasource.password="dummy" SPRING_DATASOURCE_PASSWORD="hogehoge" OS ؀ڥม਺ Spring Boot Ͱ͸ɺRelaxed binding ͷػೳ͕͋ΔͷͰɺ্هͷม਺͸ಉ͡ɻ Property Note person.firstName Standard camel case syntax. person.first-name Dashed notation, recommended for use in .properties and .yml files. PERSON_FIRST_NAME Upper case format. Recommended when using a system environment variables. http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot- features-external-config-relaxed-binding
  44. 56.

    > < 56 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    ϓϩύςΟ ֤؀ڥผͷϓϩύςΟ͸ɺ֤؀ڥ༻ͷϑΝΠϧʹهड़͢Δ ͜ΕͰɺϓϩύςΟʹؔͯ͠͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ ػີ৘ใ͸ OS ؀ڥม਺Ͱ্ॻ͖
  45. 58.

    > < 58 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢ΔલʹϩΪϯάʹ͍ͭͯߟ͍͑ͨ͜ͱ •

    log4j ͸͍͍Ճݮʹ΍Ί͍ͨ • ग़ྗจࣈྻͷߏஙͱ͔ΊΜͲ͍͘͞ • isDebugEnabled ΋ΊΜͲ͍͘͞ • log4j ͸طʹ EOL • ϩάΠϯ͍ͯ͠Δ userIdɺrequestId ౳͸ࣗಈͰ෇͘Α͏ʹ͍ͨ͠ • ͜ΕΒΛϩάʹग़͓ͯ͘͠ͱɺো֐࣌ͷݪҼڀ໌ʹศརɻ
 ಛʹ requestId ʹؔͯ͠͸ microservices తʹ։ൃ͍ͯ͠Δ৔߹ɺ
 αʔϏεؒͷϩάͷඥ෇͚ͱͯ͠ಛʹॏཁɻ • ͨͩɺࣗ෼Ͱຖճॻ͘ͷ͸ͩΔ͍ɻ
  46. 59.

    > < 59 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ log4j ͸͍͍Ճݮʹ΍Ί͍ͨ Spring Boot ͳΒ SLF4J + logback ͕σϑΥϧτ౥ࡌɻ application.properties(.yml) Ͱ΋ઃఆมߋ͕Մೳ͕ͩɺ಺༰͸ݶΒΕΔɻ logback-spring.xmlʢlogback.xml Ͱ͸ͳ͘ʣΛ༻ҙ͠·͠ΐ͏ɻ logback-spring.xml ͱ͍͏ϑΝΠϧΛ༻ҙ͓ͯ͘͠ͱɺ Logback extensionsʢಠࣗλάʣ͕࢖͑ΔͷͰศརɻ <springProfile name="!production"> <!-- configuration to be enabled when the "production" profile is not active --> </springProfile> <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host" defaultValue="localhost"/> <appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender"> <remoteHost>${fluentHost}</remoteHost> ... </appender>
  47. 60.

    > < 60 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ2ʣ ϩάΠϯ͍ͯ͠Δ userIdɺrequestId ౳͸ࣗಈͰ෇͘Α͏ʹ͍ͨ͠ MDC = Mapped Diagnostic ContextʢϚοϓԽ͞Εͨ਍அίϯςΩετʣ Thread Local ͳ Map Λϩάͷ௥Ճ৘ใͱͯ͠ར༻Ͱ͖Δײ͡ɻ Map ʹઃఆ͞Εͨ΋ͷ͸ɺࣗಈͰΫϦΞ͞Εͳ͍ͷͰɺ ͪΌΜͱࣗ෼ͰΫϦΞ͢Δඞཁ͕͋Δɻ Web ΞϓϦέʔγϣϯͷ৔߹͸ɺServlet Filter Ͱ࣮૷͞ΕΔ͜ͱ͕ଟ͍ɻ ͜͏͍͏࣌͸ MDC
  48. 61.

    > < 61 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ public class MDCLoggingFilter implements Filter { private static final String KEY_REQUEST_ID = "REQUEST_ID"; private static final String KEY_LOGIN_USER_ID = "LOGIN_USER_ID"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { putMDC(request); try { chain.doFilter(request, response); } finally { clearMDC(); } } private void putMDC(ServletRequest request) { if (request instanceof HttpServletRequest) { HttpServletRequest httpRequest = (HttpServletRequest) request; String requestId = httpRequest.getHeader("X-Request-Id"); if (requestId != null) { MDC.put(KEY_REQUEST_ID, requestId); } String loginUserId = "t-yoshida"; // session ౳͔ΒϢʔβ৘ใΛऔಘ if (loginUserId != null) { MDC.put(KEY_LOGIN_USER_ID, loginUserId); } } } private void clearMDC() { MDC.remove(KEY_REQUEST_ID); MDC.remove(KEY_LOGIN_USER_ID); } // লུ } MDC ʹ put ͢Δ MDC ͔Β remove ͢Δ
  49. 62.

    > < 62 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{ISO8601} %-5p [%t] %c{2} \(%L\) - [%X{REQUEST_ID:-undefined}][%X{LOGIN_USER_ID:- undefined}] %m%n</pattern> </encoder> </appender> 2016-05-02 21:45:12,490 INFO [http-nio-8080-exec-4] c.e.c.s.a.LogController (14) - [ab939dfca5d57843ea4c695cab6f721d][t-yoshida] Log1 2016-05-02 21:45:12,491 INFO [http-nio-8080-exec-4] c.e.c.s.a.LogController (15) - [ab939dfca5d57843ea4c695cab6f721d][t-yoshida] Log2 @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Bean public FilterRegistrationBean mdcLoggingFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new MDCLoggingFilter()); bean.setOrder(1); return bean; } } Filter Λొ࿥͢Δ MDC ͷ஋Λදࣔ͢Δ
  50. 63.

    > < 63 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    ϩΪϯά SLF4J + logback ͕࢖͑ͯɺuserId ౳͸ࣗ෼Ͱॻ͔ͳͯ͘Α͍ ͜ΕͰɺϩΪϯάʹؔͯ͠͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ
  51. 65.

    > < 65 JJUG CCC 2016 Spring. 2016/05/21 ػೳ։ൃΛ͢ΔલʹηΩϡϦςΟʹ͍ͭͯߟ͍͑ͨ͜ͱ •

    XSS • ςϯϓϨʔτΤϯδϯͰࣗಈͰΤεέʔϓ͞Ε͍ͯΔ͔ʁ • SQL Injection • OR ϚούʔͰద੾ʹ Injection ରࡦ͕ͳ͞Ε͍ͯΔ͔ʁ • LIKE ԋࢉࢠ΍ ORDER BY ۟΁ͷόΠϯυม਺ͷڍಈ • CSRF • ࣗ෼Ͱ࡞Γࠐ·ͣɺ؆୯ʹରࡦ͕Ͱ͖Δ͔ʁ • Http Security HeadersʢList of useful HTTP headers – OWASPʣ • ؆୯ʹઃఆͰ͖ΔͷͰɺ΍͓͖͍ͬͯͨɻ • ϥΠϒϥϦʢjarʣͷΞοϓσʔτ • pom.xml ͷ jar ͕શવߋ৽͞Εͳ͍ͱ͔ɾɾɾ ʢ˞ ೝূɾೝՄʹ͍ͭͯ͸આ໌͠·ͤΜʣ
  52. 66.

    > < 66 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ XSS Spring Boot ͳΒ Thymeleaf ͕Ұ൪͓͢͢Ίɻ Thymeleaf ʹΑΔςΩετͷग़ྗ͸σϑΥϧτͰΤεέʔϓ͞ΕΔɻ <!-- Τεέʔϓ͞ΕΔ --> <span th:text=“${message}">escapedString</span> <!-- Τεέʔϓ͞Εͳ͍ --> <span th:utext="${message}">unescapedString</span> ͪΌΜͱ҆શଆ͕σϑΥϧτʹͳ͍ͬͯΔɻ
  53. 67.

    > < 67 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ2ʣ SQL Injection ͪΌΜͱͨ͠ OR ϚούʔΛબͼ·͠ΐ͏ɻ ʢPrepared Statement ͰϓϨʔεϗϧμΛͪΌΜͱ࢖͏ʣ ͱ͸ݴ͑ɺLIKE ԋࢉࢠ΍ ORDER BY ۟౳ͷΤεέʔϓ͸ɺ ։ൃऀʹ೚͞Ε͍ͯΔ৔߹͕͋ΔͷͰɺ ೖྗจࣈྻΛ͖ͪΜͱόϦσʔγϣϯ͢Δɻ • ϗϫΠτϦετͰݕূ͢Δ • ϗϫΠτϦετ͕࢖͑ͳ͍৔߹͸ɺϦςϥϧΛਖ਼͘͠Τεέʔϓ͢Δ
  54. 68.

    > < 68 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ CSRF Spring Security Λ࢖͑͹ɺϑΥʔϜ΁ͷτʔΫϯຒΊࠐΈ͔Βɺ αʔόʔαΠυͰͷνΣοΫ·ͰΛࣗಈͰ΍ͬͯ͘ΕΔɻ ͨͩ͠ɺSpring Security ͸݁ߏ͓͔͍ͤͬͳ΋ͷ΋༗ޮʹͳͬͯ͠·͏ͷͰɺ ͦ͜Β΁Μ͸ͪΌΜͱແޮԽ͠ͳ͍ͱ͍͚ͳ͍ɻBasic ೝূͱ͔ɻ <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> security.basic.enabled=false
  55. 69.

    > < 69 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ ࡉ͔͍ઃఆ͸ɺapplication.properties ͔ɺ WebSecurityConfigurerAdapter Λܧঝͨ͠ΫϥεͰઃఆՄೳɻ @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // CSRF อޢΛແޮԽ͢Δ URL String[] ignoreCsrfPatterns = Stream.of(Site.values()) .filter(l -> !l.isProtectCsrf()).map(l -> l.getBaseUrl() + "/**").toArray(String[]::new); http.csrf() .ignoringAntMatchers(ignoreCsrfPatterns).and() // CSRF อޢΛແޮԽ͢Δ URL Λࢦఆ͢Δ .exceptionHandling().accessDeniedHandler(accessDeniedHandler); // CSRF ʹҾ͔͔ͬͬͬͨ৔߹ͷྫ֎ϋϯυϦϯά } @Value("${server.error.path:${error.path:/error}}") private String errorPath; private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandler() { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { if (!response.isCommitted()) { request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, accessDeniedException); response.setStatus(HttpStatus.FORBIDDEN.value()); request.getRequestDispatcher(errorPath).forward(request, response); } } }; } API ͸ CSRF อޢΛແޮԽ͢Δ CSRF ʹҾ͔ͬͬͨ৔߹ɺGlobalErrorController ʹ forward ͢ΔΑ͏ʹઃఆɻ
  56. 70.

    > < 70 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ5ʣ ࣗಈͰઃఆ͞ΕΔ※ ʢth:action Λ࢖͍ͬͯΔ৔߹ʣ
  57. 71.

    > < 71 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ6ʣ Status Code ͸ 403
  58. 72.

    > < 72 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ7ʣ Http Security HeadersʢList of useful HTTP headers – OWASPʣ Spring Security Λ༗ޮʹ͢Ε͹ɺSecurity Header ͸ࣗಈͰ෇༩͞ΕΔɻ ࡉ͔͍ઃఆ͸ɺapplication.properties ͔ɺWebSecurityConfigurerAdapter Λ ܧঝͨ͠ΫϥεͰઃఆՄೳɻ spring.mvc.static-path-pattern=/public/** security.ignored=/public/** security.headers.cache=true # Enable cache control HTTP headers. security.headers.content-type=true # Enable "X-Content-Type-Options" header. security.headers.frame=true # Enable "X-Frame-Options" header. security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all). security.headers.xss=true # Enable cross site scripting (XSS) protection. security.ignored= # Comma-separated list of paths to exclude from the default secured paths. σϑΥϧτ஋ Static Resource ͸আ֎ https://www.owasp.org/index.php/List_of_useful_HTTP_headers
  59. 73.

    > < 73 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ8ʣ Security Header ͕ ग़ྗ͞Ε͍ͯΔ
  60. 74.

    > < 74 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ9ʣ ϥΠϒϥϦʢjarʣͷΞοϓσʔτ Spring Boot ͷ৔߹ɺspring-boot-starter-parent ͷ਌ POM ͕ɺ ੔߹ੑͷऔΕͨˍΘΓͱ࠷৽ͷ jar Λ࢖ͬͯ͘ΕΔͷͰɺ جຊతʹ͸ Boot ͷόʔδϣϯΛ্͛Δ͚ͩʢࣗ෼Ͱ <version> Λࢦఆ͠ͳ͍ʣ ͨͩ͠ɺݸผͷ jar Ͱ Security Fix ͳͲ͕ग़ͯɺ Boot ͷϦϦʔε͕ؒʹ߹͍ͬͯͳ͍৔߹͸ɺݸผʹόʔδϣϯΛࢦఆ͢Δɻ <properties> <jedis.version>2.8.1</jedis.version> </properties> ਌ POM Ͱ property ͕࢖ΘΕ͍ͯΔͷͰɺ ͦΕΛ্ॻ͖͢Δ͚ͩͰΑ͍ɻ https://github.com/spring-projects/spring-boot/blob/master/spring-boot- dependencies/pom.xml
  61. 75.

    > < 75 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ10ʣ ࣗ෼ͰೖΕͨ jar ͷ৔߹͸ɺVersions Maven Plugin Λ࢖͏ͷ͕ศརɻ http://www.mojohaus.org/versions-maven-plugin/ <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-maven-plugin</artifactId> <version>2.1</version> </plugin> </plugins> </build> όʔδϣϯΞοϓ͕Մೳͳ dependency, plugin ͷදࣔ΍ߋ৽ʢةݥʂʣ Λߦ͏͜ͱ͕Ͱ͖Δɻ ଞʹ΋ project ͷ <version> λάͷߋ৽ͳͲ΋Ͱ͖Δɻ
  62. 76.

    > < 76 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring

    Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ11ʣ [SpringDemo] mvn versions:display-dependency-updates [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building SpringDemo 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- versions-maven-plugin:2.1:display-dependency-updates (default-cli) @ SpringDemo --- [INFO] The following dependencies in Dependency Management have newer versions: [INFO] antlr:antlr ........................................ 2.7.7 -> 20030911 [INFO] ch.qos.logback:logback-access ......................... 1.1.5 -> 1.1.7 [INFO] ch.qos.logback:logback-classic ........................ 1.1.5 -> 1.1.7 [INFO] com.atomikos:transactions-jdbc ........................ 3.9.3 -> 4.0.2 [INFO] com.atomikos:transactions-jms ......................... 3.9.3 -> 4.0.2 [INFO] com.atomikos:transactions-jta ......................... 3.9.3 -> 4.0.2 ... [INFO] [INFO] The following dependencies in Dependencies have newer versions: [INFO] org.mybatis.spring.boot:mybatis-spring-boot-starter ... 1.0.2 -> 1.1.1 [INFO] org.projectlombok:lombok ............................ 1.16.6 -> 1.16.8 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.462 s [INFO] Finished at: 2016-05-04T11:37:18+09:00 [INFO] Final Memory: 9M/205M [INFO] ------------------------------------------------------------------------ ਌ POM Ͱࢦఆ͞ΕͯΔ jar ͷόʔδϣϯ৘ใ όʔδϣϯΞοϓ͕Մೳͳ dependency Λදࣔ͢Δ mvn ίϚϯυ ࣗ෼ͰೖΕͨ jar ͷόʔδϣϯ৘ใ ߋ৽͠·͠ΐ͏
  63. 77.

    > < 77 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ ɿ

    ηΩϡϦςΟ XSS ͸ΞϯΤεέʔϓͯ͠ग़ྗ͍͚ͨ࣌ͩ͠஫ҙ͢Δ ͜ΕͰɺηΩϡϦςΟʹؔͯ͠͸ ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ SQL Injection ͸όΠϯυม਺Λ࢖Θͳ͍͚࣌ͩ஫ҙ͢Δ CSRF ͸ࣗಈͰରࡦ͞ΕΔΑ͏ʹͳͬͨʢth:action ๨Εͣʹʣ Boot ͷ version Λҙࣝͭͭ͠ɺఆظతʹόʔδϣϯΞοϓΛ֬ೝ Http Security Headers ͸ࣗಈͰग़ྗ
  64. 79.

    > < 79 JJUG CCC 2016 Spring. 2016/05/21 DevTools ։ൃ࣌ʹେମઃఆ͢ΔͰ͋Ζ͏ɺ

    ςϯϓϨʔτΩϟογϡͷແޮԽɺϗοτϦϩʔυͷઃఆ౳͕ҰൃͰՄೳɻ ʢSpring Loaded ͱ͸ผ෺ʣ <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ #using-boot-devtools ͜ͷઃఆ͚ͩͰ spring.thymeleaf.cache=false ͱ͔ɺ spring.freemarker.cache=false ౳Λɺݸผʹॻ͔ͳͯ͘΋Α͘ͳΔɻ ΋ͪΖΜຊ൪؀ڥͰ༗ޮʹͳΒͳ͍Α͏ʹߟྀ͞Ε͍ͯΔɻ
  65. 80.

    > < 80 JJUG CCC 2016 Spring. 2016/05/21 lombok Spring

    ؔ܎ͳ͍͚Ͳɺ͍͢͝ศརͳͷͰɺੋඇಋೖ͠·͠ΐ͏ɻ ͨͩ͠ɺexperimental ͳػೳʹ͍ͭͯ͸ɺ͝ར༻͸ܭըతʹɻ <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> <scope>provided</scope> </dependency> </dependencies>
  66. 81.

    > < 81 JJUG CCC 2016 Spring. 2016/05/21 ΞϓϦέʔγϣϯͷݟ͑ΔԽ Spring

    ΞϓϦέʔγϣϯͰɺ৭ʑͳ΋ͷΛݟ͑ΔԽ͓ͯ͘͠ͱɺ ΞϓϦέʔγϣϯͷཧղ͕ਂ·ͬͨΓɺࡉ͔ͳϛεΛؾ͚ͮΔɻ Spring ࣗମͷཧղ΋ḿΔɻ • Routing • Context • Batch • Build Info ʢͦΕɺactuator ͰͰ͖ΔΑʣ
  67. 85.

    > < 85 JJUG CCC 2016 Spring. 2016/05/21 ΞϓϦέʔγϣϯͷݟ͑ΔԽʢBuild Infoʣ

    https://github.com/sinsengumi/spring-boot-application-infrastructure/blob/ master/src/main/java/com/example/controller/screen/admin/system/ BuildController.java
  68. 87.

    > < 87 JJUG CCC 2016 Spring. 2016/05/21 ·ͱΊ •

    ػೳΛ࡞ΓࠐΉલʹɺج൫ઃܭΛͪΌΜͱ͓ͯ͜͠͏ • ૊Έ߹Θ͕ͤେมͱ͔ݴ͚ͬͨͲɺSpring Boot ͸ૉ੖Β͍͠ϓϩμΫτ
 ࠓɺJava ͰΞϓϦ࡞ΔͳΒɺީิͱͯ͠͸࠷༗ྗͳ͸ͣ • ࠓ೔࿩ͤͳ͔ͬͨ͜ͱʢೝূɾೝՄɺΩϟογϡɺςετʣ • ࠓ೔ͷαϯϓϧίʔυ͸
 https://github.com/sinsengumi/spring-boot-application-infrastructure