Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Springで始める3層アーキテクチャ / start three layer architecture with spring
yachiy
November 14, 2019
0
51
Springで始める3層アーキテクチャ / start three layer architecture with spring
yachiy
November 14, 2019
Tweet
Share
More Decks by yachiy
See All by yachiy
AWS事始め / Introduction AWS
yachiy
1
27
Springで始めるWebApplication / Start Spring Web Application
yachiy
0
81
RDRAとDDDを実践していく上でのCleanArchitectureの同異点 / RDRA and Clean Architecture differences
yachiy
0
110
議事録のとり方 / how to write proceeding
yachiy
0
150
値オブジェクトの悩みポイントとどう付き合っていくか
yachiy
1
1.3k
Featured
See All Featured
The Invisible Side of Design
smashingmag
290
48k
In The Pink: A Labor of Love
frogandcode
131
21k
10 Git Anti Patterns You Should be Aware of
lemiorhan
638
52k
Design by the Numbers
sachag
271
17k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
37
3.3k
Designing Experiences People Love
moore
130
22k
The Illustrated Children's Guide to Kubernetes
chrisshort
15
36k
Designing the Hi-DPI Web
ddemaree
272
32k
Ruby is Unlike a Banana
tanoku
91
9.2k
Support Driven Design
roundedbygravity
86
8.5k
Statistics for Hackers
jakevdp
781
210k
StorybookのUI Testing Handbookを読んだ
zakiyama
5
2.3k
Transcript
4QSJOHͰ࢝ΊΔΞʔΩςΫνϟ
ͱ
ϓϨθϯςʔγϣϯ σʔλΞΫηε ϏδωεϩδοΫ
ϓϨθϯςʔγϣϯ
ը໘ͩͬͨΓɺ"1*ͷΤϯυϙΠϯτͩͬͨΓ ར༻ऀͱͷڥքɺΠϯλϑΣʔεʹͳΔ෦
σʔλΞΫηε
σʔλͷӬଓԽɺ࠶ߏΛߦ͏Έʢ%# ͱ͔ϑΝΠϧͱ͔ʣͱͷΓऔΓΛߦ͏
ϏδωεϩδοΫ
ۀͷϩδοΫΛهड़͢Δ
ʁʁʁ
ۀͱ
ۀ ˠͦͷΞϓϦέʔγϣϯͰղܾ͍ͨ͠ ˠଟذʹΘͨΔʹෳࡶ
IUUQTXXXTMJEFTIBSFOFUNBTVEBTT
͜͜
݁ہҰ൪ूத͍ͨ͠ͷۀͷ༰͔ͩΒ ೖग़ྗ͔Βִͯ͠͠·͠ΐ͏ͱ͍͏
4QSJOHͰ͍͏ͱ
!$POUSPMMFS !3FTU$POUSPMMFS !3FQPTJUPSZ !4FSWJDF
࣮ફ
ίϝϯτΛॻ͖ࠐΊΔϝϞாΛߟ͑Δ ʢߦͷ్தʹίϝϯτೖΕͯແࢹ͢Δʣ ༰Λॻ͚Δ ೖྗ༰ΛอଘͰ͖Δ ίϝϯτ͕ফ͑ͨঢ়ଶͰ༰͕ݟΕΔ
ίϝϯτΛॻ͖ࠐΊΔϝϞாΛߟ͑Δ ʢߦͷ్தʹίϝϯτೖΕͯແࢹ͢Δʣ ༰Λॻ͚Δ ೖྗ༰ΛอଘͰ͖Δ ίϝϯτ͕ফ͑ͨঢ়ଶͰ༰͕ݟΕΔ
package com.yachiy.spring.introduction.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class MemoController
{ @GetMapping("/") public String memo() { return "memo"; } } .FNP$POUSPMMFSKBWB
<!doctype html> <html> <head> <meta charset="UTF-8"/> <title>ίϝϯτΞτ͕ޮ͘ϝϞாʢԾʣ</title> </head> <body> <h1>ίϝϯτΞτ͕ޮ͘ϝϞாʢԾʣ</h1>
<textarea id="content" cols="50" rows="20" placeholder="༰Λೖྗ͍ͯͩ͘͠͞"></textarea> <button>ૹ৴</button> </body> </html> NFNPIUNM
࣮ߦͯ͠MPDBMIPTUʹΞΫηε
ը໘ग़Δʢೖྗͯ͠ૹ৴ͯ͠Կى͜Βͳ͍͚Ͳʣ
࣍ʹೖྗͷड͚औΓ
package com.yachiy.spring.introduction.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping;
@Controller public class MemoController { @GetMapping("/") public String memo() { return "memo"; } @PostMapping("/") public String receive(MemoForm memoForm, Model model) { model.addAttribute("content", memoForm.getContent()); return "received"; } } .FNP$POUSPMMFSKBWB 1045ͷ݁ՌΛड͚औΔϝιουΛ Ճ
package com.yachiy.spring.introduction.controller; /** * ϝϞ༰Λड͚ͨ͢ΊͷϞσϧ */ public class MemoForm {
private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } } .FNP'PSNKBWB
<!doctype html> <html xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"/> <title>݁Ռ</title> </head> <body>
<h1>༰Λड͚औΓ·ͨ͠</h1> <div th:text="${content}"></div> </body> </html> SFDFJWFEIUNM
<!doctype html> <html> <head> <meta charset="UTF-8"/> <title>ίϝϯτΞτ͕ޮ͘ϝϞாʢԾʣ</title> </head> <body> <h1>ίϝϯτΞτ͕ޮ͘ϝϞாʢԾʣ</h1>
<form method="post" action="/"> <textarea id="content" name="content" cols="50" rows="20" placeholder="༰Λೖྗ͍ͯͩ͘͠͞"></textarea> <button>ૹ৴</button> </form> </body> </html> NFNPIUNM GPSNλάՃ .FNP'PSNͷϑΟʔϧυ໊ͱҰகͤ͞Δ
࣮ߦͯ͠MPDBMIPTUʹΞΫηε
ೖྗͯ͠ ԡԼ
ೖྗ༰͕ө͞Ε͍ͯΔ
ίϝϯτΛॻ͖ࠐΊΔϝϞாΛߟ͑Δ ʢߦͷ్தʹίϝϯτೖΕͯແࢹ͢Δʣ ༰Λॻ͚Δ ೖྗ༰ΛอଘͰ͖Δ ίϝϯτ͕ফ͑ͨঢ়ଶͰ༰͕ݟΕΔ
࣍อଘͱ֬ೝʢϝϞாͳͷͰʣ
͚ͩͲ%#Λ༻ҙ͢Δͷ݁ߏେมʜ ˠࠓճϝϞϦ্ʹอଘ͢ΔΑ͏࣮
͡Ό࣮͋ࡍ%#͏Α͏ʹͳͬͨΒ ৭ʑͳॴஔ͖͑ͳ͖Ό͍͚ͳ͍ͷʁ ˠ%*ͷΈΛͬͯӬଓԽͷೖग़ྗͷϩδοΫ͚ͩ ஔ͖͑ΕॅΉΑ͏ʹ࣮͢Δ
package com.yachiy.spring.introduction.dao; public interface MemoDao { /** * ϝϞ༰ΛӬଓԽ͠ϝϞIDΛฦ٫͢Δ. *
* @param content ༰ * @return ϝϞID */ int store(String content); /** * IDΛࢦఆͯ͠ϝϞ༰Λऔಘ͢Δ. * * @param id ϝϞID * @return ϝϞ༰ */ String findById(int id); } .FNP%BPKBWB ϝϞΛӬଓԽ࠶ߏ͢ΔͨΊͷΠϯλϑΣʔε
package com.yachiy.spring.introduction.dao; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; @Repository public
class InMemoryMemoDao implements MemoDao { private static final List<String> memoList = new ArrayList<>(); @Override public int store(String content) { memoList.add(content); return memoList.size(); } @Override public String findById(int id) { return memoList.get(id - 1); // 0࢝·ΓͳͷͰ-1 } } *O.FNPSZ.FNP%BPKBWB ϝϞϦ্Ͱ.FNP%BPͷڍಈΛ࣮ݱ͢Δ࣮Ϋϥε %*ίϯςφʹొ
package com.yachiy.spring.introduction.controller; import com.yachiy.spring.introduction.dao.MemoDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @Controller public class MemoController { private MemoDao memoDao; @Autowired public MemoController(MemoDao memoDao) { this.memoDao = memoDao; } @GetMapping("/") public String memo() { return "memo"; } @PostMapping("/") public String receive(MemoForm memoForm, Model model) { int memoId = memoDao.store(memoForm.getContent()); model.addAttribute("memoId", memoId); return "received"; } @GetMapping("/{memoId}") public String view(@PathVariable int memoId, Model model) { String content = memoDao.findById(memoId); model.addAttribute("content", content); return "view"; } } .FNP$POUSPMMFSKBWB %FQFOEFODZ*OKFDUJPO ύε͔ΒΛऔಘ
<!doctype html> <html xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"/> <title>݁Ռ</title> </head> <body>
<h1>༰Λड͚औΓ·ͨ͠</h1> <div>ϝϞIDɿ</div> <div th:text="${memoId}"></div> </body> </html> SFDFJWFEIUNM <!doctype html> <html xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"/> <title>༰</title> </head> <body> <div th:text="${content}"></div> </body> </html> WJFXIUNM
!3FQPTJUPSZ ӬଓԽͷͨΊͷ࣮Λ%*ίϯςφʹొ ͢ΔͨΊͷΞϊςʔγϣϯ
%*ίϯςφ %FQFOEFODZ*OKFDUJPO͍࣮ͨ͠Λొ ͓ͯ͘͠ॴ
!"VUPXJSFE %*ίϯςφ͔Βͯ·Δ࣮Λೖ͢Δ ͨΊͷΞϊςʔγϣϯ
ʁʁʁ
ԿΛ͍͔ͨ͠
$POUSPMMFSͷཱ͔Β͢Δͱʜ ˠड͚औͬͨϝϞͷ༰ͷӬଓԽΛґཔ͍ͨ͠ɻ ˠӬଓԽઌ%#ͰϑΝΠϧͰϝϞϦ্Ͱ΄͍͠ͱ͖ʹऔΓग़ͤΕ Ͳ͜Ͱ͍͍ɻ ˠ࣮ʹґଘͨ͘͠ͳ͍ ˠΠϯλϑΣʔε͚͍ͩͬͯͨ ˠదͳ࣮Λউखʹࠩ͠ࠐΜͰ΄͍͠ ґଘੑٯసͷ๏ଇ
ґଘੑΛٯసΠϯλϑΣʔεʹͯ·Δ࣮ Λࠩ͠ࠐΉ ˠ%FQFOEFODZ*OKFDUJPO
͡Ό͋ԿΛࠩ͠ࠐΉ͔ ˠ%*ίϯςφʹొ͞Ε͍ͯΔͷͷͳ͔͔Βͦ ͷΠϯλʔϑΣʔεΛ࣮͍ͯ͠ΔͷΛࠩ͠ࠐΉ ͳͷͰಉ͡ΠϯλʔϑΣʔεΛ࣮͍ͯ͠Δ ͷ͔̍ͭ͠%*ίϯςφʹొͰ͖ͳ͍
ϝϞϦʹอଘ͢ΔͷΊͯ .Z42-Λ͍͍ͨ߹
package com.yachiy.spring.introduction.dao; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; // @Repository
public class InMemoryMemoDao implements MemoDao { private static final List<String> memoList = new ArrayList<>(); @Override public int store(String content) { memoList.add(content); return memoList.size(); } @Override public String findById(int id) { return memoList.get(id - 1); // 0࢝·Γͳͷ Ͱ-1 } } *O.FNPSZ.FNP%BPKBWB ίϝϯτΞτ package com.yachiy.spring.introduction.dao; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; @Repository public class MySQLMemoDao implements MemoDao { @Override public int store(String content) { JdbcTemplate …. } @Override public String findById(int id) { JdbcTemplate …. } } .Z42-.FNP%BPKBWB ͪ͜ΒΛ%*ίϯςφʹొ
package com.yachiy.spring.introduction.controller; import com.yachiy.spring.introduction.dao.MemoDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @Controller public class MemoController { private MemoDao memoDao; @Autowired public MemoController(MemoDao memoDao) { this.memoDao = memoDao; } @GetMapping("/") public String memo() { return "memo"; } @PostMapping("/") public String receive(MemoForm memoForm, Model model) { int memoId = memoDao.store(memoForm.getContent()); model.addAttribute("memoId", memoId); return "received"; } @GetMapping("/{memoId}") public String view(@PathVariable int memoId, Model model) { String content = memoDao.findById(memoId); model.addAttribute("content", content); return "view"; } } .FNP$POUSPMMFSKBWB มߋҰͳ͠
ಈ͔ͯ͠ΈΔ
CPPU3VOͯ͠MPDBMIPTUʹΞΫηε
ԡԼ
อଘ͞ΕͨϝϞͷ*%
MPDBMIPTU\NFNP*E^ʹΞΫηε
ϝϞͷ༰͕ग़ྗ͞Εͯ ͍Δ͜ͱΛ֬ೝ
ೖग़ྗ0,
ίϝϯτΛॻ͖ࠐΊΔϝϞாΛߟ͑Δ ʢߦͷ్தʹίϝϯτೖΕͯແࢹ͢Δʣ ༰Λॻ͚Δ ೖྗ༰ΛอଘͰ͖Δ ίϝϯτ͕ফ͑ͨঢ়ଶͰ༰͕ݟΕΔ
ͬͱۀϩδοΫ
ࠓճͷۀ ίϝϯτΛফ͢
ίϝϯτΛফ͢λΠϛϯάͲͪΒ͕ྑͦ͞͏͔ อଘ͢Δͱ͖ʹίϝϯτΛফ͔ͯ͠Βอଘ ͢Δ ੜσʔλΛอଘͯ͠ϝϞΛ֬ೝ͢Δͱ͖ʹ ίϝϯτΛফ͢
ݕ౼
อଘ࣌ʹίϝϯτΛফ͢ύλʔϯ ίϝϯτΛফ͢ॲཧ͕ͳͯ͘ࡁΉʢελΠϧ ͯΔͷอଘ࣌ͷΈʣ ੜσʔλͷ֬ೝෆՄ औಘ࣌ʹίϝϯτΛফ͢ύλʔϯ ੜσʔλΛ֬ೝͰ͖Δ ֬ೝͷͨͼʹίϝϯτΛফ͢ඞཁ͕͋Δ
࣮ࡍʹۀͷࠓޙΛߟ͑Δͱʜ ฤूػೳཉ͘͠ͳΓͦ͏ ˠͦͷͱ͖ʹੜσʔλͰฤू͍ͨ͠ ˠίϝϯτΛফͯ͠อଘ͢ΔͱͦͷใࣦΘ Εͯ͠·͏ ˠࠓճͷۀͰফͨ͠ঢ়ଶͰอଘ͍͚ͯ͠ ͳ͍
ͲͬͪͰ͍͍߹Έ ʢˍνʔϜͰͷܾΊʣ
package com.yachiy.spring.introduction.service; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class
CommentOutService { public String execute(String content) { List<String> lines = Arrays.asList(content.split("\r\n")); List<String> markUpList = lines.stream() .map(this::commentOut) .collect(Collectors.toList()); return String.join("\r\n", markUpList); } private String commentOut(String content) { if (content.matches("//.+")) { return ""; } return content; } } $PNNFOU0VU4FSWJDFKBWB
package com.yachiy.spring.introduction.controller; import com.yachiy.spring.introduction.dao.MemoDao; import com.yachiy.spring.introduction.service.CommentOutService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @Controller public class MemoController { private MemoDao memoDao; @Autowired public MemoController(MemoDao memoDao) { this.memoDao = memoDao; } @GetMapping("/") public String memo() { return "memo"; } @PostMapping("/") public String receive(MemoForm memoForm, Model model) { int memoId = memoDao.store(memoForm.getContent()); model.addAttribute("memoId", memoId); return "received"; } @GetMapping("/{memoId}") public String view(@PathVariable int memoId, Model model) { String content = memoDao.findById(memoId); model.addAttribute("content", new CommentOutService().execute(content)); return "view"; } } .FNP$POUSPMMFSKBWB ίϝϯτΞτͷۀ ϩδοΫΛݺग़
CPPU3VOͯ͠MPDBMIPTUʹΞΫηε
ԡԼ
MPDBMIPTU\NFNP*E^ʹΞΫηε
ίϝϯτ͕ফ͍͑ͯΔ͜ͱ Λ֬ೝ
ΞʔΩςΫνϟΛ࣮ݱͰ͖ͨ
େࣄͳͷ֤ͷׂ͕ଞͷʹછΈग़͞ ͳ͍͜ͱ ಛʹۀϩδοΫଞͷʹછΈग़͕ͪ͠ ͳͷͰҙࣝͯ͠ઃܭ͢Δ