Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

> < 13 JJUG CCC 2016 Spring. 2016/05/21 Boot ͸ૣ͍͕ɾɾɾʢ5ʣ େํ਑ • Spring ͷํ਑ʹै͏ʢRail ʹ৐Δతͳʣ
 @Controller, @Service, @Repository Λ࢖ͬͨجຊతͳϨΠϠʔߏ੒ • ίʔυΛͳΔ΂͘ॻ͔ͳ͍
 ॻ͔ͳ͍ͨΊʹϑϨʔϜϫʔΫΛ࢖͍ͬͯΔ • ۀ຿ػೳΛ࡞Δ࣌ʹɺ͸·Βͳ͍ɺ೰·ͳ͍Α͏ͳઃܭ

Slide 14

Slide 14 text

> < 01 URL Layout 63-ઃܭ 14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

> < 02 Exception ྫ֎ 19

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

> < 04 Batch όον 43

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

> < 05 Property ϓϩύςΟ 51

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

> < 06 Logging ϩΪϯά 57

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

> < 07 Security ηΩϡϦςΟ 64

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

> < 70 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ5ʣ ࣗಈͰઃఆ͞ΕΔ※ ʢth:action Λ࢖͍ͬͯΔ৔߹ʣ

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

> < 73 JJUG CCC 2016 Spring. 2016/05/21 Ͱ͸ Spring Boot Ͱ͸Ͳ͏͢Δ͔ʁʢ8ʣ Security Header ͕ ग़ྗ͞Ε͍ͯΔ

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

> < 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 ͷ λάͷߋ৽ͳͲ΋Ͱ͖Δɻ

Slide 76

Slide 76 text

> < 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 ͷόʔδϣϯ৘ใ ߋ৽͠·͠ΐ͏

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

> < 08 Others ͦͷଞ 78

Slide 79

Slide 79 text

> < 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 ౳Λɺݸผʹॻ͔ͳͯ͘΋Α͘ͳΔɻ ΋ͪΖΜຊ൪؀ڥͰ༗ޮʹͳΒͳ͍Α͏ʹߟྀ͞Ε͍ͯΔɻ

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

> < 99 Conclusion ·ͱΊ 86

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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