├── .gitignore
├── .idea
├── .gitignore
├── modules.xml
├── spring_basic2.iml
└── vcs.xml
├── LICENSE
├── README.md
├── ch2
├── BoardController.java
├── Car.java
├── DBConnectionTest2Test.java
├── ExceptionController.java
├── ExceptionController2.java
├── GlobalCatcher.java
├── GlobalValidator.java
├── HelloServlet.java
├── LoginController.java
├── MethodCall.java
├── MethodCall2.java
├── MethodCall3.java
├── MethodInfo.java
├── MyDate.java
├── MyDispatcherServlet.java
├── PerformanceFilter.java
├── Person.java
├── PrivateMethodCall.java
├── RegisterController.java
├── RequestHeader.java
├── RequestInfo.java
├── RequestMappingTest.java
├── RequestMessage.java
├── RequestParamTest.java
├── SetterCall.java
├── TwoDice.java
├── TwoDiceServlet.java
├── User.java
├── UserValidator.java
├── YoilTeller.java
├── YoilTellerMVC.java
├── YoilTellerMVC2.java
├── YoilTellerMVC3.java
├── YoilTellerMVC4.java
├── YoilTellerMVC5.java
├── YoilTellerMVC6.java
├── YoilTellerServlet.java
├── boardList.jsp
├── dice.zip
├── el.jsp
├── error.jsp
├── error_message.properties
├── index.jsp
├── jstl.jsp
├── loginForm.jsp
├── menu.css
├── registerForm.html
├── registerForm.jsp
├── registerInfo.jsp
├── servlet-context.xml
├── twoDice.jsp
├── web.xml
├── yoil.jsp
├── yoilError.jsp
└── yoilTeller.jsp
├── ch3
├── AopMain.java
├── ApplicationContextTest.java
├── DBConnectionTest.java
├── DBConnectionTest2.java
├── DBConnectionTest2Test.java
├── DBConnectionTest3.java
├── HomeController.java
├── LoginController.java
├── RegisterController.java
├── User.java
├── UserDao.java
├── UserDaoImpl.java
├── UserValidator.java
├── config.xml
├── config1.xml
├── error_message.properties
├── index.jsp
├── loginForm.jsp
├── menu.css
├── readme.md
├── registerForm.jsp
├── registerInfo.jsp
├── root-context.xml
└── root-context_aop.xml
├── ch4
├── BoardController.java
├── BoardController2.java
├── BoardController3.java
├── BoardDao.java
├── BoardDaoImpl.java
├── BoardDaoImplTest.java
├── BoardDto.java
├── BoardService.java
├── BoardServiceImpl.java
├── BoardServiceImplTest.java
├── CommentController.java
├── CommentDao.java
├── CommentDaoImpl.java
├── CommentDaoImplTest.java
├── CommentDto.java
├── CommentServiceImpl.java
├── CommentServiceImplTest.java
├── LoginController.java
├── PageHandler.java
├── SearchCondition.java
├── SimpleRestController.java
├── User.java
├── UserDao.java
├── UserDaoImpl.java
├── UserDaoImplTest.java
├── ajax.jsp
├── board.jsp
├── board2.jsp
├── board3.jsp
├── boardList.jsp
├── boardList2.jsp
├── boardList3.jsp
├── boardMapper.xml
├── boardMapper2.xml
├── comment.html
├── commentMapper.xml
├── create_table_board.sql
├── index.jsp
├── log4jdbc.log4j2.properties
├── logback.xml
├── loginForm.jsp
├── menu.css
├── mybatis-config.xml
├── pom.xml
├── readme.md
├── root-context.xml
├── servlet-context.xml
├── test.jsp
├── test2.jsp
└── web.xml
├── ch5
├── readme.md
├── springbasic.mwb
├── 프로젝트_파일목록.xlsx
├── 화면정의서_샘플.pptx
├── 화면정의서_샘플_주주마켓.pdf
└── 화면정의서_요소.pptx
└── download
├── MySQL57설치방법_MacOS_m1.md
├── ch2.zip
├── ch2_final.zip
├── ch2_final_mac.zip
├── ch3.zip
├── ch3_final.zip
├── ch4.zip
├── firstSpring.zip
├── myportfolio.zip
├── project_import1.PNG
├── project_import2.PNG
├── readme.md
├── 프로젝트_파일목록.xlsx
├── 화면정의서_샘플.pptx
├── 화면정의서_샘플_주주마켓.pdf
├── 화면정의서_요소.pptx
├── 강의자료
├── [스프링의정석_기초편]ch2_01_원격실행.pdf
├── [스프링의정석_기초편]ch2_02_HTTP요청과응답_실습.pdf
├── [스프링의정석_기초편]ch2_03_HTTP클라이언트서버.pdf
├── [스프링의정석_기초편]ch2_04_HTTP요청과응답_이론.pdf
├── [스프링의정석_기초편]ch2_05_SpringMVC.pdf
├── [스프링의정석_기초편]ch2_06_Servlet_JSP.pdf
├── [스프링의정석_기초편]ch2_07_RequestParam_ModelAttribute.pdf
├── [스프링의정석_기초편]ch2_08_redirect와forward.pdf
├── [스프링의정석_기초편]ch2_09_RequestMapping.pdf
├── [스프링의정석_기초편]ch2_10_쿠키.pdf
├── [스프링의정석_기초편]ch2_11_세션.pdf
├── [스프링의정석_기초편]ch2_12_예외처리.pdf
├── [스프링의정석_기초편]ch2_13_DispatcherServlet.pdf
├── [스프링의정석_기초편]ch2_14_데이터의변환과검증.pdf
├── [스프링의정석_기초편]ch3_1_스프링DI_흉내내기1.pdf
├── [스프링의정석_기초편]ch3_2_스프링DI_활용하기_이론1.pdf
├── [스프링의정석_기초편]ch3_3_DAO의작성과적용.pdf
├── [스프링의정석_기초편]ch3_4_Transaction_commit_rollback.pdf
├── [스프링의정석_기초편]ch3_5_AOP의개념과용어.pdf
├── [스프링의정석_기초편]ch3_6_서비스계층의분리와Transactional.pdf
├── [스프링의정석_기초편]ch4_01_MyBatis의개요와설정.pdf
├── [스프링의정석_기초편]ch4_02_MyBatis로DAO작성하기.pdf
├── [스프링의정석_기초편]ch4_03_게시판목록만들기와페이징TDD.pdf
├── [스프링의정석_기초편]ch4_04_게시판CRUD기능구현1.pdf
├── [스프링의정석_기초편]ch4_05_게시판검색기능추가.pdf
├── [스프링의정석_기초편]ch4_06_REST_API와Ajax.pdf
├── [스프링의정석_기초편]ch4_07_댓글기능구현1_DAO작성.pdf
├── [스프링의정석_기초편]ch5_01_02_git의기본명령어와원리1.pdf
├── [스프링의정석_기초편]ch5_03_git의기본명령어와원리2.pdf
└── readme.md
└── 인텔리제이_단축키.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/spring_basic2.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | No Cmmercial use, No Modification
2 | Distribution without modification and private use are allowed.
3 |
4 | Copyright (c) 2021 SEONG NAMKUNG
5 |
6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
11 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
12 | SOFTWARE.
13 |
--------------------------------------------------------------------------------
/ch2/BoardController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpSession;
5 |
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 |
10 | @Controller
11 | @RequestMapping("/board")
12 | public class BoardController {
13 | @GetMapping("/list")
14 | public String list(HttpServletRequest request) {
15 | if(!loginCheck(request))
16 | return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
17 |
18 | return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
19 | }
20 |
21 | private boolean loginCheck(HttpServletRequest request) {
22 | // 1. 세션을 얻어서
23 | HttpSession session = request.getSession();
24 | // 2. 세션에 id가 있는지 확인, 있으면 true를 반환
25 | return session.getAttribute("id")!=null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ch2/Car.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | public class Car {
4 | private String color = "red";
5 | public String getColor() { return color; }
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/ch2/ExceptionController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.FileNotFoundException;
4 |
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.ui.Model;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 |
12 | @Controller
13 | public class ExceptionController {
14 | @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
15 | public String catcher2(Exception ex, Model m) {
16 | m.addAttribute("ex", ex);
17 | return "error";
18 | }
19 |
20 | @ExceptionHandler(Exception.class)
21 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 200 -> 500
22 | public String catcher(Exception ex, Model m) {
23 | System.out.println("catcher() in ExceptionController");
24 | System.out.println("m="+m);
25 | // m.addAttribute("ex", ex);
26 |
27 | return "error";
28 | }
29 |
30 | @RequestMapping("/ex")
31 | public String main(Model m) throws Exception {
32 | m.addAttribute("msg", "message from ExceptionController.main()");
33 | throw new Exception("¿¹¿Ü°¡ ¹ß»ýÇß½À´Ï´Ù.");
34 | }
35 |
36 | @RequestMapping("/ex2")
37 | public String main2() throws Exception {
38 | throw new NullPointerException("¿¹¿Ü°¡ ¹ß»ýÇß½À´Ï´Ù.");
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ch2/ExceptionController2.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.FileNotFoundException;
4 |
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.ResponseStatus;
9 |
10 | //@ResponseStatus(HttpStatus.BAD_REQUEST) // 500 -> 400
11 | class MyException extends RuntimeException {
12 | MyException(String msg) {
13 | super(msg);
14 | }
15 | MyException() { this(""); }
16 | }
17 |
18 | @Controller
19 | public class ExceptionController2 {
20 |
21 | @RequestMapping("/ex3")
22 | public String main() throws Exception {
23 | throw new MyException("¿¹¿Ü°¡ ¹ß»ýÇß½À´Ï´Ù.");
24 | }
25 |
26 | @RequestMapping("/ex4")
27 | public String main2() throws Exception {
28 | throw new FileNotFoundException("¿¹¿Ü°¡ ¹ß»ýÇß½À´Ï´Ù.");
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/ch2/GlobalCatcher.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.FileNotFoundException;
4 |
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.ControllerAdvice;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 |
9 | @ControllerAdvice("com.fastcampus.ch3") // ÁöÁ¤µÈ ÆÐŰÁö¿¡¼ ¹ß»ýÇÑ ¿¹¿Ü¸¸ ó¸®
10 | // @ControllerAdvice // ¸ðµç ÆÐŰÁö¿¡ Àû¿ë
11 | public class GlobalCatcher {
12 | @ExceptionHandler({NullPointerException.class, FileNotFoundException.class})
13 | public String catcher2(Exception ex, Model m) {
14 | m.addAttribute("ex", ex);
15 | return "error";
16 | }
17 |
18 | @ExceptionHandler(Exception.class)
19 | public String catcher(Exception ex, Model m) {
20 | m.addAttribute("ex", ex);
21 |
22 | return "error";
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ch2/GlobalValidator.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.validation.Errors;
4 | import org.springframework.validation.ValidationUtils;
5 | import org.springframework.validation.Validator;
6 |
7 | public class GlobalValidator implements Validator {
8 | @Override
9 | public boolean supports(Class> clazz) {
10 | // return User.class.equals(clazz); // 검증하려는 객체가 User타입인지 확인
11 | return User.class.isAssignableFrom(clazz); // clazz가 User 또는 그 자손인지 확인
12 | }
13 |
14 | @Override
15 | public void validate(Object target, Errors errors) {
16 | System.out.println("GlobalValidator.validate() is called");
17 |
18 | User user = (User)target;
19 |
20 | String id = user.getId();
21 |
22 | // if(id==null || "".equals(id.trim())) {
23 | // errors.rejectValue("id", "required");
24 | // }
25 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "required");
26 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "pwd", "required");
27 |
28 | if(id==null || id.length() < 5 || id.length() > 12) {
29 | errors.rejectValue("id", "invalidLength", new String[]{"5", "12"}, null);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ch2/HelloServlet.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 |
6 | import javax.servlet.ServletConfig;
7 | import javax.servlet.ServletException;
8 | import javax.servlet.annotation.WebServlet;
9 | import javax.servlet.http.HttpServlet;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 |
13 | //@WebServlet(urlPatterns={"/hello"}, loadOnStartup=1)
14 | @WebServlet("/hello")
15 | public class HelloServlet extends HttpServlet {
16 | @Override
17 | public void init() throws ServletException {
18 | // 서블릿 초기화 - 서블릿이 생성 또는 리로딩 때, 단 한번만 수행됨.
19 | System.out.println("[HelloSerlvet] init()");
20 | }
21 |
22 | @Override // 호출될 때마다 반복적으로 수행됨.
23 | public void service(HttpServletRequest request, HttpServletResponse response) {
24 | // 1. 입력
25 | // 2. 처리
26 | // 3. 출력
27 | System.out.println("[HelloSerlvet] service()");
28 | }
29 |
30 | @Override
31 | public void destroy() {
32 | // 뒷정리 작업 - 서블릿이 제거(unload)될 때, 단 한번만 수행됨.
33 | System.out.println("[HelloSerlvet] destroy()");
34 | }
35 | }
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/ch2/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.net.URLEncoder;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletResponse;
7 |
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.GetMapping;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 |
13 | @Controller
14 | @RequestMapping("/login")
15 | public class LoginController {
16 | @GetMapping("/login")
17 | public String loginForm() {
18 | return "loginForm";
19 | }
20 |
21 | @PostMapping("/login")
22 | public String login(String id, String pwd, boolean rememberId, HttpServletResponse response) throws Exception {
23 | System.out.println("id="+id);
24 | System.out.println("pwd="+pwd);
25 | System.out.println("rememberId="+rememberId);
26 | // 1. id와 pwd를 확인
27 | if(!loginCheck(id, pwd)) {
28 | // 2-1 일치하지 않으면, loginForm으로 이동
29 | String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");
30 |
31 | return "redirect:/login/login?msg="+msg;
32 | }
33 |
34 | // 2-2. id와 pwd가 일치하면,
35 | if(rememberId) {
36 | // 1. 쿠키를 생성
37 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
38 | // 2. 응답에 저장
39 | response.addCookie(cookie);
40 | } else {
41 | // 1. 쿠키를 삭제
42 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
43 | cookie.setMaxAge(0); // 쿠키를 삭제
44 | // 2. 응답에 저장
45 | response.addCookie(cookie);
46 | }
47 | // 3. 홈으로 이동
48 | return "redirect:/";
49 | }
50 |
51 | private boolean loginCheck(String id, String pwd) {
52 | return "asdf".equals(id) && "1234".equals(pwd);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ch2/MethodCall.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.HashMap;
6 | import java.util.Iterator;
7 | import java.util.Scanner;
8 | import java.util.Set;
9 |
10 | public class MethodCall {
11 | public static void main(String[] args) throws Exception{
12 | HashMap map = new HashMap();
13 | System.out.println("before:"+map);
14 |
15 | ModelController mc = new ModelController();
16 | String viewName = mc.main(map);
17 |
18 | System.out.println("after :"+map);
19 |
20 | render(map, viewName);
21 | }
22 |
23 | static void render(HashMap map, String viewName) throws IOException {
24 | String result = "";
25 |
26 | // 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
27 | Scanner sc = new Scanner(new File(viewName+".txt"));
28 |
29 | while(sc.hasNextLine())
30 | result += sc.nextLine()+ System.lineSeparator();
31 |
32 | // 2. map에 담긴 key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
33 | Iterator it = map.keySet().iterator();
34 |
35 | while(it.hasNext()) {
36 | String key = (String)it.next();
37 |
38 | // 3. replace()로 key를 value 치환한다.
39 | result = result.replace("${"+key+"}", (String)map.get(key));
40 | }
41 |
42 | // 4.렌더링 결과를 출력한다.
43 | System.out.println(result);
44 | }
45 | }
46 |
47 | class ModelController {
48 | public String main(HashMap map) {
49 | map.put("id", "asdf");
50 | map.put("pwd", "1111");
51 |
52 | return "txtView2";
53 | }
54 | }
55 |
56 | [txtView1.txt]
57 | id=${id}, pwd=${pwd}
58 |
59 | [txtView2.txt]
60 | id:${id}
61 | pwd:${pwd}
62 |
63 |
64 |
65 | [실행결과]
66 | before:{}
67 | after :{id=asdf, pwd=1111}
68 | [txtView2.txt]
69 | id:asdf
70 | pwd:1111
71 |
72 |
--------------------------------------------------------------------------------
/ch2/MethodCall2.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.lang.reflect.Method;
6 | import java.util.Iterator;
7 | import java.util.Map;
8 | import java.util.Scanner;
9 |
10 | import org.springframework.ui.Model;
11 | import org.springframework.validation.support.BindingAwareModelMap;
12 |
13 | public class MethodCall2 {
14 | public static void main(String[] args) throws Exception{
15 |
16 | Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC");
17 | Object obj = clazz.newInstance();
18 |
19 | Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class);
20 |
21 | Model model = new BindingAwareModelMap();
22 | System.out.println("[before] model="+model);
23 |
24 | // String viewName = obj.main(2021, 10, 1, model);
25 | String viewName = (String)main.invoke(obj, new Object[] { 2021, 10, 1, model });
26 | System.out.println("viewName="+viewName);
27 |
28 | // Model의 내용을 출력
29 | System.out.println("[after] model="+model);
30 |
31 | // 텍스트 파일을 이용한 rendering
32 | render(model, viewName);
33 | } // main
34 |
35 | static void render(Model model, String viewName) throws IOException {
36 | String result = "";
37 |
38 | // 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
39 | Scanner sc = new Scanner(new File("src/main/webapp/WEB-INF/views/"+viewName+".jsp"), "utf-8");
40 |
41 | while(sc.hasNextLine())
42 | result += sc.nextLine()+ System.lineSeparator();
43 |
44 | // 2. model을 map으로 변환
45 | Map map = model.asMap();
46 |
47 | // 3.key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
48 | Iterator it = map.keySet().iterator();
49 |
50 | while(it.hasNext()) {
51 | String key = (String)it.next();
52 |
53 | // 4. replace()로 key를 value 치환한다.
54 | result = result.replace("${"+key+"}", ""+map.get(key));
55 | }
56 |
57 | // 5.렌더링 결과를 출력한다.
58 | System.out.println(result);
59 | }
60 | }
61 |
62 | /* [실행결과]
63 | [before] model={}
64 | viewName=yoil
65 | [after] model={year=2021, month=10, day=1, yoil=금}
66 | <%@ page contentType="text/html;charset=utf-8" %>
67 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
68 | <%@ page session="false" %>
69 |
70 |
71 | YoilTellerMVC
72 |
73 |
74 | 2021년 10월 1일은 금요일입니다.
75 |
76 |
77 |
78 | */
79 |
--------------------------------------------------------------------------------
/ch2/MethodCall3.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.lang.reflect.Method;
6 | import java.lang.reflect.Parameter;
7 | import java.util.Arrays;
8 | import java.util.HashMap;
9 | import java.util.Iterator;
10 | import java.util.Map;
11 | import java.util.Scanner;
12 |
13 | import org.springframework.ui.Model;
14 | import org.springframework.validation.support.BindingAwareModelMap;
15 |
16 | public class MethodCall3 {
17 | public static void main(String[] args) throws Exception{
18 | Map map = new HashMap();
19 | map.put("year", "2021");
20 | map.put("month", "10");
21 | map.put("day", "1");
22 |
23 | Model model = null;
24 | Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC");
25 | Object obj = clazz.newInstance();
26 |
27 | // YoilTellerMVC.main(int year, int month, int day, Model model)
28 | Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class);
29 |
30 | Parameter[] paramArr = main.getParameters();
31 | Object[] argArr = new Object[main.getParameterCount()];
32 |
33 | for(int i=0;i
108 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
109 | <%@ page session="false" %>
110 |
111 |
112 | YoilTellerMVC
113 |
114 |
115 | 2021년 10월 1일은 금요일입니다.
116 |
117 |
118 | */
119 |
--------------------------------------------------------------------------------
/ch2/MethodInfo.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.lang.reflect.Method;
4 | import java.lang.reflect.Parameter;
5 | import java.util.StringJoiner;
6 |
7 | public class MethodInfo {
8 | public static void main(String[] args) throws Exception{
9 |
10 | Class clazz = Class.forName("com.fastcampus.ch2.YoilTeller");
11 | Object obj = clazz.newInstance();
12 |
13 | Method[] methodArr = clazz.getDeclaredMethods();
14 |
15 | for(Method m : methodArr) {
16 | String name = m.getName();
17 | Parameter[] paramArr = m.getParameters();
18 | // Class[] paramTypeArr = m.getParameterTypes();
19 | Class returnType = m.getReturnType();
20 |
21 | StringJoiner paramList = new StringJoiner(", ", "(", ")");
22 |
23 | for(Parameter param : paramArr) {
24 | String paramName = param.getName();
25 | Class paramType = param.getType();
26 |
27 | paramList.add(paramType.getName() + " " + paramName);
28 | }
29 |
30 | System.out.printf("%s %s%s%n", returnType.getName(), name, paramList);
31 | }
32 | } // main
33 | }
34 |
35 | /* [실행결과]
36 | java.lang.String main(java.lang.String year, java.lang.String month, java.lang.String day, org.springframework.ui.Model model)
37 | boolean isValid(int year, int month, int day)
38 | */
39 |
40 |
41 |
--------------------------------------------------------------------------------
/ch2/MyDate.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | public class MyDate {
4 | private int year;
5 | private int month;
6 | private int day;
7 |
8 | public int getYear() {
9 | return year;
10 | }
11 |
12 | public void setYear(int year) {
13 | this.year = year;
14 | }
15 |
16 | public int getMonth() {
17 | return month;
18 | }
19 |
20 | public void setMonth(int month) {
21 | this.month = month;
22 | }
23 |
24 | public int getDay() {
25 | return day;
26 | }
27 |
28 | public void setDay(int day) {
29 | this.day = day;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return String.format("[year=%d, month=%d, day=%d]", year, month, day);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ch2/MyDispatcherServlet.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.PrintWriter;
6 | import java.lang.reflect.Array;
7 | import java.lang.reflect.Method;
8 | import java.lang.reflect.Parameter;
9 | import java.util.Arrays;
10 | import java.util.Iterator;
11 | import java.util.Map;
12 | import java.util.Scanner;
13 |
14 | import javax.servlet.annotation.WebServlet;
15 | import javax.servlet.http.HttpServlet;
16 | import javax.servlet.http.HttpServletRequest;
17 | import javax.servlet.http.HttpServletResponse;
18 |
19 | import org.springframework.ui.Model;
20 | import org.springframework.validation.support.BindingAwareModelMap;
21 |
22 | @WebServlet("/myDispatcherServlet") // http://localhost/ch2/myDispatcherServlet?year=2021&month=10&day=1
23 | public class MyDispatcherServlet extends HttpServlet {
24 | @Override
25 | public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
26 | Map map = request.getParameterMap();
27 | Model model = null;
28 | String viewName = "";
29 |
30 | try {
31 | Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC");
32 | Object obj = clazz.newInstance();
33 |
34 | // 1. main메서드의 정보를 얻는다.
35 | Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class);
36 |
37 | // 2. main메서드의 매개변수 목록(paramArr)을 읽어서 메서드 호출에 사용할 인자 목록(argArr)을 만든다.
38 | Parameter[] paramArr = main.getParameters();
39 | Object[] argArr = new Object[main.getParameterCount()];
40 |
41 | for(int i=0;i int
76 | return Integer.valueOf((String)value);
77 | } else if(String.class.isInstance(value) && type==double.class) { // String -> double
78 | return Double.valueOf((String)value);
79 | }
80 |
81 | return value;
82 | }
83 |
84 | private String getResolvedViewName(String viewName) {
85 | return getServletContext().getRealPath("/WEB-INF/views") +"/"+viewName+".jsp";
86 | }
87 |
88 | private void render(Model model, String viewName, HttpServletResponse response) throws IOException {
89 | String result = "";
90 |
91 | response.setContentType("text/html");
92 | response.setCharacterEncoding("utf-8");
93 | PrintWriter out = response.getWriter();
94 |
95 | // 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
96 | Scanner sc = new Scanner(new File(getResolvedViewName(viewName)), "utf-8");
97 |
98 | while(sc.hasNextLine())
99 | result += sc.nextLine()+ System.lineSeparator();
100 |
101 | // 2. model을 map으로 변환
102 | Map map = model.asMap();
103 |
104 | // 3.key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
105 | Iterator it = map.keySet().iterator();
106 |
107 | while(it.hasNext()) {
108 | String key = (String)it.next();
109 |
110 | // 4. replace()로 key를 value 치환한다.
111 | result = result.replace("${"+key+"}", map.get(key)+"");
112 | }
113 |
114 | // 5.렌더링 결과를 출력한다.
115 | out.println(result);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/ch2/PerformanceFilter.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.Filter;
6 | import javax.servlet.FilterChain;
7 | import javax.servlet.FilterConfig;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.annotation.WebFilter;
12 | import javax.servlet.http.HttpServletRequest;
13 |
14 | // 필터를 적용할 요청의 패턴 지정 - 모든 요청에 필터를 적용.
15 | @WebFilter(urlPatterns="/*")
16 | public class PerformanceFilter implements Filter {
17 | @Override
18 | public void init(FilterConfig filterConfig) throws ServletException {
19 | // 초기화 작업
20 | }
21 |
22 | @Override
23 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
24 | throws IOException, ServletException {
25 | // 1. 전처리 작업
26 | long startTime = System.currentTimeMillis();
27 |
28 | // 2. 서블릿 또는 다음 필터를 호출
29 | chain.doFilter(request, response);
30 |
31 | // 3. 후처리 작업
32 | System.out.print("["+((HttpServletRequest)request).getRequestURI()+"]");
33 | System.out.println(" 소요시간="+(System.currentTimeMillis()-startTime)+"ms");
34 | }
35 |
36 | @Override
37 | public void destroy() {
38 | // 정리 작업
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/ch2/Person.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | public class Person {
4 | private Car car = new Car();
5 | public Car getCar() { return car; }
6 | }
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ch2/PrivateMethodCall.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public class PrivateMethodCall {
6 | public static void main(String[] args) throws Exception{
7 | // Hello hello = new Hello();
8 | // hello.main(); // private이라서 외부 호출 불가
9 |
10 | // Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능제공
11 | // java.lang.reflect패키지를 제공
12 | // Hello클래스의 Class객체(클래스의 정보를 담고 있는 객체)를 얻어온다.
13 | Class helloClass = Class.forName("com.fastcampus.ch2.Hello");
14 | Hello hello = (Hello)helloClass.newInstance(); // Class객체가 가진 정보로 객체 생성
15 | Method main = helloClass.getDeclaredMethod("main");
16 | main.setAccessible(true); // private인 main()을 호출가능하게 한다.
17 |
18 | main.invoke(hello); // hello.main()와 같은 의미. main()이 private인데도 호출성공
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ch2/RegisterController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.ModelAttribute;
6 | import org.springframework.web.bind.annotation.PostMapping;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.servlet.mvc.support.RedirectAttributes;
9 |
10 | @Controller // ctrl+shift+o 자동 임포트
11 | public class RegisterController {
12 | // @RequestMapping(value="/register/add", method=RequestMethod.GET) // 신규회원 가입
13 | @GetMapping("/register/add") // 4.3부터 추가
14 | public String register() {
15 | return "registerForm"; // WEB-INF/views/registerForm.jsp
16 | }
17 |
18 | // @RequestMapping(value="/register/save", method=RequestMethod.POST) // 신규회원 가입
19 | // @PostMapping("/register/save")
20 | @PostMapping("/register/add")
21 | public String save(@ModelAttribute("user") User user, Model m) {
22 | if(!isValid(user)) {
23 | String msg = URLEncoder.encode("id를 잘못입력하셨습니다.", "utf-8");
24 |
25 | m.addAttribute("msg", msg);
26 | return "redirect:/register/add"; // 신규회원 가입화면으로 이동(redirect)
27 | }
28 |
29 | return "registerInfo";
30 | }
31 |
32 | private boolean isValid(User user) {
33 | return false;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/ch2/RequestHeader.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Enumeration;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 |
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 |
10 | @Controller
11 | public class RequestHeader {
12 | @RequestMapping("/requestHeader")
13 | public void main(HttpServletRequest request) {
14 |
15 | Enumeration e = request.getHeaderNames();
16 |
17 | while (e.hasMoreElements()) {
18 | String name = e.nextElement();
19 | System.out.println(name + ":" + request.getHeader(name));
20 | }
21 | }
22 | }
23 |
24 | [실행결과]
25 | host:localhost:8080
26 | connection:keep-alive
27 | sec-ch-ua:"Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
28 | sec-ch-ua-mobile:?0
29 | sec-ch-ua-platform:"macOS"
30 | upgrade-insecure-requests:1
31 | user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
32 | accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
33 | sec-fetch-site:none
34 | sec-fetch-mode:navigate
35 | sec-fetch-user:?1
36 | sec-fetch-dest:document
37 | accept-encoding:gzip, deflate, br
38 | accept-language:ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
39 |
--------------------------------------------------------------------------------
/ch2/RequestInfo.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | import javax.servlet.http.HttpServletRequest;
7 |
8 | @Controller
9 | public class RequestInfo {
10 | @RequestMapping("/requestInfo")
11 | // public static void main(String[] args) {
12 | public void main(HttpServletRequest request) {
13 | System.out.println("request.getCharacterEncoding()="+request.getCharacterEncoding()); // 요청 내용의 인코딩
14 | System.out.println("request.getContentLength()="+request.getContentLength()); // 요청 내용의 길이. 알수 없을 때는 -1
15 | System.out.println("request.getContentType()="+request.getContentType()); // 요청 내용의 타입. 알 수 없을 때는 null
16 |
17 | System.out.println("request.getMethod()="+request.getMethod()); // 요청 방법
18 | System.out.println("request.getProtocol()="+request.getProtocol()); // 프로토콜의 종류와 버젼 HTTP/1.1
19 | System.out.println("request.getScheme()="+request.getScheme()); // 프로토콜
20 |
21 | System.out.println("request.getServerName()="+request.getServerName()); // 서버 이름 또는 ip주소
22 | System.out.println("request.getServerPort()="+request.getServerPort()); // 서버 포트
23 | System.out.println("request.getRequestURL()="+request.getRequestURL()); // 요청 URL
24 | System.out.println("request.getRequestURI()="+request.getRequestURI()); // 요청 URI
25 |
26 | System.out.println("request.getContextPath()="+request.getContextPath()); // context path
27 | System.out.println("request.getServletPath()="+request.getServletPath()); // servlet path
28 | System.out.println("request.getQueryString()="+request.getQueryString()); // 쿼리 스트링
29 |
30 | System.out.println("request.getLocalName()="+request.getLocalName()); // 로컬 이름
31 | System.out.println("request.getLocalPort()="+request.getLocalPort()); // 로컬 포트
32 |
33 | System.out.println("request.getRemoteAddr()="+request.getRemoteAddr()); // 원격 ip주소
34 | System.out.println("request.getRemoteHost()="+request.getRemoteHost()); // 원격 호스트 또는 ip주소
35 | System.out.println("request.getRemotePort()="+request.getRemotePort()); // 원격 포트
36 | }
37 | }
38 |
39 | [실행결과] http://localhost:8080/ch2/requestInfo?year=2021&month=10&day=1
40 | request.getCharacterEncoding()=UTF-8
41 | request.getContentLength()=-1
42 | request.getContentType()=null
43 | request.getMethod()=GET
44 | request.getProtocol()=HTTP/1.1
45 | request.getScheme()=http
46 | request.getServerName()=localhost
47 | request.getServerPort()=8080
48 | request.getRequestURI()=http://localhost:8080/ch2/requestInfo
49 | request.getRequestURI()=/ch2/requestInfo
50 | request.getContextPath()=/ch2
51 | request.getServletPath()=/requestInfo
52 | request.getQueryString()=year=2021&month=10&day=1
53 | request.getLocalName()=localhost
54 | request.getLocalPort()=8080
55 | request.getRemoteAddr()=0:0:0:0:0:0:0:1 <--- AWS에 배포(deploy)한 다음에 실행하면, 실제 ip주소를 확인할 수 있음.
56 | request.getRemoteHost()=0:0:0:0:0:0:0:1 <--- AWS에 배포(deploy)한 다음에 실행하면, 실제 ip주소를 확인할 수 있음.
57 | request.getRemotePort()=54855
58 |
--------------------------------------------------------------------------------
/ch2/RequestMappingTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | @Controller
7 | public class RequestMappingTest {
8 | // @RequestMapping({"/login/hello.do", "/login/hi.do"})
9 | @RequestMapping("/login/hello.do") // http://localhost/ch2/login/hello.do
10 | public void test1(){
11 | System.out.println("urlpattern=/login/hello.do");
12 | }
13 |
14 | @RequestMapping("/login/*") // /login/hello, /login/hi
15 | public void test2(){
16 | System.out.println("urlpattern=/login/*");
17 | }
18 |
19 | @RequestMapping("/login/**/tmp/*.do") // /login/tmp/hello.do, /login/aaa/tmp/hello.do
20 | public void test3(){
21 | System.out.println("urlpattern=/login/**/tmp/*.do");
22 | }
23 |
24 | @RequestMapping("/login/??")
25 | public void test4(){ // /login/hi, /login/my.car
26 | System.out.println("urlpattern=/login/??");
27 | }
28 |
29 | @RequestMapping("*.do") // /hello.do, /hi.do, /login/hi.do
30 | public void test5(){
31 | System.out.println("urlpattern=*.do");
32 | }
33 |
34 | @RequestMapping("/*.???") // /hello.aaa, /abc.txt
35 | public void test6(){
36 | System.out.println("urlpattern=*.???");
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ch2/RequestMessage.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.Enumeration;
6 | import javax.servlet.http.HttpServletRequest;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 |
10 | @Controller
11 | public class RequestMessage {
12 | @RequestMapping("/requestMessage")
13 | public void main(HttpServletRequest request) throws Exception {
14 |
15 | // 1. request line
16 | String requestLine = request.getMethod(); // GET 또는 POST
17 | requestLine += " " + request.getRequestURI(); // /ch2/requestMessage
18 |
19 | String queryString = request.getQueryString(); // year=2021&month=10&day=1
20 | requestLine += queryString == null ? "" : "?"+queryString;
21 | requestLine += " " + request.getProtocol(); // HTTP/1.1
22 | System.out.println(requestLine);
23 |
24 |
25 | // 2. request headers
26 | Enumeration e = request.getHeaderNames();
27 |
28 | while (e.hasMoreElements()) {
29 | String name = e.nextElement();
30 | System.out.println(name + ":" + request.getHeader(name));
31 | }
32 |
33 | // 3. request body - POST일 때만 해당, GET은 body가 없음(CONTENT_LENGTH=0)
34 | final int CONTENT_LENGTH = request.getContentLength();
35 | // System.out.println("content length="+CONTENT_LENGTH);
36 |
37 | if(CONTENT_LENGTH > 0) {
38 | byte[] content = new byte[CONTENT_LENGTH];
39 |
40 | InputStream in = request.getInputStream();
41 | in.read(content, 0, CONTENT_LENGTH);
42 |
43 | System.out.println(); // empty line
44 | System.out.println(new String(content, "utf-8")); // year=2021&month=10&day=1
45 | } // if
46 | } // main
47 | }
48 |
49 |
50 | [실행결과1] - GET 요청
51 | GET /ch2/requestMessage?year=2021&month=10&day=1 HTTP/1.1 <--- 요청 라인(request line)
52 | host:localhost:8080
53 | connection:keep-alive
54 | sec-ch-ua:"Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
55 | sec-ch-ua-mobile:?0
56 | sec-ch-ua-platform:"macOS"
57 | upgrade-insecure-requests:1
58 | user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
59 | accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
60 | sec-fetch-site:none
61 | sec-fetch-mode:navigate
62 | sec-fetch-user:?1
63 | sec-fetch-dest:document
64 | accept-encoding:gzip, deflate, br
65 | accept-language:ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
66 |
67 | [실행결과2] - POST 요청
68 | POST /ch2/requestMessage HTTP/1.1 <--- 요청 라인(request line)
69 | host:localhost:8080
70 | connection:keep-alive
71 | content-length:90
72 | sec-ch-ua:"Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
73 | cache-control:no-cache
74 | content-type:application/x-www-form-urlencoded
75 | sec-ch-ua-mobile:?0
76 | user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
77 | sec-ch-ua-platform:"macOS"
78 | accept:*/*
79 | origin:chrome-extension://coohjcphdfgbiolnekdpbcijmhambjff
80 | sec-fetch-site:none
81 | sec-fetch-mode:cors
82 | sec-fetch-dest:empty
83 | accept-encoding:gzip, deflate, br
84 | accept-language:ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
85 | <--- empty line
86 | year=2021&month=10&day=1 <--- request body
87 |
--------------------------------------------------------------------------------
/ch2/SetterCall.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Method;
5 | import java.util.Arrays;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | import org.springframework.util.StringUtils;
10 |
11 | public class SetterCall {
12 | public static void main(String[] args) throws Exception{
13 | Map map = new HashMap<>();
14 | map.put("year", "2021");
15 | map.put("month", "10");
16 | map.put("day", "1");
17 |
18 | Class> type = Class.forName("com.fastcampus.ch2.MyDate");
19 |
20 | // MyDate인스턴스를 생성하고, map의 값으로 초기화한다.
21 | Object obj = dataBind(map, type);
22 | System.out.println("obj="+obj); // obj=[year=2021, month=10, day=1]
23 | } // main
24 |
25 | private static Object dataBind(Map map, Class> clazz) throws Exception {
26 | // 1. MyDate인스턴스 생성
27 | // Object obj = clazz.newInstance(); // deprecated method
28 | Object obj = clazz.getDeclaredConstructor().newInstance(new Object[0]);
29 |
30 | // 2. MyDate인스턴스의 setter를 호출해서, map의 값으로 MyDate를 초기화
31 | // 2-1. MyDate의 모든 iv를 돌면서 map에 있는지 찾는다.
32 | // 2-2. 찾으면, 찾은 값을 setter로 객체에 저장한다.
33 | Field[] ivArr = clazz.getDeclaredFields();
34 |
35 | for(int i=0;i type = ivArr[i].getType();
38 |
39 | // map에 같은 이름의 key가 있으면 가져와서 setter호출
40 | Object value = map.get(name); // 못찾으면 value의 값은 null
41 | Method method = null;
42 |
43 | try { // map에 iv와 일치하는 키가 있을 때만, setter를 호출
44 | if(value==null) continue;
45 |
46 | method = clazz.getDeclaredMethod(getSetterName(name), type); // setter의 정보 얻기
47 | System.out.println("method="+method);
48 | method.invoke(obj, convertTo(value, type)); // obj의 setter를 호출
49 | } catch(Exception e) {
50 | e.printStackTrace();
51 | }
52 | }
53 |
54 | System.out.println(Arrays.toString(ivArr));
55 |
56 | return obj;
57 | }
58 |
59 | private static Object convertTo(Object value, Class> type) {
60 | // value의 타입과 type의 타입이 같으면 그대로 반환
61 | if(value==null || type==null || type.isInstance(value))
62 | return value;
63 |
64 | // value의 타입과 type이 다르면, 변환해서 반환
65 | if(String.class.isInstance(value) && type==int.class) // String -> int
66 | return Integer.valueOf(""+value);
67 |
68 | return value;
69 | }
70 |
71 | // iv의 이름으로 setter의 이름을 만들어서 반환하는 메서드("day" -> "setDay")
72 | private static String getSetterName(String name) {
73 | // return "set"+name.substring(0,1).toUpperCase()+name.substring(1);
74 | return "set" + StringUtils.capitalize(name); // org.springframework.util.StringUtils
75 | }
76 | }
77 |
78 | /*
79 | [실행결과]
80 | method=public void com.fastcampus.ch2.MyDate.setYear(int)
81 | method=public void com.fastcampus.ch2.MyDate.setMonth(int)
82 | method=public void com.fastcampus.ch2.MyDate.setDay(int)
83 | [private int com.fastcampus.ch2.MyDate.year, private int com.fastcampus.ch2.MyDate.month, private int com.fastcampus.ch2.MyDate.day]
84 | obj=[year=2021, month=10, day=1]
85 | */
86 |
--------------------------------------------------------------------------------
/ch2/TwoDice.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 | import java.io.PrintWriter;
9 |
10 | @Controller
11 | public class TwoDice {
12 | @RequestMapping("/rollDice")
13 | // public static void main(String[] args) {
14 | public void main(HttpServletResponse response) throws IOException {
15 | int idx1 = (int)(Math.random()*6)+1;
16 | int idx2 = (int)(Math.random()*6)+1;
17 |
18 | response.setContentType("text/html");
19 | response.setCharacterEncoding("utf-8");
20 | PrintWriter out = response.getWriter();
21 | out.println("");
22 | out.println("");
23 | out.println("");
24 | out.println("");
25 | out.println("
");
26 | out.println("
");
27 | out.println("");
28 | out.println("");
29 | out.close();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ch2/TwoDiceServlet.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 | import java.util.Random;
6 |
7 | import javax.servlet.annotation.WebServlet;
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 |
12 | @WebServlet("/rollDice2")
13 | public class TwoDiceServlet extends HttpServlet {
14 | int getRandomInt(int range) {
15 | return new Random().nextInt(range)+1;
16 | }
17 |
18 | public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
19 | int idx1 = getRandomInt(6);
20 | int idx2 = getRandomInt(6);
21 |
22 | response.setContentType("text/html");
23 | response.setCharacterEncoding("utf-8");
24 | PrintWriter out = response.getWriter();
25 | out.println("");
26 | out.println("");
27 | out.println("");
28 | out.println("");
29 | out.println("
");
30 | out.println("
");
31 | out.println("");
32 | out.println("");
33 | out.close();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ch2/User.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Arrays;
4 |
5 | public class User {
6 | private String id;
7 | private String pwd;
8 | private String name;
9 | private String email;
10 | private String birth;
11 | private String[] sns;
12 |
13 | public String getId() {
14 | return id;
15 | }
16 | public void setId(String id) {
17 | this.id = id;
18 | }
19 | public String getPwd() {
20 | return pwd;
21 | }
22 | public void setPwd(String pwd) {
23 | this.pwd = pwd;
24 | }
25 | public String getName() {
26 | return name;
27 | }
28 | public void setName(String name) {
29 | this.name = name;
30 | }
31 | public String getEmail() {
32 | return email;
33 | }
34 | public void setEmail(String email) {
35 | this.email = email;
36 | }
37 | public String getBirth() {
38 | return birth;
39 | }
40 | public void setBirth(String birth) {
41 | this.birth = birth;
42 | }
43 | public String[] getSns() {
44 | return sns;
45 | }
46 | public void setSns(String[] sns) {
47 | this.sns = sns;
48 | }
49 | @Override
50 | public String toString() {
51 | return "User [id=" + id + ", pwd=" + pwd + ", name=" + name + ", email=" + email + ", birth=" + birth + ", sns="
52 | + Arrays.toString(sns) + "]";
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ch2/UserValidator.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.validation.Errors;
4 | import org.springframework.validation.ValidationUtils;
5 | import org.springframework.validation.Validator;
6 |
7 |
8 | public class UserValidator implements Validator {
9 | @Override
10 | public boolean supports(Class> clazz) {
11 | // return User.class.equals(clazz); // 검증하려는 객체가 User타입인지 확인
12 | return User.class.isAssignableFrom(clazz); // clazz가 User 또는 그 자손인지 확인
13 | }
14 |
15 | @Override
16 | public void validate(Object target, Errors errors) {
17 | System.out.println("LocalValidator.validate() is called");
18 |
19 | User user = (User)target;
20 |
21 | String id = user.getId();
22 |
23 | // if(id==null || "".equals(id.trim())) {
24 | // errors.rejectValue("id", "required");
25 | // }
26 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "required");
27 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "pwd", "required");
28 |
29 | if(id==null || id.length() < 5 || id.length() > 12) {
30 | errors.rejectValue("id", "invalidLength");
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/ch2/YoilTeller.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 |
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import java.io.IOException;
9 | import java.io.PrintWriter;
10 | import java.util.Calendar;
11 |
12 | @Controller
13 | public class YoilTeller {
14 | @RequestMapping("/getYoil") // http://localhost:8080/ch2/getYoil?year=2021&month=10&day=1
15 | // public static void main(String[] args) {
16 | public void main(HttpServletRequest request, HttpServletResponse response) throws IOException {
17 | // 1. 입력
18 | // String year = args[0];
19 | // String month = args[1];
20 | // String day = args[2];
21 | String year = request.getParameter("year");
22 | String month = request.getParameter("month");
23 | String day = request.getParameter("day");
24 |
25 | int yyyy = Integer.parseInt(year);
26 | int mm = Integer.parseInt(month);
27 | int dd = Integer.parseInt(day);
28 |
29 | // 2. 처리
30 | Calendar cal = Calendar.getInstance();
31 | cal.set(yyyy, mm - 1, dd);
32 |
33 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
34 | char yoil = " 일월화수목금토".charAt(dayOfWeek); // 일요일:1, 월요일:2, ...
35 |
36 | // 3. 출력
37 | // System.out.println(year + "년 " + month + "월 " + day + "일은 ");
38 | // System.out.println(yoil + "요일입니다.");
39 | response.setContentType("text/html"); // 응답의 형식을 html로 지정
40 | response.setCharacterEncoding("utf-8"); // 응답의 인코딩을 utf-8로 지정
41 | PrintWriter out = response.getWriter(); // 브라우저로의 출력 스트림(out)을 얻는다.
42 | out.println("");
43 | out.println("");
44 | out.println("");
45 | out.println("");
46 | out.println(year + "년 " + month + "월 " + day + "일은 ");
47 | out.println(yoil + "요일입니다.");
48 | out.println("");
49 | out.println("");
50 | out.close();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.ui.Model;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 |
10 | @Controller
11 | public class YoilTellerMVC {
12 | @RequestMapping("/getYoilMVC") // http://localhost/ch2/getYoilMVC
13 | public String main(int year, int month, int day, Model model) {
14 |
15 | // 1. 유효성 검사
16 | if(!isValid(year, month, day))
17 | return "yoilError"; // 유효하지 않으면, /WEB-INF/views/yoilError.jsp로 이동
18 |
19 | // 2. 처리
20 | char yoil = getYoil(year, month, day);
21 |
22 | // 3. Model에 작업 결과 저장
23 | model.addAttribute("year", year);
24 | model.addAttribute("month", month);
25 | model.addAttribute("day", day);
26 | model.addAttribute("yoil", yoil);
27 |
28 | // 4. 작업 결과를 보여줄 View의 이름을 반환
29 | return "yoil"; // /WEB-INF/views/yoil.jsp
30 | }
31 |
32 | private char getYoil(int year, int month, int day) {
33 | Calendar cal = Calendar.getInstance();
34 | cal.set(year, month - 1, day);
35 |
36 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
37 | return " 일월화수목금토".charAt(dayOfWeek);
38 | }
39 |
40 | private boolean isValid(int year, int month, int day) {
41 | if(year==-1 || month==-1 || day==-1)
42 | return false;
43 |
44 | return (1<=month && month<=12) && (1<=day && day<=31); // 간단히 체크
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC2.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.ui.Model;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RequestParam;
10 |
11 | @Controller
12 | public class YoilTellerMVC2 {
13 | @ExceptionHandler(Exception.class)
14 | public String catcher(Exception ex) {
15 | return "yoilError";
16 | }
17 |
18 | @RequestMapping("/getYoilMVC2") // http://localhost/ch2/getYoilMVC2
19 | public String main(@RequestParam(required=true) int year,
20 | @RequestParam(required=true) int month,
21 | @RequestParam(required=true) int day, Model model) {
22 |
23 | // 1. 유효성 검사
24 | if(!isValid(year, month, day))
25 | return "yoilError"; // 유효하지 않으면, /WEB-INF/views/yoilError.jsp로 이동
26 |
27 | // 2. 처리
28 | char yoil = getYoil(year, month, day);
29 |
30 | // 3. Model에 작업 결과 저장
31 | model.addAttribute("year", year);
32 | model.addAttribute("month", month);
33 | model.addAttribute("day", day);
34 | model.addAttribute("yoil", yoil);
35 |
36 | // 4. 작업 결과를 보여줄 View의 이름을 반환
37 | return "yoil"; // /WEB-INF/views/yoil.jsp
38 | }
39 |
40 | private char getYoil(int year, int month, int day) {
41 | Calendar cal = Calendar.getInstance();
42 | cal.set(year, month - 1, day);
43 |
44 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
45 | return " 일월화수목금토".charAt(dayOfWeek);
46 | }
47 |
48 | private boolean isValid(int year, int month, int day) {
49 | if(year==-1 || month==-1 || day==-1)
50 | return false;
51 |
52 | return (1<=month && month<=12) && (1<=day && day<=31); // 간단히 체크
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC3.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestParam;
8 | import org.springframework.web.servlet.ModelAndView;
9 |
10 | @Controller
11 | public class YoilTellerMVC3 {
12 | @RequestMapping("/getYoilMVC3") // http://localhost/ch2/getYoilMVC3
13 | public ModelAndView main( // 반환 타입이 ModelAndView
14 | @RequestParam(defaultValue="-1") int year,
15 | @RequestParam(defaultValue="-1") int month,
16 | @RequestParam(defaultValue="-1") int day
17 | ) {
18 |
19 | // 1. ModelAndView를 생성
20 | ModelAndView mv = new ModelAndView();
21 |
22 | // 2. 유효성 검사
23 | if(!isValid(year, month, day)) {
24 | mv.setViewName("yoilError"); // View의 이름을 지정
25 | return mv;
26 | }
27 |
28 | // 3. 처리
29 | char yoil = getYoil(year, month, day);
30 |
31 | // 4. ModelAndView에 작업한 결과를 저장
32 | mv.addObject("year", year);
33 | mv.addObject("month", month);
34 | mv.addObject("day", day);
35 | mv.addObject("yoil", yoil);
36 |
37 | // 5. 작업 결과를 보여줄 View의 이름을 지정
38 | mv.setViewName("yoil");
39 |
40 | // 6. ModelAndView를 반환
41 | return mv;
42 | }
43 |
44 | private char getYoil(int year, int month, int day) {
45 | Calendar cal = Calendar.getInstance();
46 | cal.set(year, month - 1, day);
47 |
48 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
49 | return " 일월화수목금토".charAt(dayOfWeek);
50 | }
51 |
52 | private boolean isValid(int year, int month, int day) {
53 | if(year==-1 || month==-1 || day==-1)
54 | return false;
55 |
56 | return (1<=month && month<=12) && (1<=day && day<=31); // 간단히 체크
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC4.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestParam;
8 | import org.springframework.web.servlet.ModelAndView;
9 |
10 | @Controller
11 | public class YoilTellerMVC4 {
12 | @RequestMapping("/getYoilMVC4") // http://localhost/ch2/getYoilMVC4?year=2021&month=10&day=1
13 | public ModelAndView main(MyDate date) { // 반환 타입이 ModelAndView
14 | System.out.println("date="+date);
15 |
16 | // 1. ModelAndView를 생성
17 | ModelAndView mv = new ModelAndView();
18 |
19 | // 2. 유효성 검사
20 | if(!isValid(date)) {
21 | mv.setViewName("yoilError"); // 뷰의 이름을 지정
22 | return mv;
23 | }
24 |
25 | // 3. 처리
26 | char yoil = getYoil(date);
27 |
28 | // 4. ModelAndView에 작업한 결과를 저장
29 | //mv.addObject("year", date.getYear());
30 | //mv.addObject("month", date.getMonth());
31 | //mv.addObject("day", date.getDay());
32 | mv.addObject("myDate", date);
33 | mv.addObject("yoil", yoil);
34 |
35 | // 5. 작업 결과를 보여줄 뷰의 이름을 지정
36 | mv.setViewName("yoil");
37 |
38 | // 6. ModelAndView를 반환
39 | return mv;
40 | }
41 |
42 | private char getYoil(MyDate date) {
43 | return getYoil(date.getYear(), date.getMonth(), date.getDay());
44 | }
45 |
46 | private char getYoil(int year, int month, int day) {
47 | Calendar cal = Calendar.getInstance();
48 | cal.set(year, month - 1, day);
49 |
50 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
51 | return " 일월화수목금토".charAt(dayOfWeek);
52 | }
53 |
54 | private boolean isValid(MyDate date) {
55 | return isValid(date.getYear(), date.getMonth(), date.getDay());
56 | }
57 |
58 | private boolean isValid(int year, int month, int day) {
59 | if(year==-1 || month==-1 || day==-1)
60 | return false;
61 |
62 | return (1<=month && month<=12) && (1<=day && day<=31); // 간단히 체크
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC5.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.ui.Model;
7 | import org.springframework.web.bind.annotation.ModelAttribute;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 |
10 | @Controller
11 | public class YoilTellerMVC5 {
12 | @ExceptionHandler(Exception.class)
13 | public String catcher(Exception ex) {
14 | System.out.println("ex="+ex);
15 |
16 | return "yoilError";
17 | }
18 |
19 | @RequestMapping("/getYoilMVC5") // http://localhost/ch2/getYoilMVC5?year=2021&month=10&day=1
20 | // public String main(@ModelAttribute("myDate") MyDate date, Model m) { // 아래와 동일
21 | public String main(@ModelAttribute MyDate date, Model m) { // @ModelAttribute사용, 반환 타입은 String
22 | System.out.println("myDate="+date);
23 |
24 | // 1. 유효성 검사
25 | if(!isValid(date))
26 | return "yoilError";
27 |
28 | // 2. 처리
29 | char yoil = getYoil(date);
30 |
31 | // 3. Model에 작업한 결과를 저장
32 | // @ModelAttribute 덕분에 MyDate를 저장안해도 됨. View로 자동 전달됨.
33 | // m.addAttribute("myDate", date);
34 | // m.addAttribute("yoil", yoil);
35 |
36 | // 4. 작업 결과를 보여줄 뷰의 이름을 반환
37 | return "yoil";
38 | }
39 |
40 | private @ModelAttribute("yoil") char getYoil(MyDate date) {
41 | return getYoil(date.getYear(), date.getMonth(), date.getDay());
42 | }
43 |
44 | private char getYoil(int year, int month, int day) {
45 | Calendar cal = Calendar.getInstance();
46 | cal.set(year, month - 1, day);
47 |
48 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
49 | return " 일월화수목금토".charAt(dayOfWeek);
50 | }
51 |
52 | private boolean isValid(MyDate date) {
53 | return isValid(date.getYear(), date.getMonth(), date.getDay());
54 | }
55 |
56 | private boolean isValid(int year, int month, int day) {
57 | if(year==-1 || month==-1 || day==-1)
58 | return false;
59 |
60 | return (1<=month && month<=12) && (1<=day && day<=31); // 간단히 체크
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ch2/YoilTellerMVC6.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.util.Calendar;
4 |
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.ui.Model;
7 | import org.springframework.validation.BindingResult;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.ModelAttribute;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RequestParam;
12 |
13 | @Controller
14 | public class YoilTellerMVC6 {
15 | @ExceptionHandler(Exception.class)
16 | public String catcher(Exception ex, BindingResult result) {
17 | System.out.println("result="+result);
18 | System.out.println("error="+result.getFieldError());
19 |
20 | return "yoilError";
21 | }
22 |
23 | @RequestMapping("/getYoilMVC6") // http://localhost/ch2/getYoilMVC6
24 | // public String main(@ModelAttribute("myDate") MyDate date, Model model) {
25 | public String main(MyDate date, BindingResult result) {
26 | System.out.println("result="+result);
27 | // 1. 유효성 검사
28 | if(!isValid(date))
29 | return "yoilError"; // 유효하지 않으면, /WEB-INF/views/yoilError.jsp로 이동
30 |
31 | // 2. 처리
32 | // char yoil = getYoil(date);
33 |
34 | // 3. Model에 작업 결과 저장
35 | // model.addAttribute("myDate", date);
36 | // model.addAttribute("yoil", yoil);
37 |
38 | // 4. 작업 결과를 보여줄 View의 이름을 반환
39 | return "yoil"; // /WEB-INF/views/yoil.jsp
40 | }
41 |
42 |
43 | private @ModelAttribute("yoil") char getYoil(MyDate date) {
44 | return getYoil(date.getYear(), date.getMonth(), date.getDay());
45 | }
46 |
47 | private char getYoil(int year, int month, int day) {
48 | Calendar cal = Calendar.getInstance();
49 | cal.set(year, month - 1, day);
50 |
51 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
52 | return " 일월화수목금토".charAt(dayOfWeek);
53 | }
54 |
55 | private boolean isValid(MyDate date) {
56 | if(date.getYear()==-1 || date.getMonth()==-1 || date.getDay()==-1)
57 | return false;
58 |
59 | return (1<=date.getMonth() && date.getMonth()<=12) && (1<=date.getDay() && date.getDay()<=31); // 간단히 체크
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/ch2/YoilTellerServlet.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch2;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 | import java.util.Calendar;
6 |
7 | import javax.servlet.annotation.WebServlet;
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 |
12 | @WebServlet("/getYoil2")
13 | public class YoilTellerServlet extends HttpServlet {
14 | @Override
15 | public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
16 | // 1. 입력
17 | String year = request.getParameter("year");
18 | String month = request.getParameter("month");
19 | String day = request.getParameter("day");
20 |
21 | int yyyy = Integer.parseInt(year);
22 | int mm = Integer.parseInt(month);
23 | int dd = Integer.parseInt(day);
24 |
25 | // 2. 처리
26 | Calendar cal = Calendar.getInstance();
27 | cal.set(yyyy, mm - 1, dd);
28 |
29 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
30 | char yoil = " 일월화수목금토".charAt(dayOfWeek);
31 |
32 | // 3. 출력
33 | response.setContentType("text/html"); // 응답의 형식을 html로 지정
34 | response.setCharacterEncoding("utf-8"); // 응답의 인코딩을 utf-8로 지정
35 |
36 | PrintWriter out = response.getWriter(); // 브라우저로의 출력 스트림(out)을 얻는다.
37 | out.println("");
38 | out.println("");
39 | out.println("");
40 | out.println("");
41 | out.println(year + "년 " + month + "월 " + day + "일은 ");
42 | out.println(yoil + "요일입니다.");
43 | out.println("");
44 | out.println("");
45 | out.println("");
46 | out.close();
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/ch2/boardList.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 |
4 |
5 |
6 |
7 |
8 | fastcampus
9 |
10 |
11 |
12 |
22 |
This is BOARD
23 | This is BOARD
24 | This is BOARD
25 | This is BOARD
26 | This is BOARD
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ch2/dice.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch2/dice.zip
--------------------------------------------------------------------------------
/ch2/el.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
3 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
4 | <%@ page import="com.fastcampus.ch2.*" %>
5 | <%
6 | Person person = new Person();
7 | request.setAttribute("person", person);
8 | request.setAttribute("name", "남궁성");
9 | request.setAttribute("list", new java.util.ArrayList());
10 | %>
11 |
12 |
13 | EL
14 |
15 |
16 | person.getCar().getColor()=<%=person.getCar().getColor()%>
17 | person.getCar().getColor()=${person.getCar().getColor()}
18 | person.getCar().getColor()=${person.car.color}
19 | name=<%=request.getAttribute("name")%>
20 | name=${requestScope.name}
21 | name=${name}
22 | id=<%=request.getParameter("id")%>
23 | id=${pageContext.request.getParameter("id")}
24 | id=${param.id}
25 | "1"+1 = ${"1"+1}
26 | "1"+="1" = ${"1"+="1"}
27 | "2">1 = ${"2">1}
28 | null = ${null}
29 | null+1 = ${null+1}
30 | null+null = ${null+null}
31 | "" + null = ${""+null}
32 | ""-1 = ${""-1}
33 | empty null=${empty null}
34 | empty list=${empty list}
35 | null==0 = ${null==0}
36 | null eq 0 = ${null eq 0}
37 | name == "남궁성"=${name=="남궁성"}
38 | name != "남궁성"=${name!="남궁성"}
39 | name eq "남궁성"=${name eq "남궁성"}
40 | name ne "남궁성"=${name ne "남궁성"}
41 | name.equals("남궁성")=${name.equals("남궁성")}
42 |
43 |
44 |
45 | [실행결과]
46 | person.getCar().getColor()=red
47 | person.getCar().getColor()=red
48 | person.car.color=red
49 | name=남궁성
50 | name=남궁성
51 | name=남궁성
52 | id=asdf
53 | id=asdf
54 | id=asdf
55 | "1"+1 = 2
56 | "1"+="1" = 11
57 | "2">1 = true
58 | null =
59 | null+1 = 1
60 | null+null = 0
61 | "" + null = 0
62 | ""-1 = -1
63 | empty null=true
64 | empty list=true
65 | null==0 = false
66 | null eq 0 = false
67 | name == "남궁성"=true
68 | name != "남궁성"=false
69 | name eq "남궁성"=true
70 | name ne "남궁성"=false
71 | name.equals("남궁성")=true
72 |
--------------------------------------------------------------------------------
/ch2/error.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 |
4 |
5 | error.jsp
6 |
7 |
8 | 예외가 발생했습니다.
9 | 발생한 예외 : ${ex}
10 | 예외 메시지 : ${ex.message}
11 |
12 |
13 | - ${i.toString()}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ch2/error_message.properties:
--------------------------------------------------------------------------------
1 | required=필수 항목 입니다.
2 | required.user.pwd=사용자 비밀번호는 필수 항목입니다.
3 | invalidLength.id=아이디의 길이는 {0}~{1}사이어야 합니다.
4 |
--------------------------------------------------------------------------------
/ch2/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 |
4 |
5 |
6 |
7 | fastcampus
8 |
9 |
10 |
11 |
12 |
22 |
23 |
This is HOME
24 | This is HOME
25 | This is HOME
26 |
27 |
--------------------------------------------------------------------------------
/ch2/jstl.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
3 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
4 |
5 |
6 | JSTL
7 |
8 |
9 |
10 |
11 |
12 | ${i}
13 |
14 |
15 |
16 |
17 | ${status.count}. arr[${status.index}]=${elem}
18 |
19 |
20 |
21 | msg=${param.msg}
22 | msg=
23 |
24 |
25 | 메시지가 없습니다.
26 |
27 |
28 | 성인입니다.
29 | 성인이 아닙니다.
30 | 값이 유효하지 않습니다.
31 |
32 |
33 |
34 | Server time is
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/ch2/loginForm.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page import="java.net.URLDecoder" %>
4 |
5 |
6 |
7 |
8 |
9 |
10 | Login
11 |
12 |
58 |
59 |
60 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/ch2/menu.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin : 0;
4 | padding: 0;
5 | }
6 |
7 | a { text-decoration: none; }
8 |
9 | ul {
10 | list-style-type: none;
11 | height: 48px;
12 | width: 100%;
13 | background-color: #30426E;
14 | display: flex;
15 | }
16 |
17 | ul > li {
18 | color: lightgray;
19 | height : 100%;
20 | width:90px;
21 | display:flex;
22 | align-items: center;
23 | }
24 |
25 | ul > li > a {
26 | color: lightgray;
27 | margin:auto;
28 | padding: 10px;
29 | font-size:20px;
30 | align-items: center;
31 | }
32 |
33 | ul > li > a:hover {
34 | color :white;
35 | border-bottom: 3px solid rgb(209, 209, 209);
36 | }
37 |
38 | #logo {
39 | color:white;
40 | font-size: 18px;
41 | padding-left:40px;
42 | margin-right:auto;
43 | display: flex;
44 | }
45 |
--------------------------------------------------------------------------------
/ch2/registerForm.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
66 | Register
67 |
68 |
69 |
89 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/ch2/registerForm.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8" %>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page import="java.net.URLDecoder"%>
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
70 | Register
71 |
72 |
73 | " method="post" onsubmit="return formCheck(this)">
74 | Register
75 |
76 |
77 | ${URLDecoder.decode(param.msg)}
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/ch2/registerInfo.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | id=${param.id}
11 | pwd=${param.pwd}
12 | name=${param.name}
13 | email=${param.email}
14 | birth=${param.birth}
15 | sns=${param.sns}
16 |
17 |
18 |
--------------------------------------------------------------------------------
/ch2/servlet-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | error400
32 |
33 |
34 |
35 |
36 | 400
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | error_message
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ch2/twoDice.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ page import="java.util.Random" %>
3 | <%-- <%! 클래스 영역 %> --%>
4 | <%!
5 | int getRandomInt(int range){
6 | return new Random().nextInt(range)+1;
7 | }
8 | %>
9 | <%-- <% 메서드 영역 - service()의 내부 %> --%>
10 | <%
11 | int idx1 = getRandomInt(6);
12 | int idx2 = getRandomInt(6);
13 | %>
14 |
15 |
16 | twoDice.jsp
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ch2/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | contextConfigLocation
9 | /WEB-INF/spring/root-context.xml
10 |
11 |
12 |
13 |
14 | org.springframework.web.context.ContextLoaderListener
15 |
16 |
17 |
18 |
19 | appServlet
20 | org.springframework.web.servlet.DispatcherServlet
21 |
22 | contextConfigLocation
23 | /WEB-INF/spring/appServlet/servlet-context.xml
24 |
25 |
26 | listings
27 | true
28 |
29 | 1
30 |
31 |
32 |
33 | appServlet
34 | /
35 |
36 |
37 |
38 |
39 | encodingFilter
40 | org.springframework.web.filter.CharacterEncodingFilter
41 |
42 | encoding
43 | UTF-8
44 |
45 |
46 | forceEncoding
47 | true
48 |
49 |
50 |
51 |
52 | encodingFilter
53 | /*
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/ch2/yoil.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8" %>
2 |
3 |
4 | YoilTellerMVC
5 |
6 |
7 | ${year}년 ${month}월 ${day}일은 ${yoil}요일입니다.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ch2/yoilError.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8" %>
2 |
3 |
4 | YoilTellerMVC
5 |
6 |
7 | 잘못된 요청입니다. 다시 요청해 주세요.
8 | year, month, day를 모두 올바른 값으로 입력하셔야합니다.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ch2/yoilTeller.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ page import="java.util.Calendar" %>
3 | <%
4 | String year = request.getParameter("year");
5 | String month = request.getParameter("month");
6 | String day = request.getParameter("day");
7 |
8 | int yyyy = Integer.parseInt(year);
9 | int mm = Integer.parseInt(month);
10 | int dd = Integer.parseInt(day);
11 |
12 | // 2. 처리
13 | Calendar cal = Calendar.getInstance();
14 | cal.set(yyyy, mm - 1, dd);
15 |
16 | int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
17 | char yoil = " 일월화수목금토".charAt(dayOfWeek);
18 |
19 | // 3. 출력
20 | %>
21 |
22 |
23 | yoilTeller.jsp
24 |
25 |
26 | <%=yyyy%>년 <%=mm%>월 <%=dd%>일은 <%=yoil%>요일입니다.
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ch3/AopMain.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3.aop;
2 |
3 | import org.springframework.transaction.annotation.Transactional;
4 |
5 | import java.lang.reflect.Method;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | public class AopMain {
10 | public static void main(String[] args) throws Exception {
11 | MyAdvice myAdvice = new MyAdvice();
12 |
13 | Class myClass = Class.forName("com.fastcampus.ch3.aop.MyClass");
14 | Object obj = myClass.newInstance();
15 |
16 | for(Method m : myClass.getDeclaredMethods()) {
17 | myAdvice.invoke(m, obj, null);
18 | }
19 | }
20 | }
21 |
22 | class MyAdvice {
23 | Pattern p = Pattern.compile("a.*");
24 |
25 | boolean matches(Method m){
26 | Matcher matcher = p.matcher(m.getName());
27 | return matcher.matches();
28 | }
29 |
30 | void invoke(Method m, Object obj, Object... args) throws Exception {
31 | if(m.getAnnotation(Transactional.class)!=null)
32 | System.out.println("[before]{");
33 |
34 | m.invoke(obj, args); // aaa(), aaa2(), bbb() 호출가능
35 |
36 | if(m.getAnnotation(Transactional.class)!=null)
37 | System.out.println("}[after]");
38 | }
39 | }
40 |
41 | class MyClass {
42 | @Transactional
43 | void aaa() {
44 | System.out.println("aaa() is called.");
45 | }
46 | void aaa2() {
47 | System.out.println("aaa2() is called.");
48 | }
49 | void bbb() {
50 | System.out.println("bbb() is called.");
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/ch3/DBConnectionTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import java.sql.*;
4 |
5 | public class DBConnectionTest {
6 | public static void main(String[] args) throws Exception {
7 | // 스키마의 이름(springbasic)이 다른 경우 알맞게 변경해야 함
8 | String DB_URL = "jdbc:mysql://localhost:3306/springbasic?useUnicode=true&characterEncoding=utf8";
9 |
10 | // DB의 userid와 pwd를 알맞게 변경해야 함
11 | String DB_USER = "asdf";
12 | String DB_PASSWORD = "1234";
13 |
14 | Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); // 데이터베이스의 연결을 얻는다.
15 | Statement stmt = conn.createStatement(); // Statement를 생성한다.
16 |
17 | String query = "SELECT now()"; // 시스템의 현재 날짜시간을 출력하는 쿼리(query)
18 | ResultSet rs = stmt.executeQuery(query); // query를 실행한 결과를 rs에 담는다.
19 |
20 | // 실행결과가 담긴 rs에서 한 줄씩 읽어서 출력
21 | while (rs.next()) {
22 | String curDate = rs.getString(1); // 읽어온 행의 첫번째 컬럼의 값을 String으로 읽어서 curDate에 저장
23 | System.out.println(curDate); // 2022-01-11 13:53:00.0
24 | }
25 | } // main()
26 | }
27 |
28 | /* [실행결과]
29 | 2022-01-11 13:53:00.0
30 | */
31 |
--------------------------------------------------------------------------------
/ch3/DBConnectionTest2.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import org.junit.*;
4 | import org.springframework.context.*;
5 | import org.springframework.context.support.*;
6 | import org.springframework.jdbc.datasource.*;
7 |
8 | import javax.sql.*;
9 | import java.sql.*;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | public class DBConnectionTest2 {
14 | @Test
15 | public void jdbcConnectionTest() throws Exception {
16 | // // 스키마의 이름(springbasic)이 다른 경우 알맞게 변경
17 | // String DB_URL = "jdbc:mysql://localhost:3306/springbasic?useUnicode=true&characterEncoding=utf8";
18 | //
19 | // // DB의 userid와 pwd를 알맞게 변경
20 | // String DB_USER = "asdf";
21 | // String DB_PASSWORD = "1234";
22 | // String DB_DRIVER = "com.mysql.jdbc.Driver";
23 | //
24 | // DriverManagerDataSource ds = new DriverManagerDataSource();
25 | // ds.setDriverClassName(DB_DRIVER);
26 | // ds.setUrl(DB_URL);
27 | // ds.setUsername(DB_USER);
28 | // ds.setPassword(DB_PASSWORD);
29 |
30 | ApplicationContext ac = new GenericXmlApplicationContext("file:src/main/webapp/WEB-INF/spring/**/root-context.xml");
31 | DataSource ds = ac.getBean(DataSource.class);
32 |
33 | Connection conn = ds.getConnection(); // 데이터베이스의 연결을 얻는다.
34 |
35 | System.out.println("conn = " + conn);
36 | assertTrue(conn!=null);
37 | }
38 | }
39 |
40 | /* [root-context.xml]
41 |
42 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | */
55 |
--------------------------------------------------------------------------------
/ch3/DBConnectionTest3.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import org.junit.*;
4 | import org.junit.runner.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.context.*;
7 | import org.springframework.context.support.*;
8 | import org.springframework.jdbc.datasource.*;
9 | import org.springframework.test.context.*;
10 | import org.springframework.test.context.junit4.*;
11 |
12 | import javax.sql.*;
13 | import java.sql.*;
14 |
15 | import static org.junit.Assert.*;
16 |
17 | @RunWith(SpringJUnit4ClassRunner.class)
18 | @ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
19 | public class DBConnectionTest3 {
20 | @Autowired
21 | DataSource ds; // 컨테이너로부터 자동 주입받는다.
22 |
23 | @Test
24 | public void jdbcConnectionTest() throws Exception {
25 | // ApplicationContext ac = new GenericXmlApplicationContext("file:src/main/webapp/WEB-INF/spring/**/root-context.xml");
26 | // DataSource ds = ac.getBean(DataSource.class);
27 |
28 | Connection conn = ds.getConnection(); // 데이터베이스의 연결을 얻는다.
29 |
30 | System.out.println("conn = " + conn);
31 | assertTrue(conn!=null);
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/ch3/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import java.util.*;
4 |
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.context.*;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.ui.Model;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestMethod;
11 | import org.springframework.web.context.*;
12 | import org.springframework.web.context.support.*;
13 |
14 | import javax.servlet.*;
15 | import javax.servlet.http.*;
16 |
17 | @Controller
18 | public class HomeController {
19 | @Autowired
20 | WebApplicationContext servletAC; // Servlet AC
21 |
22 | @RequestMapping(value = "/", method = RequestMethod.GET)
23 | public String home(Locale locale, HttpServletRequest request, Model model) {
24 | // 원래는 request.getServletContext()지만, 컨트롤러는 HttpServlet을 상속받지 않아서 아래와 같이 해야함.
25 | ServletContext sc = request.getSession().getServletContext(); // ApplicationContextFacade
26 | WebApplicationContext rootAC = WebApplicationContextUtils.getWebApplicationContext(sc); // Root AC
27 |
28 | System.out.println("webApplicationContext = " + rootAC);
29 | System.out.println("servletAC = " + servletAC);
30 |
31 | System.out.println("rootAC.getBeanDefinitionNames() = " + Arrays.toString(rootAC.getBeanDefinitionNames()));
32 | System.out.println("servletAC.getBeanDefinitionNames() = " + Arrays.toString(servletAC.getBeanDefinitionNames()));
33 |
34 | System.out.println("rootAC.getBeanDefinitionCount() = " + rootAC.getBeanDefinitionCount());
35 | System.out.println("servletAC.getBeanDefinitionCount() = " + servletAC.getBeanDefinitionCount());
36 |
37 | System.out.println("servletAC.getParent()==rootAC = " + (servletAC.getParent() == rootAC)); // servletAC.getParent()==rootAC = true
38 | return "home";
39 | }
40 | }
41 | /* [실행결과]
42 | webApplicationContext = Root WebApplicationContext: startup date [Thu Jan 06 16:26:50 KST 2022]; root of context hierarchy
43 | servletAC = WebApplicationContext for namespace 'appServlet-servlet': startup date [Thu Jan 06 16:26:51 KST 2022]; parent: Root WebApplicationContext
44 | rootAC.getBeanDefinitionNames() = []
45 | servletAC.getBeanDefinitionNames() = [mvcContentNegotiationManager, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping, mvcCorsConfigurations, org.springframework.format.support.FormattingConversionServiceFactoryBean#0, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter, mvcUriComponentsContributor, org.springframework.web.servlet.handler.MappedInterceptor#0, org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0, org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0, org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0, org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping, org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter, org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter, mvcHandlerMappingIntrospector, mvcResourceUrlProvider, org.springframework.web.servlet.handler.MappedInterceptor#1, mvcPathMatcher, mvcUrlPathHelper, org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0, org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0, org.springframework.web.servlet.view.InternalResourceViewResolver#0, car, door, engine, homeController, superEngine, turboEngine, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory]
46 | rootAC.getBeanDefinitionCount() = 0
47 | servletAC.getBeanDefinitionCount() = 33
48 | servletAC.getParent()==rootAC = true
49 | */
50 |
--------------------------------------------------------------------------------
/ch3/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import java.net.URLEncoder;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import javax.servlet.http.HttpSession;
9 |
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.web.bind.annotation.CookieValue;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PostMapping;
14 | import org.springframework.web.bind.annotation.RequestMapping;
15 |
16 | @Controller
17 | @RequestMapping("/login")
18 | public class LoginController {
19 | @GetMapping("/login")
20 | public String loginForm() {
21 | return "loginForm";
22 | }
23 |
24 | @GetMapping("/logout")
25 | public String logout(HttpSession session) {
26 | // 1. 세션을 종료
27 | session.invalidate();
28 | // 2. 홈으로 이동
29 | return "redirect:/";
30 | }
31 |
32 | @PostMapping("/login")
33 | public String login(String id, String pwd, String toURL, boolean rememberId,
34 | HttpServletRequest request, HttpServletResponse response) throws Exception {
35 |
36 | // 1. id와 pwd를 확인
37 | if(!loginCheck(id, pwd)) {
38 | // 2-1 일치하지 않으면, loginForm으로 이동
39 | String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");
40 |
41 | return "redirect:/login/login?msg="+msg;
42 | }
43 | // 2-2. id와 pwd가 일치하면,
44 | // 세션 객체를 얻어오기
45 | HttpSession session = request.getSession();
46 | // 세션 객체에 id를 저장
47 | session.setAttribute("id", id);
48 |
49 | if(rememberId) {
50 | // 1. 쿠키를 생성
51 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
52 | // 2. 응답에 저장
53 | response.addCookie(cookie);
54 | } else {
55 | // 1. 쿠키를 삭제
56 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
57 | cookie.setMaxAge(0); // 쿠키를 삭제
58 | // 2. 응답에 저장
59 | response.addCookie(cookie);
60 | }
61 | // 3. 홈으로 이동
62 | toURL = toURL==null || toURL.equals("") ? "/" : toURL;
63 |
64 | return "redirect:"+toURL;
65 | }
66 |
67 | private boolean loginCheck(String id, String pwd) {
68 | return "asdf".equals(id) && "1234".equals(pwd);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/ch3/RegisterController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import java.net.URLEncoder;
4 | import java.util.List;
5 |
6 | import javax.validation.Valid;
7 |
8 | import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
9 | import org.springframework.core.convert.ConversionService;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.ui.Model;
12 | import org.springframework.validation.BindingResult;
13 | import org.springframework.validation.Validator;
14 | import org.springframework.web.bind.WebDataBinder;
15 | import org.springframework.web.bind.annotation.InitBinder;
16 | import org.springframework.web.bind.annotation.PostMapping;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 | import org.springframework.web.bind.annotation.RequestMethod;
19 |
20 | @Controller // ctrl+shift+o 자동 import
21 | @RequestMapping("/register")
22 | public class RegisterController {
23 |
24 | @InitBinder
25 | public void toDate(WebDataBinder binder) {
26 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
27 | binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
28 | binder.setValidator(new UserValidator()); // UserValidator를 WebDataBinder의 로컬 validator로 등록
29 | // List validatorList = binder.getValidators();
30 | // System.out.println("validatorList="+validatorList);
31 | }
32 |
33 | @GetMapping("/add")
34 | public String register() {
35 | return "registerForm"; // WEB-INF/views/registerForm.jsp
36 | }
37 |
38 | @PostMapping("/add")
39 | public String save(@Valid User user, BindingResult result, Model m) throws Exception {
40 | System.out.println("result="+result);
41 | System.out.println("user="+user);
42 |
43 | // User객체를 검증한 결과 에러가 있으면, registerForm을 이용해서 에러를 보여줘야 함.
44 | if(result.hasErrors()) {
45 | return "registerForm";
46 | }
47 |
48 | // 2. DB에 신규회원 정보를 저장
49 | return "registerInfo";
50 | }
51 |
52 | private boolean isValid(User user) {
53 | return true;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ch3/User.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import java.util.Date;
4 | import java.util.Objects;
5 |
6 | public class User {
7 | private String id;
8 | private String pwd;
9 | private String name;
10 | private String email;
11 | private Date birth;
12 | private String sns;
13 | private Date reg_date;
14 |
15 | public User(){}
16 | public User(String id, String pwd, String name, String email, Date birth, String sns, Date reg_date) {
17 | this.id = id;
18 | this.pwd = pwd;
19 | this.name = name;
20 | this.email = email;
21 | this.birth = birth;
22 | this.sns = sns;
23 | this.reg_date = reg_date;
24 | }
25 |
26 | @Override
27 | public boolean equals(Object o) {
28 | if (this == o) return true;
29 | if (o == null || getClass() != o.getClass()) return false;
30 | User user = (User) o;
31 | return id.equals(user.id) && Objects.equals(pwd, user.pwd) && Objects.equals(name, user.name) && Objects.equals(email, user.email) && Objects.equals(birth, user.birth) && Objects.equals(sns, user.sns);
32 | }
33 |
34 | @Override
35 | public int hashCode() {
36 | return Objects.hash(id, pwd, name, email, birth, sns, reg_date);
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return "User{" +
42 | "id='" + id + '\'' +
43 | ", pwd='" + pwd + '\'' +
44 | ", name='" + name + '\'' +
45 | ", email='" + email + '\'' +
46 | ", birth=" + birth +
47 | ", sns='" + sns + '\'' +
48 | ", reg_date=" + reg_date +
49 | '}';
50 | }
51 |
52 | public String getId() {
53 | return id;
54 | }
55 |
56 | public void setId(String id) {
57 | this.id = id;
58 | }
59 |
60 | public String getPwd() {
61 | return pwd;
62 | }
63 |
64 | public void setPwd(String pwd) {
65 | this.pwd = pwd;
66 | }
67 |
68 | public String getName() {
69 | return name;
70 | }
71 |
72 | public void setName(String name) {
73 | this.name = name;
74 | }
75 |
76 | public String getEmail() {
77 | return email;
78 | }
79 |
80 | public void setEmail(String email) {
81 | this.email = email;
82 | }
83 |
84 | public Date getBirth() {
85 | return birth;
86 | }
87 |
88 | public void setBirth(Date birth) {
89 | this.birth = birth;
90 | }
91 |
92 | public String getSns() {
93 | return sns;
94 | }
95 |
96 | public void setSns(String sns) {
97 | this.sns = sns;
98 | }
99 |
100 | public Date getReg_date() {
101 | return reg_date;
102 | }
103 |
104 | public void setReg_date(Date reg_date) {
105 | this.reg_date = reg_date;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/ch3/UserValidator.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch3;
2 |
3 | import org.springframework.validation.Errors;
4 | import org.springframework.validation.ValidationUtils;
5 | import org.springframework.validation.Validator;
6 |
7 | public class UserValidator implements Validator {
8 | @Override
9 | public boolean supports(Class> clazz) {
10 | // return User.class.equals(clazz); // 검증하려는 객체가 User타입인지 확인
11 | return User.class.isAssignableFrom(clazz); // clazz가 User 또는 그 자손인지 확인
12 | }
13 |
14 | @Override
15 | public void validate(Object target, Errors errors) {
16 | System.out.println("UserValidator.validate() is called");
17 |
18 | User user = (User)target;
19 |
20 | String id = user.getId();
21 |
22 | // if(id==null || "".equals(id.trim())) {
23 | // errors.rejectValue("id", "required");
24 | // }
25 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "required");
26 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "pwd", "required");
27 |
28 | if(id==null || id.length() < 5 || id.length() > 12) {
29 | errors.rejectValue("id", "invalidLength", new String[]{"5","12"}, null);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ch3/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ch3/config1.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ch3/error_message.properties:
--------------------------------------------------------------------------------
1 | required=필수 항목입니다.
2 | required.user.pwd=사용자 비밀번호는 필수 항목입니다.
3 | invalidLength.id=아이디의 길이는 {0}~{1}사이어야 합니다.
4 |
--------------------------------------------------------------------------------
/ch3/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page session="false" %>
4 |
5 |
6 |
7 |
8 |
9 |
10 | fastcampus
11 |
12 |
13 |
14 |
15 |
25 |
26 |
This is HOME
27 | This is HOME
28 | This is HOME
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ch3/loginForm.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page import="java.net.URLDecoder" %>
4 | <%@ page session="false" %>
5 |
6 |
7 |
8 |
9 |
10 |
11 | Login
12 |
13 |
59 |
60 |
61 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/ch3/menu.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin : 0;
4 | padding: 0;
5 | }
6 |
7 | a { text-decoration: none; }
8 |
9 | ul {
10 | list-style-type: none;
11 | height: 48px;
12 | width: 100%;
13 | background-color: #30426E;
14 | display: flex;
15 | }
16 |
17 | ul > li {
18 | color: lightgray;
19 | height : 100%;
20 | width:90px;
21 | display:flex;
22 | align-items: center;
23 | }
24 |
25 | ul > li > a {
26 | color: lightgray;
27 | margin:auto;
28 | padding: 10px;
29 | font-size:20px;
30 | align-items: center;
31 | }
32 |
33 | ul > li > a:hover {
34 | color :white;
35 | border-bottom: 3px solid rgb(209, 209, 209);
36 | }
37 |
38 | #logo {
39 | color:white;
40 | font-size: 18px;
41 | padding-left:40px;
42 | margin-right:auto;
43 | display: flex;
44 | }
45 |
--------------------------------------------------------------------------------
/ch3/readme.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch3/readme.md
--------------------------------------------------------------------------------
/ch3/registerForm.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=utf-8" %>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
4 |
5 | <%@ page import="java.net.URLDecoder"%>
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
73 | Register
74 |
75 |
76 |
77 |
78 | Register
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/ch3/registerInfo.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 |
4 |
5 |
6 |
7 | Insert title here
8 |
9 |
10 | id=${user.id}
11 | pwd=${user.pwd}
12 | name=${user.name}
13 | email=${user.email}
14 | birth=${user.birth}
15 | hobby=${user.hobby}
16 | sns=${user.sns}
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ch3/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ch3/root-context_aop.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ch4/BoardController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.controller;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import com.fastcampus.ch4.service.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.stereotype.*;
7 | import org.springframework.ui.*;
8 | import org.springframework.web.bind.annotation.*;
9 | import org.springframework.web.servlet.mvc.support.*;
10 |
11 | import javax.servlet.http.*;
12 | import java.time.*;
13 | import java.util.*;
14 |
15 | @Controller
16 | @RequestMapping("/board")
17 | public class BoardController {
18 | @Autowired
19 | BoardService boardService;
20 |
21 | @GetMapping("/list")
22 | public String list(HttpServletRequest request) {
23 | if(!loginCheck(request))
24 | return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
25 |
26 | return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
27 | }
28 |
29 | private boolean loginCheck(HttpServletRequest request) {
30 | // 1. 세션을 얻어서
31 | HttpSession session = request.getSession();
32 | // 2. 세션에 id가 있는지 확인, 있으면 true를 반환
33 | return session.getAttribute("id")!=null;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ch4/BoardController3.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.controller;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import com.fastcampus.ch4.service.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.stereotype.*;
7 | import org.springframework.ui.*;
8 | import org.springframework.web.bind.annotation.*;
9 | import org.springframework.web.servlet.mvc.support.*;
10 |
11 | import javax.servlet.http.*;
12 | import java.time.*;
13 | import java.util.*;
14 |
15 | @Controller
16 | @RequestMapping("/board")
17 | public class BoardController {
18 | @Autowired
19 | BoardService boardService;
20 |
21 | @PostMapping("/modify")
22 | public String modify(BoardDto boardDto, SearchCondition sc, RedirectAttributes rattr, Model m, HttpSession session) {
23 | String writer = (String)session.getAttribute("id");
24 | boardDto.setWriter(writer);
25 |
26 | try {
27 | if (boardService.modify(boardDto)!= 1)
28 | throw new Exception("Modify failed.");
29 |
30 | rattr.addFlashAttribute("msg", "MOD_OK");
31 | return "redirect:/board/list"+sc.getQueryString();
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | m.addAttribute(boardDto);
35 | m.addAttribute("msg", "MOD_ERR");
36 | return "board";
37 | }
38 | }
39 |
40 | @GetMapping("/write")
41 | public String write(Model m) {
42 | m.addAttribute("mode", "new");
43 |
44 | return "board";
45 | }
46 |
47 | @PostMapping("/write")
48 | public String write(BoardDto boardDto, RedirectAttributes rattr, Model m, HttpSession session) {
49 | String writer = (String)session.getAttribute("id");
50 | boardDto.setWriter(writer);
51 |
52 | try {
53 | if (boardService.write(boardDto) != 1)
54 | throw new Exception("Write failed.");
55 |
56 | rattr.addFlashAttribute("msg", "WRT_OK");
57 | return "redirect:/board/list";
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | m.addAttribute(boardDto);
61 | m.addAttribute("mode", "new");
62 | m.addAttribute("msg", "WRT_ERR");
63 | return "board";
64 | }
65 | }
66 |
67 | @GetMapping("/read")
68 | public String read(Integer bno, SearchCondition sc, RedirectAttributes rattr, Model m) {
69 | try {
70 | BoardDto boardDto = boardService.read(bno);
71 | m.addAttribute(boardDto);
72 | } catch (Exception e) {
73 | e.printStackTrace();
74 | rattr.addFlashAttribute("msg", "READ_ERR");
75 | return "redirect:/board/list"+sc.getQueryString();
76 | }
77 |
78 | return "board";
79 | }
80 |
81 | @PostMapping("/remove")
82 | public String remove(Integer bno, SearchCondition sc, RedirectAttributes rattr, HttpSession session) {
83 | String writer = (String)session.getAttribute("id");
84 | String msg = "DEL_OK";
85 |
86 | try {
87 | if(boardService.remove(bno, writer)!=1)
88 | throw new Exception("Delete failed.");
89 | } catch (Exception e) {
90 | e.printStackTrace();
91 | msg = "DEL_ERR";
92 | }
93 |
94 | rattr.addFlashAttribute("msg", msg);
95 | return "redirect:/board/list"+sc.getQueryString();
96 | }
97 |
98 | @GetMapping("/list")
99 | public String list(Model m, SearchCondition sc, HttpServletRequest request) {
100 | if(!loginCheck(request))
101 | return "redirect:/login/login?toURL="+request.getRequestURL(); // 로그인을 안했으면 로그인 화면으로 이동
102 |
103 | try {
104 | int totalCnt = boardService.getSearchResultCnt(sc);
105 | m.addAttribute("totalCnt", totalCnt);
106 |
107 | PageHandler pageHandler = new PageHandler(totalCnt, sc);
108 |
109 | List list = boardService.getSearchResultPage(sc);
110 | m.addAttribute("list", list);
111 | m.addAttribute("ph", pageHandler);
112 |
113 | Instant startOfToday = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant();
114 | m.addAttribute("startOfToday", startOfToday.toEpochMilli());
115 | } catch (Exception e) {
116 | e.printStackTrace();
117 | m.addAttribute("msg", "LIST_ERR");
118 | m.addAttribute("totalCnt", 0);
119 | }
120 |
121 | return "boardList"; // 로그인을 한 상태이면, 게시판 화면으로 이동
122 | }
123 |
124 | private boolean loginCheck(HttpServletRequest request) {
125 | // 1. 세션을 얻어서(false는 session이 없어도 새로 생성하지 않는다. 반환값 null)
126 | HttpSession session = request.getSession(false);
127 | // 2. 세션에 id가 있는지 확인, 있으면 true를 반환
128 | return session!=null && session.getAttribute("id")!=null;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/ch4/BoardDao.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 |
5 | import java.util.*;
6 |
7 | public interface BoardDao {
8 | BoardDto select(Integer bno) throws Exception;
9 | int delete(Integer bno, String writer) throws Exception;
10 | int insert(BoardDto dto) throws Exception;
11 | int update(BoardDto dto) throws Exception;
12 | int increaseViewCnt(Integer bno) throws Exception;
13 |
14 | List selectPage(Map map) throws Exception;
15 | List selectAll() throws Exception;
16 | int deleteAll() throws Exception;
17 | int count() throws Exception;
18 |
19 | int searchResultCnt(SearchCondition sc) throws Exception;
20 | List searchSelectPage(SearchCondition sc) throws Exception;
21 | }
22 |
--------------------------------------------------------------------------------
/ch4/BoardDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.apache.ibatis.session.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.stereotype.*;
7 |
8 | import java.util.*;
9 |
10 | @Repository
11 | public class BoardDaoImpl implements BoardDao {
12 | @Autowired
13 | private SqlSession session;
14 | private static String namespace = "com.fastcampus.ch4.dao.BoardMapper.";
15 |
16 | public int count() throws Exception {
17 | return session.selectOne(namespace+"count");
18 | } // T selectOne(String statement)
19 |
20 | @Override
21 | public int deleteAll() {
22 | return session.delete(namespace+"deleteAll");
23 | } // int delete(String statement)
24 |
25 | @Override
26 | public int delete(Integer bno, String writer) throws Exception {
27 | Map map = new HashMap();
28 | map.put("bno", bno);
29 | map.put("writer", writer);
30 | return session.delete(namespace+"delete", map);
31 | } // int delete(String statement, Object parameter)
32 |
33 | public int insert(BoardDto dto) throws Exception {
34 | return session.insert(namespace+"insert", dto);
35 | } // int insert(String statement, Object parameter)
36 |
37 | @Override
38 | public List selectAll() throws Exception {
39 | return session.selectList(namespace+"selectAll");
40 | } // List selectList(String statement)
41 |
42 | public BoardDto select(Integer bno) throws Exception {
43 | return session.selectOne(namespace + "select", bno);
44 | } // T selectOne(String statement, Object parameter)
45 |
46 | @Override
47 | public List selectPage(Map map) throws Exception {
48 | return session.selectList(namespace+"selectPage", map);
49 | } // List selectList(String statement, Object parameter)
50 |
51 | @Override
52 | public int update(BoardDto dto) throws Exception {
53 | return session.update(namespace+"update", dto);
54 | } // int update(String statement, Object parameter)
55 |
56 | @Override
57 | public int increaseViewCnt(Integer bno) throws Exception {
58 | return session.update(namespace+"increaseViewCnt", bno);
59 | } // int update(String statement, Object parameter)
60 |
61 | @Override
62 | public int searchResultCnt(SearchCondition sc) throws Exception {
63 | System.out.println("sc in searchResultCnt() = " + sc);
64 | System.out.println("session = " + session);
65 | return session.selectOne(namespace+"searchResultCnt", sc);
66 | } // T selectOne(String statement, Object parameter)
67 |
68 | @Override
69 | public List searchSelectPage(SearchCondition sc) throws Exception {
70 | return session.selectList(namespace+"searchSelectPage", sc);
71 | } // List selectList(String statement, Object parameter)
72 | }
73 |
--------------------------------------------------------------------------------
/ch4/BoardDto.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.domain;
2 |
3 | import java.util.*;
4 |
5 | public class BoardDto {
6 | private Integer bno;
7 | private String title;
8 | private String content;
9 | private String writer;
10 | private int view_cnt;
11 | private int comment_cnt;
12 | private Date reg_date;
13 |
14 | @Override
15 | public boolean equals(Object o) {
16 | if (this == o) return true;
17 | if (o == null || getClass() != o.getClass()) return false;
18 | BoardDto boardDto = (BoardDto) o;
19 | return Objects.equals(bno, boardDto.bno) && Objects.equals(title, boardDto.title) && Objects.equals(content, boardDto.content) && Objects.equals(writer, boardDto.writer);
20 | }
21 |
22 | @Override
23 | public int hashCode() {
24 | return Objects.hash(bno, title, content, writer);
25 | }
26 |
27 | public BoardDto() { this("","",""); }
28 | public BoardDto(String title, String content, String writer){
29 | this.title = title;
30 | this.content = content;
31 | this.writer = writer;
32 | }
33 |
34 | public Integer getBno() {
35 | return bno;
36 | }
37 | public void setBno(Integer bno) {
38 | this.bno = bno;
39 | }
40 | public String getTitle() {
41 | return title;
42 | }
43 | public void setTitle(String title) {
44 | this.title = title;
45 | }
46 | public String getContent() {
47 | return content;
48 | }
49 | public void setContent(String content) {
50 | this.content = content;
51 | }
52 | public String getWriter() {
53 | return writer;
54 | }
55 | public void setWriter(String writer) {
56 | this.writer = writer;
57 | }
58 | public int getView_cnt() {
59 | return view_cnt;
60 | }
61 | public void setView_cnt(int view_cnt) {
62 | this.view_cnt = view_cnt;
63 | }
64 | public int getComment_cnt() {
65 | return comment_cnt;
66 | }
67 | public void setComment_cnt(int comment_cnt) {
68 | this.comment_cnt = comment_cnt;
69 | }
70 | public Date getReg_date() {
71 | return reg_date;
72 | }
73 | public void setReg_date(Date reg_date) {
74 | this.reg_date = reg_date;
75 | }
76 |
77 | @Override
78 | public String toString() {
79 | return "BoardDto{" +
80 | "bno=" + bno +
81 | ", title='" + title + '\'' +
82 | ", content='" + content + '\'' +
83 | ", writer='" + writer + '\'' +
84 | ", view_cnt=" + view_cnt +
85 | ", comment_cnt=" + comment_cnt +
86 | ", reg_date=" + reg_date +
87 | '}';
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/ch4/BoardService.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.service;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 |
5 | import java.util.*;
6 |
7 | public interface BoardService {
8 | int getCount() throws Exception;
9 | int remove(Integer bno, String writer) throws Exception;
10 | int write(BoardDto boardDto) throws Exception;
11 | List getList() throws Exception;
12 | BoardDto read(Integer bno) throws Exception;
13 | List getPage(Map map) throws Exception;
14 | int modify(BoardDto boardDto) throws Exception;
15 |
16 | int getSearchResultCnt(SearchCondition sc) throws Exception;
17 | List getSearchResultPage(SearchCondition sc) throws Exception;
18 | }
19 |
--------------------------------------------------------------------------------
/ch4/BoardServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.service;
2 |
3 | import com.fastcampus.ch4.dao.*;
4 | import com.fastcampus.ch4.domain.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.stereotype.*;
7 |
8 | import java.util.*;
9 |
10 | @Service
11 | public class BoardServiceImpl implements BoardService {
12 | @Autowired
13 | BoardDao boardDao;
14 |
15 | @Override
16 | public int getCount() throws Exception {
17 | return boardDao.count();
18 | }
19 |
20 | @Override
21 | public int remove(Integer bno, String writer) throws Exception {
22 | return boardDao.delete(bno, writer);
23 | }
24 |
25 | @Override
26 | public int write(BoardDto boardDto) throws Exception {
27 | return boardDao.insert(boardDto);
28 | }
29 |
30 | @Override
31 | public List getList() throws Exception {
32 | return boardDao.selectAll();
33 | }
34 |
35 | @Override
36 | public BoardDto read(Integer bno) throws Exception {
37 | BoardDto boardDto = boardDao.select(bno);
38 | boardDao.increaseViewCnt(bno);
39 |
40 | return boardDto;
41 | }
42 |
43 | @Override
44 | public List getPage(Map map) throws Exception {
45 | return boardDao.selectPage(map);
46 | }
47 |
48 | @Override
49 | public int modify(BoardDto boardDto) throws Exception {
50 | return boardDao.update(boardDto);
51 | }
52 |
53 | @Override
54 | public int getSearchResultCnt(SearchCondition sc) throws Exception {
55 | return boardDao.searchResultCnt(sc);
56 | }
57 |
58 | @Override
59 | public List getSearchResultPage(SearchCondition sc) throws Exception {
60 | return boardDao.searchSelectPage(sc);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ch4/BoardServiceImplTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.service;
2 |
3 | import org.junit.*;
4 |
5 | import java.time.*;
6 |
7 | import static org.junit.Assert.*;
8 |
9 | public class BoardServiceImplTest {
10 |
11 | @Test
12 | public void read() {
13 | }
14 |
15 | @Test
16 | public void edit() {
17 | }
18 |
19 | @Test
20 | public void write() {
21 | }
22 |
23 | @Test
24 | public void remove() {
25 | }
26 |
27 | @Test
28 | public void getPage() {
29 | }
30 |
31 | @Test
32 | public void getList() {
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ch4/CommentController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.controller;
2 |
3 | import com.fastcampus.ch4.domain.CommentDto;
4 | import com.fastcampus.ch4.service.CommentService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.http.HttpStatus;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.servlet.http.HttpSession;
12 | import java.util.List;
13 |
14 | //@Controller
15 | //@ResponseBody
16 | @RestController
17 | public class CommentController {
18 | @Autowired
19 | CommentService service;
20 |
21 | // {
22 | // "pcno":0,
23 | // "comment" : "hihihi",
24 | // "commenter" : "asdf"
25 | // }
26 | // 댓글을 수정하는 메서드
27 | @PatchMapping("/comments/{cno}") // /ch4/comments/26 PATCH
28 | public ResponseEntity modify(@PathVariable Integer cno, @RequestBody CommentDto dto) {
29 | // String commenter = (String)session.getAttribute("id");
30 | String commenter = "asdf";
31 | dto.setCommenter(commenter);
32 | dto.setCno(cno);
33 | System.out.println("dto = " + dto);
34 |
35 | try {
36 | if(service.modify(dto)!=1)
37 | throw new Exception("Write failed.");
38 |
39 | return new ResponseEntity<>("MOD_OK", HttpStatus.OK);
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | return new ResponseEntity("MOD_ERR", HttpStatus.BAD_REQUEST);
43 | }
44 | }
45 |
46 | // {
47 | // "pcno":0,
48 | // "comment" : "hi"
49 | // }
50 | // 댓글을 등록하는 메서드
51 | @PostMapping("/comments") // /ch4/comments?bno=1085 POST
52 | public ResponseEntity write(@RequestBody CommentDto dto, Integer bno, HttpSession session) {
53 | // String commenter = (String)session.getAttribute("id");
54 | String commenter = "asdf";
55 | dto.setCommenter(commenter);
56 | dto.setBno(bno);
57 | System.out.println("dto = " + dto);
58 |
59 | try {
60 | if(service.write(dto)!=1)
61 | throw new Exception("Write failed.");
62 |
63 | return new ResponseEntity<>("WRT_OK", HttpStatus.OK);
64 | } catch (Exception e) {
65 | e.printStackTrace();
66 | return new ResponseEntity("WRT_ERR", HttpStatus.BAD_REQUEST);
67 | }
68 | }
69 |
70 | // 지정된 댓글을 삭제하는 메서드
71 | @DeleteMapping("/comments/{cno}") // DELETE /comments/1?bno=1085 <-- 삭제할 댓글 번호
72 | public ResponseEntity remove(@PathVariable Integer cno, Integer bno, HttpSession session) {
73 | // String commenter = (String)session.getAttribute("id");
74 | String commenter = "asdf";
75 |
76 | try {
77 | int rowCnt = service.remove(cno, bno, commenter);
78 |
79 | if(rowCnt!=1)
80 | throw new Exception("Delete Failed");
81 |
82 | return new ResponseEntity<>("DEL_OK", HttpStatus.OK);
83 | } catch (Exception e) {
84 | e.printStackTrace();
85 | return new ResponseEntity<>("DEL_ERR", HttpStatus.BAD_REQUEST);
86 | }
87 | }
88 |
89 | // 지정된 게시물의 모든 댓글을 가져오는 메서드
90 | @GetMapping("/comments") // /comments?bno=1080 GET
91 | public ResponseEntity> list(Integer bno) {
92 | List list = null;
93 | try {
94 | list = service.getList(bno);
95 | return new ResponseEntity>(list, HttpStatus.OK); // 200
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | return new ResponseEntity>(HttpStatus.BAD_REQUEST); // 400
99 | }
100 | }
101 |
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/ch4/CommentDao.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.CommentDto;
4 | import org.apache.ibatis.annotations.Param;
5 |
6 | import java.util.List;
7 |
8 | public interface CommentDao {
9 | int count(Integer bno) throws Exception;
10 | int deleteAll(Integer bno);
11 | int delete(Integer cno, String commenter) throws Exception;
12 | int insert(CommentDto dto) throws Exception;
13 | List selectAll(Integer bno) throws Exception;
14 | CommentDto select(Integer cno) throws Exception;
15 | int update(CommentDto dto) throws Exception;
16 | }
17 |
--------------------------------------------------------------------------------
/ch4/CommentDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.apache.ibatis.annotations.*;
5 | import org.apache.ibatis.session.*;
6 | import org.springframework.beans.factory.annotation.*;
7 | import org.springframework.stereotype.*;
8 |
9 | import java.util.*;
10 |
11 | @Repository
12 | public class CommentDaoImpl implements CommentDao {
13 | @Autowired
14 | private SqlSession session;
15 | private static String namespace = "com.fastcampus.ch4.dao.CommentMapper.";
16 |
17 | @Override
18 | public int count(Integer bno) throws Exception {
19 | return session.selectOne(namespace+"count", bno);
20 | } // T selectOne(String statement)
21 |
22 | @Override
23 | public int deleteAll(Integer bno) {
24 | return session.delete(namespace+"deleteAll", bno);
25 | } // int delete(String statement)
26 |
27 | @Override
28 | public int delete(Integer cno, String commenter) throws Exception {
29 | Map map = new HashMap();
30 | map.put("cno", cno);
31 | map.put("commenter", commenter);
32 | return session.delete(namespace+"delete", map);
33 | } // int delete(String statement, Object parameter)
34 |
35 | @Override
36 | public int insert(CommentDto dto) throws Exception {
37 | return session.insert(namespace+"insert", dto);
38 | } // int insert(String statement, Object parameter)
39 |
40 | @Override
41 | public List selectAll(Integer bno) throws Exception {
42 | return session.selectList(namespace+"selectAll", bno);
43 | } // List selectList(String statement)
44 |
45 | @Override
46 | public CommentDto select(Integer cno) throws Exception {
47 | return session.selectOne(namespace + "select", cno);
48 | } // T selectOne(String statement, Object parameter)
49 |
50 | @Override
51 | public int update(CommentDto dto) throws Exception {
52 | return session.update(namespace+"update", dto);
53 | } // int update(String statement, Object parameter)
54 | }
55 |
--------------------------------------------------------------------------------
/ch4/CommentDaoImplTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.junit.*;
5 | import org.junit.runner.*;
6 | import org.springframework.beans.factory.annotation.*;
7 | import org.springframework.test.context.*;
8 | import org.springframework.test.context.junit4.*;
9 |
10 | import java.util.*;
11 |
12 | import static org.junit.Assert.*;
13 |
14 | @RunWith(SpringJUnit4ClassRunner.class)
15 | @ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
16 | public class CommentDaoImplTest {
17 | @Autowired
18 | CommentDao commentDao;
19 |
20 | @Test
21 | public void count() throws Exception {
22 | commentDao.deleteAll(1);
23 | assertTrue(commentDao.count(1)==0);
24 | }
25 |
26 | @Test
27 | public void delete() throws Exception {
28 | commentDao.deleteAll(1);
29 | CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
30 | assertTrue(commentDao.insert(commentDto)==1);
31 | assertTrue(commentDao.count(1)==1);
32 | }
33 |
34 | @Test
35 | public void insert() throws Exception {
36 | commentDao.deleteAll(1);
37 | CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
38 | assertTrue(commentDao.insert(commentDto)==1);
39 | assertTrue(commentDao.count(1)==1);
40 |
41 | commentDto = new CommentDto(1, 0, "comment", "asdf");
42 | assertTrue(commentDao.insert(commentDto)==1);
43 | assertTrue(commentDao.count(1)==2);
44 | }
45 |
46 | @Test
47 | public void selectAll() throws Exception {
48 | commentDao.deleteAll(1);
49 | CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
50 | assertTrue(commentDao.insert(commentDto)==1);
51 | assertTrue(commentDao.count(1)==1);
52 |
53 | List list = commentDao.selectAll(1);
54 | assertTrue(list.size()==1);
55 |
56 | commentDto = new CommentDto(1, 0, "comment", "asdf");
57 | assertTrue(commentDao.insert(commentDto)==1);
58 | assertTrue(commentDao.count(1)==2);
59 |
60 | list = commentDao.selectAll(1);
61 | assertTrue(list.size()==2);
62 | }
63 |
64 | @Test
65 | public void select() throws Exception {
66 | commentDao.deleteAll(1);
67 | CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
68 | assertTrue(commentDao.insert(commentDto)==1);
69 | assertTrue(commentDao.count(1)==1);
70 |
71 | List list = commentDao.selectAll(1);
72 | String comment = list.get(0).getComment();
73 | String commenter = list.get(0).getCommenter();
74 | assertTrue(comment.equals(commentDto.getComment()));
75 | assertTrue(commenter.equals(commentDto.getCommenter()));
76 | }
77 |
78 | @Test
79 | public void update() throws Exception {
80 | commentDao.deleteAll(1);
81 | CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf");
82 | assertTrue(commentDao.insert(commentDto)==1);
83 | assertTrue(commentDao.count(1)==1);
84 |
85 | List list = commentDao.selectAll(1);
86 | commentDto.setCno(list.get(0).getCno());
87 | commentDto.setComment("comment2");
88 | assertTrue(commentDao.update(commentDto)==1);
89 |
90 | list = commentDao.selectAll(1);
91 | String comment = list.get(0).getComment();
92 | String commenter = list.get(0).getCommenter();
93 | assertTrue(comment.equals(commentDto.getComment()));
94 | assertTrue(commenter.equals(commentDto.getCommenter()));
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/ch4/CommentDto.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.domain;
2 |
3 | import java.util.*;
4 |
5 | public class CommentDto {
6 | private Integer cno;
7 | private Integer bno;
8 | private Integer pcno;
9 | private String comment;
10 | private String commenter;
11 | private Date reg_date;
12 | private Date up_date;
13 |
14 | public CommentDto() {}
15 | public CommentDto(Integer bno, Integer pcno, String comment, String commenter) {
16 | this.bno = bno;
17 | this.pcno = pcno;
18 | this.comment = comment;
19 | this.commenter = commenter;
20 | }
21 |
22 | @Override
23 | public boolean equals(Object o) {
24 | if (this == o) return true;
25 | if (o == null || getClass() != o.getClass()) return false;
26 | CommentDto that = (CommentDto) o;
27 | return Objects.equals(cno, that.cno) && Objects.equals(bno, that.bno) && Objects.equals(pcno, that.pcno) && Objects.equals(comment, that.comment) && Objects.equals(commenter, that.commenter);
28 | }
29 |
30 | @Override
31 | public int hashCode() {
32 | return Objects.hash(cno, bno, pcno, comment, commenter);
33 | }
34 |
35 | public Integer getBno() {
36 | return bno;
37 | }
38 |
39 | public void setBno(Integer bno) {
40 | this.bno = bno;
41 | }
42 |
43 | public Integer getPcno() {
44 | return pcno;
45 | }
46 |
47 | public void setPcno(Integer pcno) {
48 | this.pcno = pcno;
49 | }
50 |
51 | public String getComment() {
52 | return comment;
53 | }
54 |
55 | public void setComment(String comment) {
56 | this.comment = comment;
57 | }
58 |
59 | public String getCommenter() {
60 | return commenter;
61 | }
62 |
63 | public void setCommenter(String commenter) {
64 | this.commenter = commenter;
65 | }
66 |
67 | public Date getReg_date() {
68 | return reg_date;
69 | }
70 |
71 | public void setReg_date(Date reg_date) {
72 | this.reg_date = reg_date;
73 | }
74 |
75 | public Date getUp_date() {
76 | return up_date;
77 | }
78 |
79 | public void setUp_date(Date up_date) {
80 | this.up_date = up_date;
81 | }
82 |
83 | public Integer getCno() {
84 | return cno;
85 | }
86 |
87 | public void setCno(Integer cno) {
88 | this.cno = cno;
89 | }
90 |
91 | @Override
92 | public String toString() {
93 | return "CommentDto{" +
94 | "cno=" + cno +
95 | ", bno=" + bno +
96 | ", pcno=" + pcno +
97 | ", comment='" + comment + '\'' +
98 | ", commenter='" + commenter + '\'' +
99 | ", reg_date=" + reg_date +
100 | ", up_date=" + up_date +
101 | '}';
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/ch4/CommentServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.service;
2 |
3 | import com.fastcampus.ch4.dao.*;
4 | import com.fastcampus.ch4.domain.*;
5 | import org.springframework.beans.factory.annotation.*;
6 | import org.springframework.stereotype.*;
7 | import org.springframework.transaction.annotation.*;
8 |
9 | import java.util.*;
10 |
11 | @Service
12 | public class CommentServiceImpl implements CommentService {
13 | @Autowired
14 | BoardDao boardDao;
15 | @Autowired
16 | CommentDao commentDao;
17 |
18 | // @Autowired
19 | // public CommentServiceImpl(CommentDao commentDao, BoardDao boardDao) {
20 | // this.commentDao = commentDao;
21 | // this.boardDao = boardDao;
22 | // }
23 |
24 | @Override
25 | public int getCount(Integer bno) throws Exception {
26 | return commentDao.count(bno);
27 | }
28 |
29 | @Override
30 |
31 | @Transactional(rollbackFor = Exception.class)
32 | public int remove(Integer cno, Integer bno, String commenter) throws Exception {
33 | int rowCnt = boardDao.updateCommentCnt(bno, -1);
34 | System.out.println("updateCommentCnt - rowCnt = " + rowCnt);
35 | // throw new Exception("test");
36 | rowCnt = commentDao.delete(cno, commenter);
37 | System.out.println("rowCnt = " + rowCnt);
38 | return rowCnt;
39 | }
40 |
41 | @Override
42 | @Transactional(rollbackFor = Exception.class)
43 | public int write(CommentDto commentDto) throws Exception {
44 | boardDao.updateCommentCnt(commentDto.getBno(), 1);
45 | // throw new Exception("test");
46 | return commentDao.insert(commentDto);
47 | }
48 |
49 | @Override
50 | public List getList(Integer bno) throws Exception {
51 | // throw new Exception("test");
52 | return commentDao.selectAll(bno);
53 | }
54 |
55 | @Override
56 | public CommentDto read(Integer cno) throws Exception {
57 | return commentDao.select(cno);
58 | }
59 |
60 | @Override
61 | public int modify(CommentDto commentDto) throws Exception {
62 | return commentDao.update(commentDto);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/ch4/CommentServiceImplTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.service;
2 |
3 | import com.fastcampus.ch4.dao.*;
4 | import com.fastcampus.ch4.domain.*;
5 | import org.junit.*;
6 | import org.junit.runner.*;
7 | import org.springframework.beans.factory.annotation.*;
8 | import org.springframework.test.context.*;
9 | import org.springframework.test.context.junit4.*;
10 |
11 | import java.util.*;
12 |
13 | import static org.junit.Assert.*;
14 |
15 | @RunWith(SpringJUnit4ClassRunner.class)
16 | @ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
17 | public class CommentServiceImplTest {
18 | @Autowired
19 | CommentService commentService;
20 | @Autowired
21 | CommentDao commentDao;
22 | @Autowired
23 | BoardDao boardDao;
24 |
25 | @Test
26 | public void remove() throws Exception {
27 | boardDao.deleteAll();
28 |
29 | BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
30 | assertTrue(boardDao.insert(boardDto) == 1);
31 | Integer bno = boardDao.selectAll().get(0).getBno();
32 | System.out.println("bno = " + bno);
33 |
34 | commentDao.deleteAll(bno);
35 | CommentDto commentDto = new CommentDto(bno,0,"hi","qwer");
36 |
37 | assertTrue(boardDao.select(bno).getComment_cnt() == 0);
38 | assertTrue(commentService.write(commentDto)==1);
39 | assertTrue(boardDao.select(bno).getComment_cnt() == 1);
40 |
41 | Integer cno = commentDao.selectAll(bno).get(0).getCno();
42 |
43 | // 일부러 예외를 발생시키고 Tx가 취소되는지 확인해야.
44 | int rowCnt = commentService.remove(cno, bno, commentDto.getCommenter());
45 | assertTrue(rowCnt==1);
46 | assertTrue(boardDao.select(bno).getComment_cnt() == 0);
47 | }
48 |
49 | @Test
50 | public void write() throws Exception {
51 | boardDao.deleteAll();
52 |
53 | BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
54 | assertTrue(boardDao.insert(boardDto) == 1);
55 | Integer bno = boardDao.selectAll().get(0).getBno();
56 | System.out.println("bno = " + bno);
57 |
58 | commentDao.deleteAll(bno);
59 | CommentDto commentDto = new CommentDto(bno,0,"hi","qwer");
60 |
61 | assertTrue(boardDao.select(bno).getComment_cnt() == 0);
62 | assertTrue(commentService.write(commentDto)==1);
63 |
64 | Integer cno = commentDao.selectAll(bno).get(0).getCno();
65 | assertTrue(boardDao.select(bno).getComment_cnt() == 1);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ch4/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.controller;
2 |
3 | import java.net.URLEncoder;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import javax.servlet.http.HttpSession;
9 |
10 | import com.fastcampus.ch4.dao.*;
11 | import com.fastcampus.ch4.domain.*;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.stereotype.Controller;
14 | import org.springframework.web.bind.annotation.CookieValue;
15 | import org.springframework.web.bind.annotation.GetMapping;
16 | import org.springframework.web.bind.annotation.PostMapping;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 |
19 | @Controller
20 | @RequestMapping("/login")
21 | public class LoginController {
22 | @Autowired
23 | UserDao userDao;
24 |
25 | @GetMapping("/login")
26 | public String loginForm() {
27 | return "loginForm";
28 | }
29 |
30 | @GetMapping("/logout")
31 | public String logout(HttpSession session) {
32 | // 1. 세션을 종료
33 | session.invalidate();
34 | // 2. 홈으로 이동
35 | return "redirect:/";
36 | }
37 |
38 | @PostMapping("/login")
39 | public String login(String id, String pwd, String toURL, boolean rememberId,
40 | HttpServletRequest request, HttpServletResponse response) throws Exception {
41 |
42 | // 1. id와 pwd를 확인
43 | if(!loginCheck(id, pwd)) {
44 | // 2-1 일치하지 않으면, loginForm으로 이동
45 | String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");
46 |
47 | return "redirect:/login/login?msg="+msg;
48 | }
49 | // 2-2. id와 pwd가 일치하면,
50 | // 세션 객체를 얻어오기
51 | HttpSession session = request.getSession();
52 | // 세션 객체에 id를 저장
53 | session.setAttribute("id", id);
54 |
55 | if(rememberId) {
56 | // 1. 쿠키를 생성
57 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
58 | // 2. 응답에 저장
59 | response.addCookie(cookie);
60 | } else {
61 | // 1. 쿠키를 삭제
62 | Cookie cookie = new Cookie("id", id); // ctrl+shift+o 자동 import
63 | cookie.setMaxAge(0); // 쿠키를 삭제
64 | // 2. 응답에 저장
65 | response.addCookie(cookie);
66 | }
67 | // 3. 홈으로 이동
68 | toURL = toURL==null || toURL.equals("") ? "/" : toURL;
69 |
70 | return "redirect:"+toURL;
71 | }
72 |
73 | private boolean loginCheck(String id, String pwd) {
74 | User user = null;
75 |
76 | try {
77 | user = userDao.selectUser(id);
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | return false;
81 | }
82 |
83 | return user!=null && user.getPwd().equals(pwd);
84 | // return "asdf".equals(id) && "1234".equals(pwd);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/ch4/PageHandler.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.domain;
2 |
3 | import org.springframework.web.util.*;
4 |
5 | public class PageHandler {
6 | private SearchCondition sc;
7 | // private int pageSize = 10; // 한 페이지당 게시물 갯수
8 | // private int page; // 현재 페이지
9 | // private String option;
10 | // private String keyword;
11 | public final int NAV_SIZE = 10; // page navigation size
12 | private int totalCnt; // 게시물의 총 갯수
13 | private int totalPage; // 전체 페이지의 갯수
14 | private int beginPage; // 화면에 보여줄 첫 페이지
15 | private int endPage; // 화면에 보여줄 마지막 페이지
16 | private boolean showNext = false; // 이후를 보여줄지의 여부. endPage==totalPage이면, showNext는 false
17 | private boolean showPrev = false; // 이전을 보여줄지의 여부. beginPage==1이 아니면 showPrev는 false
18 |
19 | public PageHandler(int totalCnt, Integer page) {
20 | this(totalCnt, new SearchCondition(page, 10));
21 | }
22 |
23 | public PageHandler(int totalCnt, Integer page, Integer pageSize) {
24 | this(totalCnt, new SearchCondition(page, pageSize));
25 | }
26 |
27 | public PageHandler(int totalCnt, SearchCondition sc) {
28 | this.totalCnt = totalCnt;
29 | this.sc = sc;
30 |
31 | doPaging(totalCnt, sc);
32 | }
33 |
34 | private void doPaging(int totalCnt, SearchCondition sc) {
35 | this.totalPage = totalCnt / sc.getPageSize() + (totalCnt % sc.getPageSize()==0? 0:1);
36 | this.sc.setPage(Math.min(sc.getPage(), totalPage)); // page가 totalPage보다 크지 않게
37 | this.beginPage = (this.sc.getPage() -1) / NAV_SIZE * NAV_SIZE + 1; // 11 -> 11, 10 -> 1, 15->11. 따로 떼어내서 테스트
38 | this.endPage = Math.min(beginPage + NAV_SIZE - 1, totalPage);
39 | this.showPrev = beginPage!=1;
40 | this.showNext = endPage!=totalPage;
41 | }
42 |
43 | public String getQueryString() {
44 | return getQueryString(this.sc.getPage());
45 | }
46 |
47 | public String getQueryString(Integer page) {
48 | // ?page=10&pageSize=10&option=A&keyword=title
49 | return UriComponentsBuilder.newInstance()
50 | .queryParam("page", page)
51 | .queryParam("pageSize", sc.getPageSize())
52 | .queryParam("option", sc.getOption())
53 | .queryParam("keyword", sc.getKeyword())
54 | .build().toString();
55 | }
56 |
57 | void print() {
58 | System.out.println("page="+ sc.getPage());
59 | System.out.print(showPrev? "PREV " : "");
60 |
61 | for(int i=beginPage;i<=endPage;i++) {
62 | System.out.print(i+" ");
63 | }
64 | System.out.println(showNext? " NEXT" : "");
65 | }
66 |
67 | public SearchCondition getSc() {
68 | return sc;
69 | }
70 |
71 | public void setSc(SearchCondition sc) {
72 | this.sc = sc;
73 | }
74 |
75 | public int getTotalCnt() {
76 | return totalCnt;
77 | }
78 |
79 | public void setTotalCnt(int totalCnt) {
80 | this.totalCnt = totalCnt;
81 | }
82 |
83 | public boolean isShowNext() {
84 | return showNext;
85 | }
86 |
87 | public void setShowNext(boolean showNext) {
88 | this.showNext = showNext;
89 | }
90 |
91 | public int getBeginPage() {
92 | return beginPage;
93 | }
94 |
95 | public void setBeginPage(int beginPage) {
96 | this.beginPage = beginPage;
97 | }
98 |
99 | public int getNAV_SIZE() {
100 | return NAV_SIZE;
101 | }
102 |
103 | public int getTotalPage() {
104 | return totalPage;
105 | }
106 |
107 | public void setTotalPage(int totalPage) {
108 | this.totalPage = totalPage;
109 | }
110 |
111 | public int getEndPage() {
112 | return endPage;
113 | }
114 |
115 | public void setEndPage(int endPage) {
116 | this.endPage = endPage;
117 | }
118 |
119 | public boolean isShowPrev() {
120 | return showPrev;
121 | }
122 |
123 | public void setShowPrev(boolean showPrev) {
124 | this.showPrev = showPrev;
125 | }
126 |
127 | @Override
128 | public String toString() {
129 | return "PageHandler{" +
130 | "sc=" + sc +
131 | ", totalCnt=" + totalCnt +
132 | ", showNext=" + showNext +
133 | ", beginPage=" + beginPage +
134 | ", NAV_SIZE=" + NAV_SIZE +
135 | ", totalPage=" + totalPage +
136 | ", endPage=" + endPage +
137 | ", showPrev=" + showPrev +
138 | '}';
139 | }
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/ch4/SearchCondition.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.domain;
2 |
3 | import org.springframework.web.util.UriComponentsBuilder;
4 |
5 | import static java.lang.Math.*;
6 | import static java.util.Objects.requireNonNullElse;
7 |
8 | public class SearchCondition {
9 | private Integer page = 1;
10 | private Integer pageSize = DEFAULT_PAGE_SIZE;
11 | private String option = "";
12 | private String keyword = "";
13 | // private Integer offset;
14 |
15 | public static final int MIN_PAGE_SIZE = 5;
16 | public static final int DEFAULT_PAGE_SIZE = 10;
17 | public static final int MAX_PAGE_SIZE = 50;
18 |
19 | public SearchCondition(){}
20 |
21 | public SearchCondition(Integer page, Integer pageSize) {
22 | this(page, pageSize, "", "");
23 | }
24 |
25 | public SearchCondition(Integer page, Integer pageSize, String option, String keyword) {
26 | this.page = page;
27 | this.pageSize = pageSize;
28 | this.option = option;
29 | this.keyword = keyword;
30 | }
31 |
32 | public String getQueryString() {
33 | return getQueryString(page);
34 | }
35 |
36 | public String getQueryString(Integer page) {
37 | // ?page=10&pageSize=10&option=A&keyword=title
38 | return UriComponentsBuilder.newInstance()
39 | .queryParam("page", page)
40 | .queryParam("pageSize", pageSize)
41 | .queryParam("option", option)
42 | .queryParam("keyword", keyword)
43 | .build().toString();
44 | }
45 | public Integer getPage() {
46 | return page;
47 | }
48 |
49 | public void setPage(Integer page) {
50 | this.page = page;
51 | }
52 |
53 | public Integer getPageSize() {
54 | return pageSize;
55 | }
56 |
57 | public void setPageSize(Integer pageSize) {
58 | this.pageSize = requireNonNullElse(pageSize, DEFAULT_PAGE_SIZE);
59 |
60 | // MIN_PAGE_SIZE <= pageSize <= MAX_PAGE_SIZE
61 | this.pageSize = max(MIN_PAGE_SIZE, min(this.pageSize, MAX_PAGE_SIZE));
62 | }
63 |
64 | public String getOption() {
65 | return option;
66 | }
67 |
68 | public void setOption(String option) {
69 | this.option = option;
70 | }
71 |
72 | public String getKeyword() {
73 | return keyword;
74 | }
75 |
76 | public void setKeyword(String keyword) {
77 | this.keyword = keyword;
78 | }
79 |
80 | public Integer getOffset() {
81 | return (page-1)*pageSize;
82 | }
83 |
84 | @Override
85 | public String toString() {
86 | return "SearchCondition{" +
87 | "page=" + page +
88 | ", pageSize=" + pageSize +
89 | ", option='" + option + '\'' +
90 | ", keyword='" + keyword + '\'' +
91 | '}';
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/ch4/SimpleRestController.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.controller;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.springframework.stereotype.*;
5 | import org.springframework.web.bind.annotation.*;
6 |
7 | @Controller
8 | public class SimpleRestController {
9 | @GetMapping("/ajax")
10 | public String ajax() {
11 | return "ajax";
12 | }
13 |
14 | @PostMapping("/send")
15 | @ResponseBody
16 | public Person test(@RequestBody Person p) {
17 | System.out.println("p = " + p);
18 | p.setName("ABC");
19 | p.setAge(p.getAge() + 10);
20 |
21 | return p;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ch4/User.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.domain;
2 |
3 | import java.util.Date;
4 | import java.util.Objects;
5 |
6 | public class User {
7 | private String id;
8 | private String pwd;
9 | private String name;
10 | private String email;
11 | private Date birth;
12 | private String sns;
13 | private Date reg_date;
14 |
15 | public User(){}
16 | public User(String id, String pwd, String name, String email, Date birth, String sns, Date reg_date) {
17 | this.id = id;
18 | this.pwd = pwd;
19 | this.name = name;
20 | this.email = email;
21 | this.birth = birth;
22 | this.sns = sns;
23 | this.reg_date = reg_date;
24 | }
25 |
26 | @Override
27 | public boolean equals(Object o) {
28 | if (this == o) return true;
29 | if (o == null || getClass() != o.getClass()) return false;
30 | User user = (User) o;
31 | return id.equals(user.id) && Objects.equals(pwd, user.pwd) && Objects.equals(name, user.name) && Objects.equals(email, user.email) && Objects.equals(birth, user.birth) && Objects.equals(sns, user.sns);
32 | }
33 |
34 | @Override
35 | public int hashCode() {
36 | return Objects.hash(id, pwd, name, email, birth, sns, reg_date);
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return "User{" +
42 | "id='" + id + '\'' +
43 | ", pwd='" + pwd + '\'' +
44 | ", name='" + name + '\'' +
45 | ", email='" + email + '\'' +
46 | ", birth=" + birth +
47 | ", sns='" + sns + '\'' +
48 | ", reg_date=" + reg_date +
49 | '}';
50 | }
51 |
52 | public String getId() {
53 | return id;
54 | }
55 |
56 | public void setId(String id) {
57 | this.id = id;
58 | }
59 |
60 | public String getPwd() {
61 | return pwd;
62 | }
63 |
64 | public void setPwd(String pwd) {
65 | this.pwd = pwd;
66 | }
67 |
68 | public String getName() {
69 | return name;
70 | }
71 |
72 | public void setName(String name) {
73 | this.name = name;
74 | }
75 |
76 | public String getEmail() {
77 | return email;
78 | }
79 |
80 | public void setEmail(String email) {
81 | this.email = email;
82 | }
83 |
84 | public Date getBirth() {
85 | return birth;
86 | }
87 |
88 | public void setBirth(Date birth) {
89 | this.birth = birth;
90 | }
91 |
92 | public String getSns() {
93 | return sns;
94 | }
95 |
96 | public void setSns(String sns) {
97 | this.sns = sns;
98 | }
99 |
100 | public Date getReg_date() {
101 | return reg_date;
102 | }
103 |
104 | public void setReg_date(Date reg_date) {
105 | this.reg_date = reg_date;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/ch4/UserDao.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 |
5 | public interface UserDao {
6 | User selectUser(String id) throws Exception;
7 | int deleteUser(String id) throws Exception;
8 | int insertUser(User user) throws Exception;
9 | int updateUser(User user) throws Exception;
10 | int count() throws Exception;
11 | void deleteAll() throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/ch4/UserDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.stereotype.Component;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import javax.sql.DataSource;
9 | import java.sql.Connection;
10 | import java.sql.PreparedStatement;
11 | import java.sql.ResultSet;
12 | import java.sql.SQLException;
13 | import java.util.Date;
14 |
15 | @Repository
16 | public class UserDaoImpl implements UserDao {
17 | @Autowired
18 | DataSource ds;
19 |
20 | @Override
21 | public int deleteUser(String id) throws Exception {
22 | int rowCnt = 0;
23 | String sql = "DELETE FROM user_info WHERE id= ? ";
24 |
25 | try ( // try-with-resources - since jdk7
26 | Connection conn = ds.getConnection();
27 | PreparedStatement pstmt = conn.prepareStatement(sql);
28 | ){
29 | pstmt.setString(1, id);
30 | return pstmt.executeUpdate(); // insert, delete, update
31 | // } catch (Exception e) {
32 | // e.printStackTrace();
33 | // throw e;
34 | }
35 | }
36 |
37 | @Override
38 | public User selectUser(String id) throws Exception {
39 | User user = null;
40 | String sql = "SELECT * FROM user_info WHERE id= ? ";
41 |
42 | try (
43 | Connection conn = ds.getConnection();
44 | PreparedStatement pstmt = conn.prepareStatement(sql);
45 | ResultSet rs = pstmt.executeQuery(); // select
46 | ){
47 | pstmt.setString(1, id);
48 |
49 | if (rs.next()) {
50 | user = new User();
51 | user.setId(rs.getString(1));
52 | user.setPwd(rs.getString(2));
53 | user.setName(rs.getString(3));
54 | user.setEmail(rs.getString(4));
55 | user.setBirth(new Date(rs.getDate(5).getTime()));
56 | user.setSns(rs.getString(6));
57 | user.setReg_date(new Date(rs.getTimestamp(7).getTime()));
58 | }
59 | }
60 |
61 | return user;
62 | }
63 |
64 | // 사용자 정보를 user_info테이블에 저장하는 메서드
65 | @Override
66 | public int insertUser(User user) throws Exception {
67 | int rowCnt = 0;
68 | String sql = "INSERT INTO user_info VALUES (?,?,?,?,?,?, now()) ";
69 |
70 | try(
71 | Connection conn = ds.getConnection();
72 | PreparedStatement pstmt = conn.prepareStatement(sql); // SQL Injection공격, 성능향상
73 | ){
74 | pstmt.setString(1, user.getId());
75 | pstmt.setString(2, user.getPwd());
76 | pstmt.setString(3, user.getName());
77 | pstmt.setString(4, user.getEmail());
78 | pstmt.setDate(5, new java.sql.Date(user.getBirth().getTime()));
79 | pstmt.setString(6, user.getSns());
80 |
81 | return pstmt.executeUpdate();
82 | }
83 | }
84 |
85 | @Override
86 | public int updateUser(User user) throws Exception {
87 | int rowCnt = 0;
88 |
89 | String sql = "UPDATE user_info " +
90 | "SET pwd = ?, name=?, email=?, birth =?, sns=?, reg_date=? " +
91 | "WHERE id = ? ";
92 |
93 | try (
94 | Connection conn = ds.getConnection();
95 | PreparedStatement pstmt = conn.prepareStatement(sql);
96 | ){
97 | pstmt.setString(1, user.getPwd());
98 | pstmt.setString(2, user.getName());
99 | pstmt.setString(3, user.getEmail());
100 | pstmt.setDate(4, new java.sql.Date(user.getBirth().getTime()));
101 | pstmt.setString(5, user.getSns());
102 | pstmt.setTimestamp(6, new java.sql.Timestamp(user.getReg_date().getTime()));
103 | pstmt.setString(7, user.getId());
104 |
105 | rowCnt = pstmt.executeUpdate();
106 | }
107 |
108 | return rowCnt;
109 | }
110 |
111 | @Override
112 | public int count() throws Exception {
113 | String sql = "SELECT count(*) FROM user_info ";
114 |
115 | try(
116 | Connection conn = ds.getConnection();
117 | PreparedStatement pstmt = conn.prepareStatement(sql);
118 | ResultSet rs = pstmt.executeQuery();
119 | ){
120 | rs.next();
121 | int result = rs.getInt(1);
122 |
123 | return result;
124 | }
125 | }
126 |
127 | @Override
128 | public void deleteAll() throws Exception {
129 | try (Connection conn = ds.getConnection();)
130 | {
131 | String sql = "DELETE FROM user_info ";
132 | PreparedStatement pstmt = conn.prepareStatement(sql);
133 | pstmt.executeUpdate();
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/ch4/UserDaoImplTest.java:
--------------------------------------------------------------------------------
1 | package com.fastcampus.ch4.dao;
2 |
3 | import com.fastcampus.ch4.domain.*;
4 | import org.junit.*;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.test.context.ContextConfiguration;
8 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
9 |
10 | import java.util.Calendar;
11 | import java.util.Date;
12 |
13 | import static org.junit.Assert.*;
14 |
15 | @RunWith(SpringJUnit4ClassRunner.class)
16 | @ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
17 | public class UserDaoImplTest {
18 | @Autowired
19 | UserDao userDao;
20 | Calendar cal;
21 |
22 | @Before // 각 테스트가 수행되기 직전에 이 메서드가 실행된다.
23 | public void init() {
24 | cal = Calendar.getInstance();
25 | cal.clear();
26 | cal.set(2021, 1, 1);
27 | }
28 |
29 | @Test(expected = Exception.class) // 예외가 발생해야 테스트 통과
30 | public void insertUser() throws Exception {
31 | userDao.deleteAll();
32 | assertTrue(userDao.count()==0);
33 |
34 | User user = new User("asdf", "1234", "abc", "aaa@aaa.com", new Date(cal.getTimeInMillis()), "fb", new Date());
35 | assertTrue(userDao.insertUser(user)==1);
36 | assertTrue(userDao.count()==1);
37 |
38 | User user2 = userDao.selectUser(user.getId());
39 | assertTrue(user.equals(user2));
40 |
41 | User user3 = new User("asdf222", "1234", "abc", "aaa@aaa.com", new Date(cal.getTimeInMillis()), "fb", new Date());
42 | assertTrue(userDao.insertUser(user3)==1);
43 | assertTrue(userDao.count()==2);
44 |
45 | // 같은 데이터를 2번 입력하고 예외가 발생하는지 테스트
46 | userDao.insertUser(user); // java.sql.SQLIntegrityConstraintViolationException예외발생. Duplicate entry 'asdf' for key 'PRIMARY'
47 | }
48 |
49 | @Test
50 | public void deleteUser() throws Exception {
51 | userDao.deleteAll();
52 | assertTrue(userDao.count()==0);
53 |
54 | User user = new User("asdf", "1234", "abc", "aaa@aaa.com", new Date(cal.getTimeInMillis()), "fb", new Date());
55 | assertTrue(userDao.insertUser(user)==1);
56 | assertTrue(userDao.count()==1);
57 |
58 | User user2 = userDao.selectUser(user.getId());
59 | assertTrue(user.equals(user2));
60 | assertTrue(userDao.deleteUser(user.getId())==1);
61 |
62 | user = userDao.selectUser("asdf");
63 | assertTrue(user==null);
64 | assertTrue(userDao.count()==0);
65 | }
66 |
67 | @Test
68 | public void selectUser() throws Exception {
69 | userDao.deleteAll();
70 | assertTrue(userDao.count()==0);
71 |
72 | User user = new User("asdf", "1234", "abc", "aaa@aaa.com", new Date(cal.getTimeInMillis()), "fb", new Date());
73 | assertTrue(userDao.insertUser(user)==1);
74 |
75 | User user2 = userDao.selectUser(user.getId());
76 | assertTrue(user.equals(user2));
77 |
78 | user2 = userDao.selectUser("aaaaaaa");
79 | assertTrue(user2==null);
80 | }
81 |
82 | @Test
83 | public void updateUser() throws Exception {
84 | userDao.deleteAll();
85 | User user = new User("asdf", "1234", "abc", "aaa@aaa.com", new Date(cal.getTimeInMillis()), "fb", new Date());
86 | int rowCnt = userDao.insertUser(user);
87 | assertTrue(rowCnt==1);
88 |
89 | user.setPwd("4321");
90 | user.setEmail("bbb@bbb.com");
91 | rowCnt = userDao.updateUser(user);
92 | assertTrue(rowCnt==1);
93 |
94 | User user2 = userDao.selectUser(user.getId());
95 | System.out.println("user = " + user);
96 | System.out.println("user2 = " + user2);
97 | assertTrue(user.equals(user2));
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/ch4/ajax.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 |
3 |
4 | Title
5 |
6 |
7 |
8 | {name:"abc", age:10}
9 |
10 | Data From Server :
11 |
12 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ch4/boardList.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 |
4 |
5 |
6 |
7 |
8 | fastcampus
9 |
10 |
11 |
12 |
22 |
This is BOARD
23 | This is BOARD
24 | This is BOARD
25 | This is BOARD
26 | This is BOARD
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ch4/boardMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
11 | DELETE FROM board
12 |
13 |
14 |
15 | DELETE FROM board WHERE bno = #{bno} and writer = #{writer}
16 |
17 |
18 |
19 | INSERT INTO board
20 | (title, content, writer)
21 | VALUES
22 | (#{title}, #{content}, #{writer})
23 |
24 |
25 |
30 |
31 |
32 | SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
33 | FROM board
34 |
35 |
36 |
40 |
41 |
46 |
47 |
48 | UPDATE board
49 | SET title = #{title}
50 | , content = #{content}
51 | , up_date = now()
52 | WHERE bno = #{bno}
53 |
54 |
55 |
60 |
61 |
62 | UPDATE board
63 | SET view_cnt = view_cnt + 1
64 | WHERE bno = #{bno}
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ch4/boardMapper2.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
11 | DELETE FROM board
12 |
13 |
14 |
15 | DELETE FROM board WHERE bno = #{bno} and writer = #{writer}
16 |
17 |
18 |
19 | INSERT INTO board
20 | (title, content, writer)
21 | VALUES
22 | (#{title}, #{content}, #{writer})
23 |
24 |
25 |
30 |
31 |
32 | SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
33 | FROM board
34 |
35 |
36 |
40 |
41 |
46 |
47 |
48 | UPDATE board
49 | SET title = #{title}
50 | , content = #{content}
51 | , up_date = now()
52 | WHERE bno = #{bno}
53 |
54 |
55 |
60 |
61 |
62 | UPDATE board
63 | SET view_cnt = view_cnt + 1
64 | WHERE bno = #{bno}
65 |
66 |
67 |
68 |
69 |
70 | AND title LIKE concat('%', #{keyword}, '%')
71 |
72 |
73 | AND writer LIKE concat('%', #{keyword}, '%')
74 |
75 |
76 | AND (title LIKE concat('%', #{keyword}, '%')
77 | OR content LIKE concat('%', #{keyword}, '%'))
78 |
79 |
80 |
81 |
82 |
90 |
91 |
97 |
98 |
--------------------------------------------------------------------------------
/ch4/commentMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | DELETE FROM comment
8 | WHERE bno = #{bno}
9 |
10 |
11 |
15 |
16 |
17 | DELETE FROM comment WHERE cno = #{cno} AND commenter = #{commenter}
18 |
19 |
20 |
21 | INSERT INTO comment
22 | (bno, pcno, comment, commenter, reg_date, up_date)
23 | VALUES
24 | (#{bno}, #{pcno}, #{comment}, #{commenter}, now(), now())
25 |
26 |
27 |
33 |
34 |
39 |
40 |
41 | UPDATE comment
42 | SET comment = #{comment}
43 | , up_date = now()
44 | WHERE cno = #{cno} and commenter = #{commenter}
45 |
46 |
47 |
--------------------------------------------------------------------------------
/ch4/create_table_board.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `board` (
2 | `bno` int(11) NOT NULL AUTO_INCREMENT,
3 | `title` varchar(45) NOT NULL,
4 | `content` text NOT NULL,
5 | `writer` varchar(30) DEFAULT NULL,
6 | `view_cnt` int(11) DEFAULT '0',
7 | `comment_cnt` int(11) DEFAULT '0',
8 | `reg_date` datetime DEFAULT CURRENT_TIMESTAMP,
9 | `up_date` datetime DEFAULT CURRENT_TIMESTAMP,
10 | PRIMARY KEY (`bno`)
11 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
12 |
--------------------------------------------------------------------------------
/ch4/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page session="false"%>
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | fastcampus
12 |
13 |
14 |
15 |
16 |
26 |
27 |
This is HOME
28 | This is HOME
29 | This is HOME
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ch4/log4jdbc.log4j2.properties:
--------------------------------------------------------------------------------
1 | log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
2 |
--------------------------------------------------------------------------------
/ch4/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ch4/loginForm.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"%>
2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3 | <%@ page session="false"%>
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | fastcampus
12 |
13 |
14 |
60 |
61 |
62 |
72 | " method="post" onsubmit="return formCheck(this);">
73 | Login
74 |
75 |
76 | ${URLDecoder.decode(param.msg)}
77 |
78 |
79 |
80 |
81 |
82 |
83 |
88 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/ch4/menu.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin : 0;
4 | padding: 0;
5 | }
6 |
7 | a { text-decoration: none; }
8 |
9 | ul {
10 | list-style-type: none;
11 | height: 48px;
12 | width: 100%;
13 | background-color: #30426E;
14 | display: flex;
15 | }
16 |
17 | ul > li {
18 | color: lightgray;
19 | height : 100%;
20 | width:90px;
21 | display:flex;
22 | align-items: center;
23 | }
24 |
25 | ul > li > a {
26 | color: lightgray;
27 | margin:auto;
28 | padding: 10px;
29 | font-size:20px;
30 | align-items: center;
31 | }
32 |
33 | ul > li > a:hover {
34 | color :white;
35 | border-bottom: 3px solid rgb(209, 209, 209);
36 | }
37 |
38 | #logo {
39 | color:white;
40 | font-size: 18px;
41 | padding-left:40px;
42 | margin-right:auto;
43 | display: flex;
44 | }
45 |
--------------------------------------------------------------------------------
/ch4/mybatis-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ch4/readme.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch4/readme.md
--------------------------------------------------------------------------------
/ch4/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/ch4/servlet-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/ch4/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | contextConfigLocation
9 | /WEB-INF/spring/root-context.xml
10 |
11 |
12 |
13 |
14 | org.springframework.web.context.ContextLoaderListener
15 |
16 |
17 |
18 |
19 | appServlet
20 | org.springframework.web.servlet.DispatcherServlet
21 |
22 | contextConfigLocation
23 | /WEB-INF/spring/appServlet/servlet-context.xml
24 |
25 | 1
26 |
27 |
28 |
29 | appServlet
30 | /
31 |
32 |
33 |
34 | encodingFilter
35 | org.springframework.web.filter.CharacterEncodingFilter
36 |
37 | encoding
38 | UTF-8
39 |
40 |
41 | forceEncoding
42 | true
43 |
44 |
45 |
46 |
47 | encodingFilter
48 | /*
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/ch5/readme.md:
--------------------------------------------------------------------------------
1 | .
2 |
--------------------------------------------------------------------------------
/ch5/springbasic.mwb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch5/springbasic.mwb
--------------------------------------------------------------------------------
/ch5/프로젝트_파일목록.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch5/프로젝트_파일목록.xlsx
--------------------------------------------------------------------------------
/ch5/화면정의서_샘플.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch5/화면정의서_샘플.pptx
--------------------------------------------------------------------------------
/ch5/화면정의서_샘플_주주마켓.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch5/화면정의서_샘플_주주마켓.pdf
--------------------------------------------------------------------------------
/ch5/화면정의서_요소.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/ch5/화면정의서_요소.pptx
--------------------------------------------------------------------------------
/download/MySQL57설치방법_MacOS_m1.md:
--------------------------------------------------------------------------------
1 | ## MySQL8.x버전을 M1칩 Mac에 설치하는 방법
2 |
3 | 아래의 링크를 클릭하세요.
4 |
5 | https://codechobo.tistory.com/31
6 |
--------------------------------------------------------------------------------
/download/ch2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch2.zip
--------------------------------------------------------------------------------
/download/ch2_final.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch2_final.zip
--------------------------------------------------------------------------------
/download/ch2_final_mac.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch2_final_mac.zip
--------------------------------------------------------------------------------
/download/ch3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch3.zip
--------------------------------------------------------------------------------
/download/ch3_final.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch3_final.zip
--------------------------------------------------------------------------------
/download/ch4.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/ch4.zip
--------------------------------------------------------------------------------
/download/firstSpring.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/firstSpring.zip
--------------------------------------------------------------------------------
/download/myportfolio.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/myportfolio.zip
--------------------------------------------------------------------------------
/download/project_import1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/project_import1.PNG
--------------------------------------------------------------------------------
/download/project_import2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/project_import2.PNG
--------------------------------------------------------------------------------
/download/readme.md:
--------------------------------------------------------------------------------
1 | # 강의와 관련된 파일입니다.
2 | - firstSpring.zip - STS3에서 Spring MVC프로젝트가 생성되지 않는 분들은 다운받아서 import하세요.
3 | STS3메뉴에서 File > Import에서 General > Existing Projects into Workspace클릭후, Next클릭(project_import1.PNG)
4 | Select archive file클릭하고, 옆의 Browse버튼 클릭해서 firstSpring.zip이 저장된 폴더를 지정하고, Finish클릭.(project_import2.PNG)
5 | - ch2.zip - ch2강의 시작할 때 생성하는 ch2프로젝트 파일. STS3에서 Spring MVC프로젝트가 생성되지 않는 분들은 다운받아서 import하세요.
6 | firstSpring.zip과 같은 방법으로 import하시면 됩니다.
7 | - ch2_final.zip - ch2강의에서 작성한 프로젝트의 최종 버전. 위와 같은 방법으로 import하세요.
8 |
9 |
--------------------------------------------------------------------------------
/download/프로젝트_파일목록.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/프로젝트_파일목록.xlsx
--------------------------------------------------------------------------------
/download/화면정의서_샘플.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/화면정의서_샘플.pptx
--------------------------------------------------------------------------------
/download/화면정의서_샘플_주주마켓.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/화면정의서_샘플_주주마켓.pdf
--------------------------------------------------------------------------------
/download/화면정의서_요소.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/화면정의서_요소.pptx
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_01_원격실행.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_01_원격실행.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_02_HTTP요청과응답_실습.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_02_HTTP요청과응답_실습.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_03_HTTP클라이언트서버.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_03_HTTP클라이언트서버.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_04_HTTP요청과응답_이론.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_04_HTTP요청과응답_이론.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_05_SpringMVC.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_05_SpringMVC.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_06_Servlet_JSP.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_06_Servlet_JSP.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_07_RequestParam_ModelAttribute.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_07_RequestParam_ModelAttribute.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_08_redirect와forward.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_08_redirect와forward.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_09_RequestMapping.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_09_RequestMapping.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_10_쿠키.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_10_쿠키.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_11_세션.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_11_세션.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_12_예외처리.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_12_예외처리.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_13_DispatcherServlet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_13_DispatcherServlet.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch2_14_데이터의변환과검증.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch2_14_데이터의변환과검증.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_1_스프링DI_흉내내기1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_1_스프링DI_흉내내기1.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_2_스프링DI_활용하기_이론1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_2_스프링DI_활용하기_이론1.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_3_DAO의작성과적용.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_3_DAO의작성과적용.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_4_Transaction_commit_rollback.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_4_Transaction_commit_rollback.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_5_AOP의개념과용어.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_5_AOP의개념과용어.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch3_6_서비스계층의분리와Transactional.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch3_6_서비스계층의분리와Transactional.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_01_MyBatis의개요와설정.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_01_MyBatis의개요와설정.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_02_MyBatis로DAO작성하기.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_02_MyBatis로DAO작성하기.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_03_게시판목록만들기와페이징TDD.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_03_게시판목록만들기와페이징TDD.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_04_게시판CRUD기능구현1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_04_게시판CRUD기능구현1.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_05_게시판검색기능추가.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_05_게시판검색기능추가.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_06_REST_API와Ajax.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_06_REST_API와Ajax.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch4_07_댓글기능구현1_DAO작성.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch4_07_댓글기능구현1_DAO작성.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch5_01_02_git의기본명령어와원리1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch5_01_02_git의기본명령어와원리1.pdf
--------------------------------------------------------------------------------
/download/강의자료/[스프링의정석_기초편]ch5_03_git의기본명령어와원리2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/castello/spring_basic/5f6f2a077ff25410619a52c35348cbbf21454f8c/download/강의자료/[스프링의정석_기초편]ch5_03_git의기본명령어와원리2.pdf
--------------------------------------------------------------------------------
/download/강의자료/readme.md:
--------------------------------------------------------------------------------
1 | # 강의자료입니다.
2 |
--------------------------------------------------------------------------------
/download/인텔리제이_단축키.md:
--------------------------------------------------------------------------------
1 | # 인텔리제이 단축키 목록
2 |
--------------------------------------------------------------------------------