- Web Application Concept :
。Browser / HTML / CSS / Request / Response / Form / Session / Authentification
- Spring MVC :
。Dispatcher Servlet / View Resolvers / Model / View / Controller / Validation
VIEW:html,JSP처럼 client에게 보여주는 문서를 의미.
- Spring Boot :
。Starters / Auto Configuration .. etc
- Framework :
。Framework: 재사용이 가능한 요소들의 집합으로서 정해진 구조, 틀 안에서 application을 용이하게 개발하는 용도.
。JSP / JSTL / JPA / Bootstrap / Spring Security / MySQL / H2 DB해당 프로젝트에서 정의할 Spring Boot의 Starter와 Module dependency
- Spring Web :
spring-boot-starter-web
。Web Application 개발에 필요한 실행환경 제공하는 Starter
。Spring MVC를 이용하여 REST API를 포함한 Restful한 Web Application을 build시 사용.
▶ REST API를 구축하기 위해 필요한 dependency
。기본 embedded container로Apache Tomcat활용.
▶ Dependency를 정의한 경우 Spring / Spring MVC / Tomcat / JSON Conversion의 기능을 사용 가능.
- Spring Boot DevTools :
spring-boot-devtools
。코드 수정 시 수동으로 서버를 재시작하지 않아도 자동으로 재시작하여 Application을 변경하는 Spring Boot Module
JSP (Java Server Page) :
。HTML를 기반으로 Java 코드를 삽입 및 활용하여 동적 웹페이지를 생성하는 Server-side script언어
▶Java를HTML에서의Javascript와 유사한 역할로 활용할 수 있다.
。JSP가 실행 시Java servlet으로 변환 후 Web Application Server에 전달되어 기능을 수행하고 생성된 데이터는 Web Page와 함께 Client로 응답.
。 일반적으로 모든JSP파일은 Spring Boot에 의해 정의된 특정 폴더(src/main/resources) 내부에서 제작.<%-- sayHello.jsp --%> <!doctype html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p>hello</p> </body> </html> <%-- html 구문을 그대로 복사 & 붙여넣기! --%>
JSP태그 종류
- 주석 :
<%-- 내용 --%>- 선언 :
<%! 내용 %>
。선언 태그에서 선언 시 전역적으로 적용.- 지시자 :
<%@ 내용 %>지시자 종류
<%@ page %>
。해당 Page의 전체 속성 지정.
<%@ include %>
。별도의 페이지를 현재 페이지에 삽입
ex)JSP에JSPF를 삽입
<%@ taglib %>
。taglib: 사용자가 만든 tag library를 사용하기위해 사용하는JSP지시자.
ex) spring form taglib :
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
uri="tag library 위치"
prefix="tag를 지칭하는 이름"- 표현식
<%= 내용 %>- Scriptlet :
<% 내용 %>
。Scriptlet에서 선언 시 지역적으로 적용.- Java Bean 연결 :
<jsp:action></jsp:action>
。action
- Java Servlet :
。Java를 사용하여 웹페이지를 동적으로 생성하는 Server-side 프로그램
▶ Java 언어을 기반으로 Web Application 개발에 최적화한 library와 Class의 집합인API로서 , 해당 API에 맞는 library 또는 class를 상속 및 구현하여 구성한 class를 Servlet이라고 한다.
。Server-side에서 Web Client의 Request를 처리 후 Response.
。JSP가 HTML을 기준으로 Java 코드를 삽입하는 방식이면Servlet은 온전히 Java코드를 활용해 생성.
JSP Framework의 dependency 정의
。JSP를 tomcat에서 실행하려면 다음 dependency를 pom.xml에 정의 후 Maven 재실행.<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>
- JSP 파일의 공통경로 지정.
src/main/resources/META-INF/resources/WEB-INF/jsp/sayHello.jsp src/main/resources/META-INF/resources/WEB-INF/jsp/welcome.jsp src/main/resources/META-INF/resources/WEB-INF/jsp/login.jsp src/main/resources/META-INF/resources/WEB-INF/jsp/todos.jsp。JSP파일을 생성 시 다음처럼 코드의 경로가 불필요하게 중복되는 경우가 많다.
▶ 공통경로부분을application.properties에 접두어(prefix), 접미어(suffix)로 정의spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp。경로
src/main/resources/META-INF/resources/경로까지는 spring MVC에 의해 자동으로 식별.
▶ 그 이후의 공통적으로 겹치는 경로인/WEB-INF/jsp/를 접두사로 설정.
▶ 이후Controller Method를 통해 문자열"sayhello"가 반환시"/WEB-INF/jsp/sayhello.jsp"경로의 JSP파일을 자동으로 참조.
。 해당 @Controller가 선언된 Class는 @RequestMapping을 통해 URL이 부여된 Controller Method마다 해당 URL로 요청 시 문자열 , HTML , JSP를 반환.
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class sayHelloController { @RequestMapping("say-hello") @ResponseBody public String sayHello() { return "Hello World"; } @RequestMapping("say-hello-html") @ResponseBody public String sayHelloHtml() { StringBuffer sb = new StringBuffer(); sb.append("<!DOCTYPE html>"); sb.append("<html lang=\"kor\">"); sb.append("<head>"); sb.append("<title>My first HTML Page</title>"); sb.append("</head>"); sb.append("<body>"); sb.append("My first html page with body"); sb.append("</body>"); sb.append("</html>"); return sb.toString(); } @RequestMapping("say-hello-jsp") public String sayHelloJsp() { return "sayHello"; } }。
@Controller: Spring Framework에서 Class가Web Controller class를 정의.
▶ Client의 Request(URL)를 처리하고 Response를 보내는 역할을 수행.
。@RequestMapping:Controller Method에 선언하여 Method와 Client의 요청 URL과 Mapping하는 역할을 수행.
。@ResponseBody: 선언된Controller Method가 반환하는 Data를 그대로 Request URL의 Client에게 반환하는 역할 수행.
sayHello():
。localhost:8080/say-hello입력 시@ResponseBody를 통해 문자열"Hello World"을 그대로 브라우저에 전달하는Controller Method.
sayHelloHtml():
。http://localhost:8080/say-hello-html입력 시@ResponseBody를 통해 하드코딩 된 HTML Page 코드를 브라우저에 전달하는Controller Method.
▶ 해당 HTML Page 코드는StringBuffer에 입력된 후 한꺼번에 브라우저에 전달됨.
SayHelloJsp():
。localhost:8080/say-hello-jsp입력 시/WEB-INF/jsp/sayhello.jsp를 redirection 하는Controller Method.
▶application.properties에서 정의한 접두사 & 접미사와 jsp 파일명과 결합하여View Resolver에 의해 JSP 파일을 참조 및 실행.
。@ResponseBody를 선언하는 경우"/WEB-INF/jsp/sayhello.jsp"문자열을 브라우저에 그대로 전달하므로 사용하지않는다.
- 이때, 진입한 웹페이지 화면에서 마우스 오른쪽버튼을 눌러 Inspect -> Network -> Doc -> say-hello-jsp로 진입 시 다음 화면이 나옴.
- General :
。Http Request URL과 Request Method를 지시.
@Controller:
。Spring Framework에서 Class가Web Controller class일 경우@Component대신 선언.
▶@Component의 구체화된 Annotation 중 하나로서Spring bean역할 수행.
▶ 주로 Web Application REST API의 Controller를 정의 시 사용.
。Servlet과 같이 Client의 Request를 처리하고 Response를 보내는 역할을 수행.
。@Controller가 선언된 class는 보통HTTP Request를 처리하기위한Controller Method들을 포함한다.
▶ 각Controller Method는@RequestMapping를 선언하여 사용하며 특정 URL의 요청을 처리하는 기능을 정의.
。Query Parameter활용 시 사용자의 Request를 처리한 후 View로 객체를 전달하는 중간 제어자 역할도 수행.
@RequestMapping(value = "url"):
。@Controller이 선언된Web Controller Class의Controller Method를 정의 시 사용.
。클라이언트의 요청(url)과 해당Controller method를 mapping하는 annotation
▶ 해당 method는 요청을 처리하고 필요한 로직을 수행 후 응답 생성.
。URL Mapping 방식을 세밀하게 제어 가능.
@RequestMapping(value="url", method = RequestMethod.GET)
。URL을 통해localhost:8080/login으로 접속 시 해당 요청 URL의 Request Method에서 오직GET에 대해서만 해당 Controller Method를 사용.
▶method=RequestMethod.POST인 경우 해당 요청 URL의POST에 대해서만 해당 Controller Method를 사용.
@GetMapping(path="url")REST API 활용
。@RequestMapping(path="url", method = RequestMethod.GET)와 비슷한 기능.
▶ 선언 할 경우 URL을 통해 접속 시GET에 해당하는 Request에 대해서만 해당 Controller Method를 사용.
。REST API에 의한Path Variable를 정의할 경우path="URL"에{Path Variable이름}을 추가해야한다.
▶@GetMapping(path="/users/{id}")
。@PostMapping,@PutMapping등의 어노테이션이 존재
@ResponseBodyREST API 활용
。Controller Method의 return type을JSON,XMLformat의HTTP Response Body로 변환하여 Application에서 Client에게 반환.
▶ Server에서 Resource를 포함한 Response를 전송하기 위해@ResponseBody를 Controller Method에 선언하여HttpRequestBody의 객체(JSON)로 변환하여 Client에게 전송.
@Controller선언된 Class의 경우
。Controller Class의Controller Method에 선언.
▶ 선언된Controller Method가 반환하는 Data의 format을 그대로@RequestMapping로 Mapping된Request URL를 전송한 Client에게 반환하는 역할 수행.
▶ return하는 문자열 이름을 가지는View Resolver를 통한View의 조회를 무시하고HTTPResponseBody에 문자열을 그대로 반환.
@RestController선언된 Class의 경우
。Class에@RestController선언 시Controller Method자동적용되므로 별도로 명시할 필요는 없다.
- Http Status Code :
1XX: Informational ( 정보제공 )
。임시 응답
。현재 클라이언트의 요청까지는 처리되었으므로 계속 진행을 지시
2XX: Success ( 성공 )
。클라이언트의 요청이 서버에서 성공적으로 처리
200: 전송 성공201: Created :POST로 성공적으로 새로운 Resource가 생성됨.204: No Content : Client의 Request를 처리했으나, Response할 데이터가 존재하지 않음.
3XX: Redirection ( 리디렉션 )
。완전한 처리를 위해 추가 동작이 필요한 경우
。EX) 요청한 URL 웹문서가 이동했으므로 해당 주소로 다시 시도
4XX: Client Error ( 클라이언트 에러 )
。없는 페이지를 요청하는 경우
400: BadRequest : Client의 Request 구문이 문법상 오류 발생 또는Validation Error이 발생한 경우
▶ EX) 요청 메시지 내용이 잘못된 경우403: Client가 요청한 Resource에 대해 접근 권한이 없음을 지시404: Resource를 발견하지 못한 경우
5XX: Server Error ( 서버 에러 )
。서버 사정으로 메시지 처리에 문제가 발생한 경우.
。EX) 서버 부하 / DB 처리과정 오류 / Server에서 Exception이 발생한 경우.
500: Server Error : Server에서 오류발생 또는 Exception 발견.
。특정 URL을 통해 정보를 전달하는 방법 : ( @RequestParam , ModelMap )
- URL을
localhost:8080/login?name=wjdtn747로 추가적인 요청 파라미터를 전달 시 처리하는 Cotroller Method 작성하기.<!-- login.jsp --> <!doctype html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> My Login Page with ${name} </body> </html>// gotoLoginPage import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class gotoLoginPage { @RequestMapping("login") public String gotoLoginPage(@RequestParam String name, ModelMap model) { model.put("name",name); return "login"; } }
localhost:8080/login?name=wjdtn747로 Query Parameter를 포함한 URL를 Request 할 경우
。@RequestParam String name: URL의 Query Parameter인name=wjdtn747의 값wjdtn747를 String type으로 갖는 변수 name 설정.
。ModelMap model:ModelMap의 객체 생성
。ModelMap객체.put("JSP변수명",값): VIEW에서 설정된 변수(${name})로 값을 전달.
。application.properties의 접두사, 접미사를 통해/WEB-INF/jsp/login.jsp로 결합 및 redirection되어View Resolver에 의해 JSP파일이 참조 및 실행.
@RequestParam:
。URL의Query Parameter를Controller Method의 매개변수로 Binding.
。ex)/login?name=wjdtn747일 경우,
매개변수에@RequestParam String name설정 시 URL의Query Parameter의name값 wjdtn747이 전달됨.
。@RequestParam는GET의 Query Parameter 뿐만 아니라,POSTmethod를 통해 전달되는 Form Data도 전달 받을 수 있다.
ModelMap:
。Modelinterface를 구현한 구현체.
。Controller Method의 매개변수에ModelMap modelmap객체를 추가한 후modelmap객체.put()을 통해 data를 추가하여 VIEW(jsp)로 전달.
▶ JSP에 전달할 Data를ModelMap에 전부 추가한 후 한꺼번에JSP에 전달.
- Model :
。스프링이 지원하는 기능으로서 key, value로 구성된 HashMap.
。ModelMap으로Modelinterface를 구현.
。View에 전달할 데이터를 저장 가능하며View에서는 expression language(${변수명})로 해당 데이터를 활용.
ModelMap객체.put("JSP변수명",값)
。ControllerMethod내부에서 JSP에서 정의된 JSP변수명과 전달값을 입력.
▶JSP에서는 Expression Language(ex.${변수이름})를 이용해 변수에 데이터를 전달.
ModelMap객체.get("VIEW의 변수이름")
。Model을 통해VIEW에서 정의된 해당 JSP변수의 값을 Java로 가져오는 역할을 수행.
ModelMap객체.addAttribute("JSP변수명",변수값):
。JSP의Expression Language로 작성된 변수(${변수명})에 Data를 전달하는 역할을 수행.
。ModelMap객체.put("변수명",변수값)과 동일한 기능으로 작용하지만@SessionAttributes("JSP변수명")으로Model에 저장되는 data를HttpSession에 전달 시 ModelMap객체.addAttribute를 사용.
- Web Application 구동 순서. MVC 설명
- #1.
Dispatcher Servlet에서 Client로 부터의HttpRequest를 수신.
- #2.
Dispatcher Servlet에서HttpRequest의 URL을 통해 해당 요청을 처리할 수 있는 적절한Controller의Controller Method를 식별.
ex)localhost:8080/login일 경우,@Controller가 선언된 Controller class의@RequestMapping("Login")이 선언된Controller Method를 식별.
- #3. 해당
Controller method가Model을 생성 및View의 이름을 return.
。Controller Method의 매개변수에ModelMap model을 생성하여model.put("name",name);을 통해ModelMap에 name라는 변수를 생성하여 전달값을 넣고, "Login" 문자열의 View 이름을 return.
- #4.return된 View 이름을 통해 Rendering할 적절한 View를
ViewResolver로 식별하여 해당 View의 코드를 실행.
。application.properties에서prefix,suffix를 설정하고,Controller Method에서 return된 "Login"을 이용하여 결합된/WEB-INF/jsp/Login.jsp로View Resolver를 통해Login.jsp를 찾아서 실행.
- #5. 이후 HttpResponse를 브라우저로 return.
- 사용자가 ID, PW를 입력 시 해당 사용자의 ID와 PW를 검증 후 간단한 환영 페이지 출력해보기.
- 이때 검증하는 단계는 Spring Security Framework를 이용해야하여 검증해야하나, 현 단계에서는 안함.
- JSP를 통해 로그인 페이지 작성하기
활용할 html 구문 HTML 코드
<form>:
。사용자 의견, 정보를 알기 위해 입력할 큰 틀을 생성하는데 사용.
。페이지 내에서 입력양식 전체를 의미하는 추상적 개념의 태그.
。입력된 데이터를 한번에 서버로 전송하여 웹서버가 처리 후 결과에 따른 또 다른 웹페이지를 보여줌.
method="":
。Http Resquest Method의GET,POST.. 로 임의 설정.
。기본값은GET
。<form method="get">로 내부의<input>된 정보를 submit 할 경우 URL의 Queryparameter로서 전달됨.
。<form method="post">로 내부의<input>된 정보를 submit 할 경우<form>의 data로서 전달됨.
▶ Form Data의 경우Chrome의Inspection - Network - Doc - Payload를 통해 확인!
▶POST가 보안측면에서 더 안전하다.<input type="text">:
。<form>의 자식요소로서 사용자로부터 입력을 받을 수 있는input field를 정의
- Java의 Controller Class와 JSP의 HTML 코드 설정
// gotoLoginPage.java @Controller public class gotoLoginPage { @RequestMapping("login") public String gotoLoginPage() { return "login"; } }。
localhost:8080/login입력 시application.properties에 정의된prefix,suffix와Controller Method에서 return된"login"을 통해/WEB-INF/jsp/login.jsp를ViewResolver를 통해 검색하여 실행.<!-- login.jsp --> <html lang="kor"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <form> <h2>My Login Page</h2> <label for="textid">Id</label> <input type="text" id="textid" name="idName"> <label for="textpw">Password</label> <input type="password" id="textpw" name="idPassword"> <button type="submit">submit</button> </form> </body> </html>
。각html element를 하나의<form>에 넣은 후 각각의<input>field에 값을 입력 후<button>을 누를 경우 Client에서 Server에 Request 되는 Request URL의 일부로서 query parameter에 포함.
▶<input>의name=""는 query parameter의 변수명으로 설정되어?변수명=입력값꼴로 전달됨을 확인 가능.
。Application에 액세스할 때마다 인터넷의 수많은 라우터를 통하여 사용자 정보를 URL의 QueryParameter로서 전송하는건 보안상 안전하지않다.
。Http Request Method를GET으로 설정하여 사용자 정보 전송 시 URL의 Query Parameter로서 전송됨.
▶<form method="post">를 설정하여 Http Request Method를POST로 설정하여 사용자의 정보가<form>data로서 전달되도록 설정.
。<form method="post">으로 수정하여 ID와 PW를 입력할 경우 사용자의 정보가 URL의 Query parameter가 아닌 Form Data의 일부로서 전달됨.
▶ Form Data의 경우Chrome의Inspection - Network - Doc - Payload를 통해 확인!
- 웹사이트로 전송하는 모든 사용자정보는 항상
POST를 사용해 Form Data의 일부로서 전송하는것이 좋다!
로그인 페이지에서 리디렉션할 환영 페이지 생성하기.
- 환영페이지 :
welcome.jsp로 작성.。브라우저에<html lang="kor"> <head> <title>Welcome Page</title> </head> <body> <div>Welcome to wjdtn747</div> <div>Your name : ${name}</div> <div>Your Password : ${name}</div> </body> </html>localhost:8080/login을 통해 login 페이지 접속 시, 초기 전달될Request Method는GET.
。ID와 PW를 입력하여 제출버튼을 누를 경우, 전달될Request Method는POST
▶ RequestMethod :POST인 경우의 다른 JSP Page 표현하기.
- 동일 URL의 다른 Request Method에 대해서 따로 처리하는 Controller Method 제작
@RequestMapping(value="URL", method = RequestMethod.GET)
。URL을 통해localhost:8080/login으로 접속 시 해당 요청 URL의 Request Method에서 오직GET에 대해서만 해당 Controller Method를 사용.// gotoLoginPage.java package com.wjdtn747.springframework.todo1.Controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class gotoLoginPage { @RequestMapping(value = "login", method= RequestMethod.GET) public String gotoLoginPage(){ return "login"; } }@RequestMapping(value = "login", method= RequestMethod.GET)
。초기 URL 접속 시GET에 대해서 정의된Controller Method만 존재하므로 반환되는 "login"을 통한ViewResolver기능으로login.jsp가 표시.
。ID와 PW를 입력 후POST로 전송 시 동일 URL에 대해POST가 정의된Controller Method가 존재하지 않으므로 Error Page가 도출.。동일 URL에// gotoLoginPage.java import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class gotoLoginPage { @RequestMapping(value="login", method= RequestMethod.GET) public String gotoLoginPage() { return "login"; } @RequestMapping(value="login", method=RequestMethod.POST) public String gotoLoginPagewPOST(@RequestParam String idName, @RequestParam String idPassword, ModelMap model) { model.put("name",idName); model.put("password",idPassword); return "welcome"; } }POST를 정의 및 "welcome"을 반환하여ViewResolver기능으로welcome.jsp를 표시하는Controller Method생성.
。POST를 통해 form data로 전달된 ID와 PW를@RequestParam을 통해Controller Method의 매개변수로 받아온다.
▶@RequestParam는GET의 Query Parameter 뿐만 아니라,POSTmethod를 통해 전달되는 Form Data도 전달 받을 수 있다.
▶ 해당 매개변수의 이름은 HTML tag의<input name="">의name속성 이름과 동일해야한다.
ex) /login?name=wjdtn747일 경우,
매개변수에@RequestParam String name설정 시 name 값이 wjdtn747로 설정됨.
。ModelMap을 통해 전달된 ID와 PW를JSP에 전달하여 표현.
ModelMap객체.put("JSP변수명",전달값)
。초기localhost:8080/login에GET으로 접속 시login.jsp가 도출되어 ID와 PW를 입력하여POST로 submit 할 경우welcome.jsp가 도출되어 form data로 전달된 ID와 PW가 페이지에서 도출.
- ( 하드코딩 ) 사용자 ID와 PW 검증 추가하기
。 하드코딩으로 특정 ID, PW 입력 시 사용자를 환영페이지로 리디렉션하고 틀릴경우 로그인페이지로 돌려보내기
。비추천.
- 인증을 담당하는 클래스 생성하기.
。class는 Spring이 Autowiring 하도록 Spring Bean으로 제작해야함.
=> 해당 class는 business logic을 수행하므로 @Service를 선언.import org.springframework.stereotype.Service; // Spring Bean으로 제작하기. // 해당 클래스는 Business logic을 수행! @Service public class AuthenticationService { public boolean authenticate(String username, String password){ boolean isValidUsername = username.equalsIgnoreCase("wjdtn"); boolean isValidPassword = password.equalsIgnoreCase("123456"); // AND 연산자로서 둘다 TRUE여야 TRUE를 반환. return isValidUsername && isValidPassword; } }
- 이때, 해당 AuthenticationService class의 참조변수를 생성 후 초기화 시, Spring에서 new AuthenticationService()로 직접 instance를 생성해서 결합하면 좋지않음.
=> Spring에서 초기화 시 가장 이상적인 방법은 생성자주입을 이용하는 방법.- 에러메시지를 출력 시 model을 생성해서 오류 메시지를 넣어주기.
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { // 입력된 ID, PW를 비교하는 Class 객체참조변수 생성. private AuthenticationService authenticationService; // 생성된 객체참조변수에 @Autowired를 이용한 생성자주입을 통해 // Spring Bean으로 선언된 AuthenticationService를 찾아 주입. @Autowired public LoginController(AuthenticationService authenticationService) { super(); this.authenticationService = authenticationService; } @RequestMapping(value = "login", method= RequestMethod.GET) public String gotoLoginPage(){ return "login"; } @RequestMapping(value = "login", method = RequestMethod.POST) public String gotoWelcomePage(@RequestParam String name, @RequestParam String password, ModelMap map){ // ID와 PW의 입력된 문자열을 각각 비교한 후 // 모두 TRUE일 경우 TRUE를 반환하는 메소드. // if 조건이 true인 경우, welcome.jsp를 실행하게하고 // false인 경우 login.jsp를 실행. if(authenticationService.authenticate(name, password)){ map.put("name",name); map.put("password",password); return "welcome"; }else{ // 에러메시지를 모델로 jsp에 전달. map.put("errMessage","ID or PW uncorrected."); return "login"; } } }<html lang="kor"> <head> <title>My first Login Page</title> </head> <body> My Login page with body <pre>${errMessage}</pre> <form method="post"> Name : <input type="text" name="name"> Password : <input type="password" name = "password"> <input type="submit"> </form> </body> </html>
- ID와 PW를 잘못 입력하면 다음처럼 도출.
<pre>:
。미리 정의된 서식의 텍스트를 정의할 때 사용.
。<pre>태그 내에서는 텍스트 작성 시space, tab, enter등이 반영된다.
A문자열.equalsIgnoreCase(B문자열):
。대소문자 차이를 무시하면서 두 문자열을 비교하는 역할 수행.
。웹페이지에 적절한 구조를 설치하기.
。설명 / 목표날짜 / 완료 여부 저장, 업데이트, 삭제 기능 구현
- TO-DO 정보를 저장할 Spring Bean 생성
。TodoClass 객체는 DB에 Data를 전달하는 instance로서id/username/description/targetDate/completed의 Field를 포함.
▶ 생성자주입 및 Getter & Setter 정의하기.import java.time.LocalDate; public class Todo { private int id; private String username; private String description; private LocalDate targetDate; private boolean completed; public Todo(int id, String username, String description, LocalDate targetDate, boolean completed) { this.id = id; this.username = username; this.description = description; this.targetDate = targetDate; this.completed = completed; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public LocalDate getTargetDate() { return targetDate; } public void setTargetDate(LocalDate targetDate) { this.targetDate = targetDate; } public boolean isCompleted() { return completed; } public void setCompleted(boolean completed) { this.completed = completed; } }
- To-DO 정보를 DB에 전달할 List 생성
。static의List자료형을 생성 후 실제 DB로 전달
▶ 이때,Static List로 데이터 저장 시 서버가 재시작 될때마다 초기화되므로MySQL등과 같은 DB를 활용.
。static변수를 초기화 설정 시에는static block을 생성해야한다.
static block: Java Class 내부의 명령문 Block으로서 생성자가 instance를 초기화하는것처럼static형식의 Data(변수/상수)를 초기화.import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @Service public class TodoService { // static List 자료형 생성 private static List<Todo> todos=new ArrayList<>(); // List 자료형 초기화 // 이때, static 변수는 static block으로 초기화. static{ todos.add(new Todo(1,"wjdtn747","Learn AWS", LocalDate.now().plusYears(1),false)); todos.add(new Todo(2,"wjdtn0619","Learn DevOps", LocalDate.now().plusYears(2),true)); todos.add(new Todo(3,"wjdtn3902","Learn FullStackDevelopment", LocalDate.now().plusYears(3),false)); } public List<Todo> findByUsername(String s){ return todos; } }。
@Service는 해당 Class가Spring Bean임과 동시에business logic에 구체화되었으므로@Component대신 선언.
。static의ArrayList변수를 생성 후static block을 통해 해당 변수를 초기화 설정.
Model구현체(ModelMap)에 추가되는 변수(name)를HttpSession에 저장
。ModelMap을 통해 JSP(welcome.jsp)에 전달된 data를 다른 JSP 페이지(listTodos.jsp)로 렌더링하여 연결이 끊기더라도HttpSession에 저장하여listTodos.jsp에서 사용할 수 있게하기.
▶welcome.jsp에 전달하고자 생성된ModelMap model객체에model.put("name",idName)를@SessionAttributes("name")를 통해Session에 전달.
<a href="url">:
。<a>는 하나의 페이지에서 다른 페이지로 연결시 사용하는 하이퍼링크를 정의 시 사용.
▶href="URL"속성은 링크된 페이지의 목적지 URL을 명시하는 역할을 수행.<!-- welcome.jsp --> <html lang="kor"> <head> <title>Welcome Page</title> </head> <body> <div>Welcome to wjdtn747</div> <div>Your name : ${name}</div> <div><a href="list-todo">Manage</a> your todos</div> </body> </html>import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; @Controller @SessionAttributes("name") public class gotoLoginPage { @RequestMapping(value="login", method= RequestMethod.GET) public String gotoLoginPage() { return "login"; } @RequestMapping(value="login", method=RequestMethod.POST) public String gotoLoginPagewPOST(@RequestParam String idName, @RequestParam String idPassword, ModelMap model) { model.addAttribute("name",idName); model.addAttribute("password",idPassword); return "welcome"; } }。
ModelMap에 추가된 Data(model.addAttribute("name",idName)) 중Session에 전달할 Data의 JSP변수명(name)을@SessionAttribute("name")로 선언하여Session에 전달.
。ModelMap객체.addAttribute("JSP변수명",변수값):ModelMap객체.put("JSP변수명",변수값)과 동일한 기능으로 작용하지만@SessionAttributes("JSP변수명")으로Model에 저장되는 data를HttpSession에 전달 시ModelMap객체.addAttribute를 사용.
- URL과 To-Do Page를 Mapping할 Controller Class 생성
。JSP를 이용한 리디렉션 기능 구현.
▶ 해당listTodos.jsp는gotoLoginPageClass의Model로부터Session에 전달된name을@SessionAttributes("name")를 통해TodoControllerClass에 전달받아서 변수${name}로 이용.// TodoController import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import java.util.List; @Controller @SessionAttributes("name") public class TodoController { private TodoService todoService; // 생성자기반 Dependency Injection. // @Autowired 없음. public TodoController(TodoService todoService) { this.todoService = todoService; } @RequestMapping("list-todo") public String ListAllTodos(ModelMap model){ List<Todo> todos = todoService.findByUsername("wjdtn747"); model.put("todos",todos); return "listTodos"; } } }。
@SessionAttributes("name"):gotoLoginPage의Modeldata를@SessionAttributes("name")를 통해 전달받아서listTodos.jsp에 전달.<!-- listTodos.jsp --> <html lang="kor"> <head> <title>List Todos Page</title> </head> <body> <div>Welcome to ${name}</div> <div>Your Todos are ${todos}</div> </body> </html>
@SessionAttributes("name"):
。TodoControllerClass에서 선언할 경우gotoLoginPageClass의Model에 추가된 변수(name)를 해당gotoLoginPageClass에서 선언된@SessionAttributes("name")을 통해listTodos.jsp의 (${name}) 변수로 전달됨.
로그인 페이지를 통해list-todo로 접속 시 todo data를 표현.
。login page에서 list-todo Page로 렌더링 했는데도 불구하고gotoLoginPage에서 Model을 통해Session에 전달한 변수 "name"를 여전히 사용 가능하다.
▶ 변수 "name"이Session Scope에 저장되었으므로 사용이 가능.
@SessionAttribute("Model에 추가된 변수명")
。특정 JSP에 전달하고자 설정한 Model 객체(ModelMap)에 저장되는 데이터를HttpSession에 저장하여 다른 JSP페이지로 렌더링되어 연결이 끊기더라도 Model 객체의 Data가 유지되도록 해주는 Annotation
。@Controller를 선언한Web Controller class앞에 선언해서View에서 사용하고자Model에 추가한 변수명을 Session에 input.
▶ Annotation에 선언된 Model의 data를 사용 시, 항상 해당 Model 객체의 Data를 사용하는 JSP가 Mapping된 모든 Controller class 앞에 선언해야한다.
HTTP(Hyper Text Transfer Protocol) :
。Web Server와 Web browser 간 데이터를 교환을 위해 사용되는 Protocol.
Protocol: 컴퓨터 내부, 컴퓨터 간 교환되는 데이터 형식의 규칙의 집합.
。Http 프로토콜은 기본적으로 상태를 유지하지 않는Stateless특징을 지니는 프로토콜이므로, 다른 JSP로 이동하여 연결을 끊을 경우 해당 JSP상의 데이터가 다 사라지므로 Web Server는 다른 JSP 페이지로 이동 시 데이터를 보존하기위해session등을 사용.
HTTP Protocol 특징
- Request :
。요청에 존재하는 모든 값은 각각의 요청에 대해서만 유효
。다음 페이지를 렌더링하기 위해서만 사용되며 다음페이지로 렌더링 이후로는 사용이 불가능.
- Model :
。스프링이 지원하는 기능으로서key,value로 구성된 HashMap.
。ModelMap으로Modelinterface를 구현.
。View에 전달할 데이터를 저장 가능하며View에서는 expression language(${변수명})로 해당 데이터를 활용.
。Request와 동일하게 다른 페이지로 렌더링 시 사용이 불가능.
- Map :
。key와value로 구성된 Entry 객체를 저장하는 구조를 지닌 자료구조.
entry : key-value 쌍
- HashMap :
。Map Interface를 구현한 대표적인 Map Collection.
▶ Map Interface를 상속하므로 Map의 성질을 그대로 지님.
- Session :
。Browser와 Server 간의 송수신 연결상태를 의미
。Web Application에서 사용자의 상태정보를 유지하기위한 메커니즘.
。Server-side에서 관리하는 정보.
▶Http Session id를 식별자로 구별하여 접속한 Server의 DB에 정보를 저장.
- Model :
。Model에 넣는 모든 값은Request Scope가 Default.
。@SessionAttribute를 통해 Session Scope를 지정 가능.
- Request Scope :
。오직 하나의 request에만 적용.
。response가 전송될 경우, request attribute가 메모리에서 삭제.
。대부분의 사례에서 활용.
- Session Scope :
。세부정보가 다수의 request에 걸쳐서 저장.
。해당 범위를 사용 시 추가적으로 메모리를 차지하고, 모든 세부정보가 서버에서 저장되므로 사용에 주의를 둬야한다.
JSTL(JSP Standard Tag Library) :
。JSP Page에서 자바코드 없이<html>태그형식으로 간편하게 데이터를 출력할 수 있도록 나온 라이브러리.
▶ JSP Page에서 연산, 조건문, 반복문, DB 등을 처리하게 할 수 있음.
pom.xml에 다음 dependency를 추가.
。 JSTL API Dependency
。JSTL Implementation Dependency<dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> </dependency>
- JSTL 태그 종류
。JSTL활용 시 JSP 상단에 다음 태그를 작성한 후 연산 사용.<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- Core (
prefix="c")
。일반 프로그래밍에서 제공하는 것과 유사한 변수 선언
。실행흐름제어 & 페이지 이동기술 제공
。URI :
http://java.sun.com/jsp/jstl/core
- forEach 함수 : foreach 역할 수행.
<c:forEach items="${todos}" var="todo">。
items: Java에서Model을 통해 전달된 source로서 List 형식 변수를 지정.
。var:<c:forEach>구문 내에서 사용할 변수 이름을 지정.
- Formatting (
prefix="fmt")
。숫자, 날짜, 시간을 formatting.
。URI : http://java.sun.com/jsp/jstl/fmt
- DB (
prefix="sql")
。DB data 입력, 수정, 삭제, 조회 기능 제공
。URI : http://java.sun.com/jsp/jstl/sql
- XML (
prefix="xml")
。XML문서 처리 기능 제공.
。URI : http://java.sun.com/jsp/jstl/xml
- Function (
prefix="fn")
。문자열 함수 제공.
。URI : http://java.sun.com/jsp/jstl/functions
- HTML 태그 활용
。html에서 표를 구현 시 기본적으로 table 태그 안에 tr, td, th를 넣어 행, 열, 제목을 지정하여 표를 구축.
<table>
。<tr>table row : 행
。<td>table data : 행의내용
。<th>table heading : 행, 열의 제목
。<thead>: 머리글
。<tbody>: 본문
。<tfoot>: 꼬리말<div>division :
。HTML 문서 내 한줄의 가로(Block) 공간을 생성.<h1>heading : 해당 영역의 제목 지시<hr>a horizontal rule :
。웹페이지에 가로로 선을 긋는 태그
。다른 컨텐츠를 구분하는 역할.<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html lang="kor"> <head> <title>List Todos Page</title> </head> <body> <div>Welcome ${name}</div> <hr> <h1>Your Todos</h1> <table> <thead> <tr> <th>id</th> <th>Description</th> <th>Target Date</th> <th>Is Done?</th> </tr> </thead> <tbody> <!-- taglib 선언 후 다음 forEach 함수 사용 가능. --> <c:forEach items="${todos}" var="todo"> <tr> <td>${todo.id}</td> <td>${todo.description}</td> <td>${todo.targetDate}</td> <td>${todo.completed}</td> </tr> </c:forEach> </tbody> </table> </body> </html>
▶ 다음처럼 결과 도출.
Bootstrap :
。Front-end개발을 용이하기위해 트위터에서 사용하는 각종 레이아웃, 버튼, 입력창 등의 디자인을CSS와Javascript로 구축한 CSS Framework.
。HTML&CSSTemplate의 양식, 버튼 등 다양한 웹페이지 구성요소를 포함.Bootstrap 사용 준비
- 기존 방법 : Bootstrap 웹페이지에서 수동으로 Bootstrap CSS 파일을 다운로드 후 스프링 프로젝트의 static폴더에 넣어서 사용
- webjars :
org.webjars
。Client-side (UI)에서 사용되는 웹라이브러리(jquery, bootstrap,react.js, vue.js, Angular)등을JAR파일 안에 패키징.
。Spring boot는Webjars에 대한 mapping을 제공하므로,pom.xml에 dependency로서 정의 가능.JAR(
.jar: Java ARchive) :
。여러 개의 Java Class 파일, 메타 데이터, Resource 파일 등을 하나의 파일로 묶은 Archive 파일.
。필요한 기본적인 dependency들을 전부 구성하여 간편하게 사용가능하게하는 Starter Project 역할 수행.
JQuery:
。JavaScript의 Library
。기존의 javascript를 통한 작성방식에 비해 간단하게 작성하여 동일 결과를 도출 가능.<dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>5.1.3</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.6.0</version> </dependency>。
webjars는jquery와bootstrap을 포함.
▶pom.xml에 다음 2개의 dependency를 입력하여webjars를 사용.
pom.xml에webjars의 dependency를 정의한 후 bootstrap.min.css / bootstrap.min.js 파일의 경로를 찾기
。External Libraries-Maven: org.webjars:bootstrap:5.1.3
。\META-INF\resources\webjars\bootstrap\5.1.3\css\bootstrap.min.css
。\META-INF\resources\webjars\bootstrap\5.1.3\js\bootstrap.min.js
。External Libraries-Maven: org.webjars:jquery:3.6.0에서jquery.min.js를 동일하게 찾은 후 copy path.
。\META-INF\resources\webjars\jquery\3.6.0\jquery.min.js
▶ 이후 적용할 jsp파일에 해당 경로들을 활용.webjars/bootstrap/5.1.3/css/bootstrap.min.css webjars/bootstrap/5.1.3/js/bootstrap.min.js webjars/jquery/3.6.0/jquery.min.js。
webjars를 이용해js,css사용 시/META-INF/resources/를 지정할 필요가 없음.
Bootstrap으로 페이지를 formatting하기.
Bootstrap framework와jQuery Library를 JSP에 불러오기.
。웹페이지 로딩 시 CSS 파일이 먼저 로딩됨.
。html에서css활용 시<head>부분에<link>를 정의하여 파일을 연결.<link href="webjars/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">。
html에서javascript활용 시 body의 종료태그</body>앞에<script>를 통해 파일 연결.<script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script> <script src="webjars/jquery/3.6.0/jquery.min.js"></script><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html lang="kor"> <head> <!-- css 파일 설정 --> <link href="webjars/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet"> <title>List Todos Page</title> </head> <body> <!-- div class 지정. --> <div class="container"> <h1>Your Todos</h1> <table class="table"> <thead> <tr> <th>id</th> <th>Description</th> <th>Target Date</th> <th>Is Done?</th> </tr> </thead> <tbody> <!-- taglib 선언 후 다음 forEach 함수 사용 가능. --> <c:forEach items="${todos}" var="todo"> <tr> <td>${todo.id}</td> <td>${todo.description}</td> <td>${todo.targetDate}</td> <td>${todo.completed}</td> </tr> </c:forEach> </tbody> </table> </div> <!-- script 파일 설정 --> <script src="webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script> <script src="webjars/jquery/3.6.0/jquery.min.js"></script> </body> </html>。이후
<body>내부 내용을<div class="container">에 넣고<table class="table">로 수정하여 JSP파일 정의.
- bootstrap에 의해 HTML의 format이 약간 변형한걸 확인 가능.
。브라우저에서 URL을 입력하여 Request 시 브라우저로 전송되는 Response로서list-todo가 전달됨.
▶ 브라우저는list-todo의 contents에 bootstrap의 css,js파일의 link를 관측 후 해당 파일들을 전부 다운로드.Bootstrap은
<div>와<table>에 대해 많은 class를 제공.
<div>:
。기존 class=""는 좌측정렬이지만,<div class="container">설정 시 중앙정렬.
<div>:
。<table class="table">설정 시 다음 디자인이 제공.