Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

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

sinsengumi

May 21, 2016
Tweet

More Decks by sinsengumi

Other Decks in Programming

Transcript

  1. >
    <
    JJUG CCC 2016 Spring. 2016/05/21
    4QSJOH#PPUͰ#PPUͨ͠ޙʹ࡞Δ
    8FCΞϓϦέʔγϣϯج൫
    ٢ా ๎໵ʢΤϜεϦʔגࣜձࣾʣ
    1

    View full-size slide

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

    View full-size slide

  3. >
    < 3
    JJUG CCC 2016 Spring. 2016/05/21
    ձࣾ঺հʢΤϜεϦʔגࣜձࣾʣ
    • ೔ຊͷҩࢣ 8 ׂɺੈքͰ 350 ສਓͷҩࢣ޲͚αʔϏεΛӡӦ͢Δ

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

    View full-size slide

  4. >
    < 4
    JJUG CCC 2016 Spring. 2016/05/21
    ໨࣍
    1. Spring Boot ʹ͍ͭͯ

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

    3. ·ͱΊ

    View full-size slide

  5. >
    <
    00
    About Spring Boot
    4QSJOH#PPU
    ʹ͍ͭͯ
    5

    View full-size slide

  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 ͕͋Δࠓɾɾɾ

    View full-size slide

  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 ϝιουΛୟ͘ʣ

    View full-size slide

  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)
    ͓͓ʔײಈ

    View full-size slide

  9. >
    < 9
    JJUG CCC 2016 Spring. 2016/05/21
    Boot ͸ૣ͍͕ɾɾɾʢ1ʣ
    ʮΑʔ͠ɺ͡Ό͋ૣ଎࡞Γ࢝ΊͪΌ͏ͧʔʯ
    ਺෼ޙɾɾɾɾ
    ʮ͑ʔͱɺྫ֎ॲཧ͸Ͳ͏͢Δͷ͕͍͍Μͩʁʯ
    ʮτϥϯβΫγϣϯ͔͚͍ͨΜ͚ͩͲɾɾɾʯ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  13. >
    < 13
    JJUG CCC 2016 Spring. 2016/05/21
    Boot ͸ૣ͍͕ɾɾɾʢ5ʣ
    େํ਑
    • Spring ͷํ਑ʹै͏ʢRail ʹ৐Δతͳʣ

    @Controller, @Service, @Repository Λ࢖ͬͨجຊతͳϨΠϠʔߏ੒
    • ίʔυΛͳΔ΂͘ॻ͔ͳ͍

    ॻ͔ͳ͍ͨΊʹϑϨʔϜϫʔΫΛ࢖͍ͬͯΔ
    • ۀ຿ػೳΛ࡞Δ࣌ʹɺ͸·Βͳ͍ɺ೰·ͳ͍Α͏ͳઃܭ

    View full-size slide

  14. >
    <
    01
    URL Layout
    63-ઃܭ
    14

    View full-size slide

  15. >
    < 15
    JJUG CCC 2016 Spring. 2016/05/21
    • Ͳ͏͍͏ URL ମܥ͕͋Δ͔ʁ

    ݴ͍׵͑ΔͱɺʮαʔϏε෼ׂʯΛݕ౼͢Δͱ͍͏͜ͱ

    • ओʹɺϢʔβը໘ɺ؅ཧը໘ɺAPIʢ֎޲͖ɺ಺޲͖ʣ౳Λ

    ಉҰΞϓϦ্ʹࡌͤΔ͔ʁɺผΞϓϦʹ͢Δ͔ʁͱ͍͏࿩ɻ

    microservices తʹ͸෼ׂͨ͠΄͏͕ྑ͍͕ɺ

    Πϯϑϥίετͷ૿େ΍ɺΞϓϦɾϏδωεͷن໛ʹ΋ΑΔ͸ͣɻ
    ͍͖ͳΓ Spring ͱ͸ؔ܎ͳ͍࿩Ͱ͕͢ɺ
    Web ΞϓϦΛ࡞Δ্Ͱ؊৺ͳͱ͜ΖͳͷͰ·ͣ͸͡Ίʹݕ౼͠·͢ɻ
    ػೳ։ൃΛ͢Δલʹ URL ઃܭʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ

    View full-size slide

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

    View full-size slide

  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 ͔ΒͲ͜ʹΞΫηε͍ͯ͠Δ͔
    Λ൑ఆ͢ΔϝιουΛ༻ҙ͓ͯ͘͠

    View full-size slide

  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

    View full-size slide

  19. >
    <
    02
    Exception
    ྫ֎
    19

    View full-size slide

  20. >
    < 20
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢Δલʹྫ֎ʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ
    • ྫ֎͕ى͖ͨ࣌ʹԿΛ͢Δ͔ʁʢϩΪϯάɺ௨஌ etcʣ
    • ྫ֎͕ى͖ͨ࣌ʹͲ͜΁ߦ͔͘ʁʢը໘ͷ৔߹ɺAPI ͷ৔߹ʣ
    • εςʔλείʔυ΋ͪΌΜͱઃఆ͍ͨ͠
    • ݕࠪྫ֎ɺඇݕࠪྫ֎ͷ࢖༻ํ਑
    • ͢΂ͯͷྫ֎Λิ଍͍ͨ͠ʢTomcat ͷΤϥʔը໘ग़Δͱ͔μα͍ʣ
    • ࢖͍ͬͯΔϑϨʔϜϫʔΫͰ͸ɺͲ͏ॲཧ͢΂͖͔ఆ͍ٛͯ͠Δ͔ʁ 

    ʢSpring తʹ͸ʁʣ

    View full-size slide

  21. >
    < 21
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢Δલʹྫ֎ʹ͍ͭͯߟ͍͑ͨ͜ͱʢ2ʣ
    ౷Ұͨ͠ྫ֎ॲཧΛ͍ͨ͠
    FW ૚ʹඇݕࠪྫ֎Λ Throw ͢Δ͚ͩ

    View full-size slide

  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
    ΍Γํ͕ͨ͘͞Μ͋Γ·͢ɻ

    View full-size slide

  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";
    }
    }

    View full-size slide

  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ʣͰى͖ͨྫ֎ Λॲཧ͢Δ

    View full-size slide

  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 Λฦ͢ɻ

    View full-size slide

  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
    ४උͱͯ͠ɺɺ

    View full-size slide

  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 ͢Δ

    View full-size slide

  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 ͳͷͰɺΤϥʔϨεϙϯεΛฦ͢
    ը໘ͳͷͰɺΤϥʔը໘Λฦ͢

    View full-size slide

  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 ͢Δ

    View full-size slide

  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 ͞ΕΔ

    View full-size slide

  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 ͕ઃఆ͞Ε͍ͯΔ

    View full-size slide

  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 ͞ΕΔ

    View full-size slide

  33. >
    < 33
    JJUG CCC 2016 Spring. 2016/05/21
    ࣮ྫʢը໘ͷ৔߹ʣʢ2ʣ
    400 ͕ઃఆ͞Ε͍ͯΔ

    View full-size slide

  34. >
    < 34
    JJUG CCC 2016 Spring. 2016/05/21
    ࣮ྫʢը໘ͷ৔߹ʣʢ3ʣ
    403 ͕ઃఆ͞Ε͍ͯΔ

    View full-size slide

  35. >
    < 35
    JJUG CCC 2016 Spring. 2016/05/21
    ·ͱΊ ɿ ྫ֎
    @ResponseStatus Λ෇͚ͨඇݕࠪྫ֎Λ Throw ͢Δ͚ͩ
    ͜ΕͰɺྫ֎͸
    ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ

    View full-size slide

  36. >
    <
    03
    Transaction
    τϥϯβΫγϣϯ
    36

    View full-size slide

  37. >
    < 37
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢ΔલʹτϥϯβΫγϣϯʹ͍ͭͯߟ͍͑ͨ͜ͱ
    ʢOR Ϛούʔ͸ɺ͓޷Έͷ΋ͷΛ࢖͍·͠ΐ͏ɻ
    ͪͳΈʹɺฐࣾͰ͸ MyBatis, Doma2 ͕Α͘࢖ΘΕΔʣ
    • τϥϯβΫγϣϯڥքΛͲ͜ʹ͢Δ͔ʁʢController ૚ or Service ૚ʣ
    • Controller ૚ʹ͢Δͱɺ

    ్தͰҰ౓ commit ͍ͨ͠৔߹ͳͲྫ֎ରԠ͕ΊΜͲ͍͘͞
    • τϥϯβΫγϣϯ͸୹͚Ε͹୹͍΄͏͕Α͍

    • ϏδωεϩδοΫʹτϥϯβΫγϣϯॲཧͷίʔυΛೖΕͨ͘ͳ͍
    • connection.commit, connection.rollback ͱ͔ɾɾɾ
    • ౷ҰతͳτϥϯβΫγϣϯॲཧΛ͍ͨ͠

    View full-size slide

  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 ͷଐੑͰઃఆՄೳ

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  41. >
    <











    transaction-context.xml
    41
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot (Tx) Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ
    com.example.service ഑Լͷ @Service ͕෇͍͍ͯΔ৔ॴ
    ͢΂ͯͷϝιουʹ෇༩͢Δͷ͕໰୊͕͋Δ৔߹͸ɺ
    ໋໊ن໿ʢcreate*, update* ʹͷΈ෇༩ʣͰɺ෇༩ର৅ΛܾΊΔͷ΋͋Γɻ

    View full-size slide

  42. >
    < 42
    JJUG CCC 2016 Spring. 2016/05/21
    ·ͱΊ ɿ τϥϯβΫγϣϯ
    Service ૚͕τϥϯβΫγϣϯڥքʢࣗಈʣ
    ͜ΕͰɺτϥϯβΫγϣϯ͸
    ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ

    View full-size slide

  43. >
    <
    04
    Batch
    όον
    43

    View full-size slide

  44. >
    < 44
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢Δલʹόονʹ͍ͭͯߟ͍͑ͨ͜ͱʢ1ʣ
    Web ΞϓϦͱ͸͍͑ɺಛఆͷ࣌ؒʹԿ͔Λ͍ͨ͠ͱ͏ཁ݅͸Α͋͘Δɻ
    • ձһͷ஀ੜ೔ʹ͓஀ੜ೔ϙΠϯτΛਐఄ͢Δ
    • ೔࣍Ͱɺ౷ܭ৘ใΛϝʔϧͰ୲౰ऀʹૹΓ͍ͨ
    • ΩϡʔΛॲཧ͢ΔʢCSV ΞοϓϩʔυͰେྔొ࿥ͳͲʣ
    • ΞΫηεͷগͳ͍ਂ໷ʹΩϟογϡΛΫϦΞ͍ͨ͠

    View full-size slide

  45. >
    < 45
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢Δલʹόονʹ͍ͭͯߟ͍͑ͨ͜ͱʢ2ʣ
    δϣϒεέδϡʔϥΛݕ౼͢Δɻ
    • JP1 ౳ͷ঎༻੡඼࢖͏
    • ͓ۚͳ͍͠ɾɾɾ
    • Rundeck ͱ͔ Azkaban ͋ͨΓͷ OSS Λ࢖͏
    • ߏங͕ΊΜͲͦ͘͞͏ɾɾɾ
    • cron
    • όονͷ؅ཧ͕೉͍͠
    • ݁ہ͸ Web ΞϓϦͷΤϯυϙΠϯτʹΞΫηε͢Δ͚ͩͰ͠ΐʁ
    • AWS ͷ Lambda Scheduled Event Ͱࠓ෩ͷδϣϒ؅ཧͩͥʔ
    • ݁ہ͸ Web ΞϓϦͷʢུ
    ΋ͬͱ؆୯ʹόονΛॻ͖͍ͨ

    View full-size slide

  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 Ͱࢦఆ࣌ࠁʹॲཧΛ࣮ߦͰ͖Δɻ
    ࢦఆ࣌ࠁͷଞʹ΋׬ྃ࣌఺͔Βࢦఆ࣌ࠁޙʹىಈͱ͍ͬͨॻ͖ํ΋Ͱ͖Δɻ

    View full-size slide

  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
    ؆୯ʂʂ
    ͱ͸ݴ͑ɺ࣮ۀ຿Ͱ࢖͏ͨΊʹɺ΋͏ͪΐͬͱ޻෉͠·͠ΐ͏ɻ
    • ෳ਺εϨουͰಈ͘Α͏ʹ͢Δ
    • ಛఆͷαʔόͷΈͰಈ͘Α͏ʹ͢Δ
    • όονͷ։࢝ɾऴྃ࣌ʹϩάΛग़͢ʢ࣮ߦ࣌ؒͱ͔ʣ
    • αʔόఀࢭ࣌ʹ଴ͭ

    View full-size slide

  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 ΠϯλϑΣʔεΛ࣮૷͢Δ͜ͱͰ࣮ݱՄೳɻ

    View full-size slide

  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 Ͱόονͷ࣮ߦ੍ޚΛ࣮ݱ͢Δ
    ಛఆͷϗετͰ͔͠ಈ͔ͳ͍Α͏ʹ͢Δ
    ։࢝ɾऴྃɾܭଌϩάΛग़͢

    View full-size slide

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

    View full-size slide

  51. >
    <
    05
    Property
    ϓϩύςΟ
    51

    View full-size slide

  52. >
    < 52
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢ΔલʹϓϩύςΟʹ͍ͭͯߟ͍͑ͨ͜ͱ
    • ຊ൪؀ڥ΍։ൃ؀ڥͳͲͰઃఆϑΝΠϧΛ෼͚͍ͨ
    • DB ͷ઀ଓઌΛม͍͑ͨ
    • ։ൃ࣌͸ messageSource ͷ cache ͸ແ͠ʹ͍ͨ͠౳ͳͲ
    • ֎෦ʢOS؀ڥม਺౳ʣ͔ΒઃఆΛ্ॻ͖Ͱ͖ΔΑ͏ʹ͍ͨ͠
    • application.properties ͸όʔδϣϯ؅ཧର৅ʹ͍ͯ͠Δ͕ɺ

    DB ͷύεϫʔυ౳ͷػີ৘ใ͸ଞͷਓ͔ΒݟΒΕͳ͍Α͏ʹ͍ͨ͠ɻ
    • Twelve-Factor App ͷཁૉͱͯ͠΋ॏཁ

    View full-size slide

  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

    View full-size slide

  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).

    View full-size slide

  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

    View full-size slide

  56. >
    < 56
    JJUG CCC 2016 Spring. 2016/05/21
    ·ͱΊ ɿ ϓϩύςΟ
    ֤؀ڥผͷϓϩύςΟ͸ɺ֤؀ڥ༻ͷϑΝΠϧʹهड़͢Δ
    ͜ΕͰɺϓϩύςΟʹؔͯ͠͸
    ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ
    ػີ৘ใ͸ OS ؀ڥม਺Ͱ্ॻ͖

    View full-size slide

  57. >
    <
    06
    Logging
    ϩΪϯά
    57

    View full-size slide

  58. >
    < 58
    JJUG CCC 2016 Spring. 2016/05/21
    ػೳ։ൃΛ͢ΔલʹϩΪϯάʹ͍ͭͯߟ͍͑ͨ͜ͱ
    • log4j ͸͍͍Ճݮʹ΍Ί͍ͨ
    • ग़ྗจࣈྻͷߏஙͱ͔ΊΜͲ͍͘͞
    • isDebugEnabled ΋ΊΜͲ͍͘͞
    • log4j ͸طʹ EOL
    • ϩάΠϯ͍ͯ͠Δ userIdɺrequestId ౳͸ࣗಈͰ෇͘Α͏ʹ͍ͨ͠
    • ͜ΕΒΛϩάʹग़͓ͯ͘͠ͱɺো֐࣌ͷݪҼڀ໌ʹศརɻ

    ಛʹ requestId ʹؔͯ͠͸ microservices తʹ։ൃ͍ͯ͠Δ৔߹ɺ

    αʔϏεؒͷϩάͷඥ෇͚ͱͯ͠ಛʹॏཁɻ
    • ͨͩɺࣗ෼Ͱຖճॻ͘ͷ͸ͩΔ͍ɻ

    View full-size slide

  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ʢಠࣗλάʣ͕࢖͑ΔͷͰศརɻ



    defaultValue="localhost"/>

    ${fluentHost}
    ...

    View full-size slide

  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

    View full-size slide

  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 ͢Δ

    View full-size slide

  62. >
    < 62
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ4ʣ


    %d{ISO8601} %-5p [%t] %c{2} \(%L\) - [%X{REQUEST_ID:-undefined}][%X{LOGIN_USER_ID:-
    undefined}] %m%n


    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 ͷ஋Λදࣔ͢Δ

    View full-size slide

  63. >
    < 63
    JJUG CCC 2016 Spring. 2016/05/21
    ·ͱΊ ɿ ϩΪϯά
    SLF4J + logback ͕࢖͑ͯɺuserId ౳͸ࣗ෼Ͱॻ͔ͳͯ͘Α͍
    ͜ΕͰɺϩΪϯάʹؔͯ͠͸
    ͱ͍͏ɺػೳ։ൃ Ready ͳঢ়ଶʹͳͬͨʂ

    View full-size slide

  64. >
    <
    07
    Security
    ηΩϡϦςΟ
    64

    View full-size slide

  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 ͕શવߋ৽͞Εͳ͍ͱ͔ɾɾɾ
    ʢ˞ ೝূɾೝՄʹ͍ͭͯ͸આ໌͠·ͤΜʣ

    View full-size slide

  66. >
    < 66
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ1ʣ
    XSS
    Spring Boot ͳΒ Thymeleaf ͕Ұ൪͓͢͢Ίɻ
    Thymeleaf ʹΑΔςΩετͷग़ྗ͸σϑΥϧτͰΤεέʔϓ͞ΕΔɻ

    escapedString

    unescapedString
    ͪΌΜͱ҆શଆ͕σϑΥϧτʹͳ͍ͬͯΔɻ

    View full-size slide

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

    View full-size slide

  68. >
    < 68
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ3ʣ
    CSRF
    Spring Security Λ࢖͑͹ɺϑΥʔϜ΁ͷτʔΫϯຒΊࠐΈ͔Βɺ
    αʔόʔαΠυͰͷνΣοΫ·ͰΛࣗಈͰ΍ͬͯ͘ΕΔɻ
    ͨͩ͠ɺSpring Security ͸݁ߏ͓͔͍ͤͬͳ΋ͷ΋༗ޮʹͳͬͯ͠·͏ͷͰɺ
    ͦ͜Β΁Μ͸ͪΌΜͱແޮԽ͠ͳ͍ͱ͍͚ͳ͍ɻBasic ೝূͱ͔ɻ


    org.springframework.boot
    spring-boot-starter-security


    security.basic.enabled=false

    View full-size slide

  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 ͢ΔΑ͏ʹઃఆɻ

    View full-size slide

  70. >
    < 70
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ5ʣ
    ࣗಈͰઃఆ͞ΕΔ※

    ʢth:action Λ࢖͍ͬͯΔ৔߹ʣ

    View full-size slide

  71. >
    < 71
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ6ʣ
    Status Code ͸ 403

    View full-size slide

  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

    View full-size slide

  73. >
    < 73
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ8ʣ
    Security Header ͕

    ग़ྗ͞Ε͍ͯΔ

    View full-size slide

  74. >
    < 74
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ9ʣ
    ϥΠϒϥϦʢjarʣͷΞοϓσʔτ
    Spring Boot ͷ৔߹ɺspring-boot-starter-parent ͷ਌ POM ͕ɺ
    ੔߹ੑͷऔΕͨˍΘΓͱ࠷৽ͷ jar Λ࢖ͬͯ͘ΕΔͷͰɺ
    جຊతʹ͸ Boot ͷόʔδϣϯΛ্͛Δ͚ͩʢࣗ෼Ͱ Λࢦఆ͠ͳ͍ʣ
    ͨͩ͠ɺݸผͷ jar Ͱ Security Fix ͳͲ͕ग़ͯɺ
    Boot ͷϦϦʔε͕ؒʹ߹͍ͬͯͳ͍৔߹͸ɺݸผʹόʔδϣϯΛࢦఆ͢Δɻ

    2.8.1

    ਌ POM Ͱ property ͕࢖ΘΕ͍ͯΔͷͰɺ

    ͦΕΛ্ॻ͖͢Δ͚ͩͰΑ͍ɻ
    https://github.com/spring-projects/spring-boot/blob/master/spring-boot-
    dependencies/pom.xml

    View full-size slide

  75. >
    < 75
    JJUG CCC 2016 Spring. 2016/05/21
    Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ10ʣ
    ࣗ෼ͰೖΕͨ jar ͷ৔߹͸ɺVersions Maven Plugin Λ࢖͏ͷ͕ศརɻ
    http://www.mojohaus.org/versions-maven-plugin/



    org.codehaus.mojo
    versions-maven-plugin
    2.1



    όʔδϣϯΞοϓ͕Մೳͳ dependency, plugin ͷදࣔ΍ߋ৽ʢةݥʂʣ
    Λߦ͏͜ͱ͕Ͱ͖Δɻ
    ଞʹ΋ project ͷ λάͷߋ৽ͳͲ΋Ͱ͖Δɻ

    View full-size slide

  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 ͷόʔδϣϯ৘ใ

    ߋ৽͠·͠ΐ͏

    View full-size slide

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

    View full-size slide

  78. >
    <
    08
    Others
    ͦͷଞ
    78

    View full-size slide

  79. >
    < 79
    JJUG CCC 2016 Spring. 2016/05/21
    DevTools
    ։ൃ࣌ʹେମઃఆ͢ΔͰ͋Ζ͏ɺ
    ςϯϓϨʔτΩϟογϡͷແޮԽɺϗοτϦϩʔυͷઃఆ౳͕ҰൃͰՄೳɻ
    ʢSpring Loaded ͱ͸ผ෺ʣ


    org.springframework.boot
    spring-boot-devtools
    true


    http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/
    #using-boot-devtools
    ͜ͷઃఆ͚ͩͰ spring.thymeleaf.cache=false ͱ͔ɺ
    spring.freemarker.cache=false ౳Λɺݸผʹॻ͔ͳͯ͘΋Α͘ͳΔɻ
    ΋ͪΖΜຊ൪؀ڥͰ༗ޮʹͳΒͳ͍Α͏ʹߟྀ͞Ε͍ͯΔɻ

    View full-size slide

  80. >
    < 80
    JJUG CCC 2016 Spring. 2016/05/21
    lombok
    Spring ؔ܎ͳ͍͚Ͳɺ͍͢͝ศརͳͷͰɺੋඇಋೖ͠·͠ΐ͏ɻ
    ͨͩ͠ɺexperimental ͳػೳʹ͍ͭͯ͸ɺ͝ར༻͸ܭըతʹɻ


    org.projectlombok
    lombok
    1.16.8
    provided


    View full-size slide

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

    View full-size slide

  82. >
    < 82
    JJUG CCC 2016 Spring. 2016/05/21
    ΞϓϦέʔγϣϯͷݟ͑ΔԽʢRoutingʣ
    https://github.com/sinsengumi/spring-boot-application-infrastructure/blob/
    master/src/main/java/com/example/controller/screen/admin/system/
    RouterController.java

    View full-size slide

  83. >
    < 83
    JJUG CCC 2016 Spring. 2016/05/21
    ΞϓϦέʔγϣϯͷݟ͑ΔԽʢContextʣ
    https://github.com/sinsengumi/spring-boot-application-infrastructure/blob/
    master/src/main/java/com/example/controller/screen/admin/system/
    ContextController.java

    View full-size slide

  84. >
    < 84
    JJUG CCC 2016 Spring. 2016/05/21
    ΞϓϦέʔγϣϯͷݟ͑ΔԽʢBatchʣ
    https://github.com/sinsengumi/spring-boot-application-infrastructure/blob/
    master/src/main/java/com/example/controller/screen/admin/system/
    BatchController.java

    View full-size slide

  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

    View full-size slide

  86. >
    <
    99
    Conclusion
    ·ͱΊ
    86

    View full-size slide

  87. >
    < 87
    JJUG CCC 2016 Spring. 2016/05/21
    ·ͱΊ
    • ػೳΛ࡞ΓࠐΉલʹɺج൫ઃܭΛͪΌΜͱ͓ͯ͜͠͏
    • ૊Έ߹Θ͕ͤେมͱ͔ݴ͚ͬͨͲɺSpring Boot ͸ૉ੖Β͍͠ϓϩμΫτ

    ࠓɺJava ͰΞϓϦ࡞ΔͳΒɺީิͱͯ͠͸࠷༗ྗͳ͸ͣ
    • ࠓ೔࿩ͤͳ͔ͬͨ͜ͱʢೝূɾೝՄɺΩϟογϡɺςετʣ
    • ࠓ೔ͷαϯϓϧίʔυ͸

    https://github.com/sinsengumi/spring-boot-application-infrastructure

    View full-size slide

  88. >
    < 88
    JJUG CCC 2016 Spring. 2016/05/21
    ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ

    View full-size slide