@PostMapping과 @GetMapping
1. @PostMapping과 @GetMapping
@Controller
public class RegisterController {
@GetMapping("register/add")
public String register() {
return "registerForm"; // WEB-INF/views/registerForm.jsp
}
@PostMapping("register/add")
public String save() {
return "registerInfo"; // WEB-INF/views/registerInfo.jsp
}
}
다음과 같이 @PostMapping과 @GetMapping 을 @RequestMapping 대신 사용하면
GET 메소드, 또는 POST 메소드로만 데이터를 전송하게 설정할 수 있다.
(데이터 전송 방법이 다르기 때문에 URL이 같아도 구분이 가능하게 된다)
이전에 @RequestMapping을 사용했을때는 두 메소드 모두 다 사용가능했지만
페이지의 용도에 따라 특정 메소드를 사용하게 될 때는 @PostMapping과 @GetMapping 애너테이션을 사용하면 된다.
2. 클래스에 붙이는 @RequestMapping
맵핑될 URL의 공통 부분을 @RequestMapping으로 클래스에 적용
@Controller
@RequestMapping("/register")
public class Practice {
@GetMapping("/add")
public String register() {
return "registerForm";
}
@PostMapping("/add")
public String save(User user, Model m) throws Exception {
if(!isValid(user)) {
String msg = URLEncoder.encode("id를 잘못입력하셨습니다.", "utf-8");
m.addAttribute("msg", msg);
return "redirect:/register/add";
}
return "registerInfo";
}
3. @RequestMapping의 URL패턴
1. 정확히 일치하는 패턴
2. 경로 맵핑
3. 확장자 맵핑
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RequestMappingTest {
// @RequestMapping({"/login/hello.do", "/login/hi.do"})
@RequestMapping("/login/hello.do") // http://localhost/ch2/login/hello.do
public void test1(){
System.out.println("urlpattern=/login/hello.do");
}
@RequestMapping("/login/*") // /login/hello, /login/hi
public void test2(){
System.out.println("urlpattern=/login/*");
}
@RequestMapping("/login/**/tmp/*.do") // /login/tmp/hello.do, /login/aaa/tmp/hello.do
public void test3(){
System.out.println("urlpattern=/login/**/tmp/*.do");
}
@RequestMapping("/login/??")
public void test4(){ // /login/hi, /login/my.car
System.out.println("urlpattern=/login/??");
}
@RequestMapping("*.do") // /hello.do, /hi.do, /login/hi.do
public void test5(){
System.out.println("urlpattern=*.do");
}
@RequestMapping("/*.???") // /hello.aaa, /abc.txt
public void test6(){
System.out.println("urlpattern=*.???");
}
}
4. URL인코딩 - 퍼센트 인코딩
URL에 포함된 non-ASCII 문자를 문자코드(16진수) 문자열로 반환
홍길동 -> URLEncoder.encode() -> "%ED%99%8D%EA%B8%B8%EB%8F%99"
<- URLDecoder.decode() <-
문자 | UTF-8 |
홍 | 0xED998D |
길 | 0xEAB8B8 |
동 | 0xEB8F99 |
GET이나 POST 메소드로 한글을 전송할 경우 위와 같이 인코딩이 되어 전송이 된다.
즉, 홍길동이 %ED%99%8D%EA%B8%B8%EB%8F%99 로 전송이 되는 것이다.
redirect와 forward
1. redirect와 forward의 처리 과정 비교
redirect)
수동으로 요청(GET 또는 POST 메소드) -> 300 Redirect 응답
-> 주어진 Location으로 새로운 요청을 하게 됨(자동, 이 때는 무조건 GET 메소드를 사용하게 됨) -> 새로운 응답
즉 2번의 요청, 2번의 응답
forward)
요청을 그대로 전달해줌
요청 -> forward(전달) -> 응답
2. RedirectView
Controller가 반환한 redirect:/register/add을 RedirectView에 전달하고
RedirectView는 응답 헤더를 만들어내서 클라이언트에 응답을 함
브라우저는 응답을 받아서 자동으로 요청을 다시 하게 됨
3. JstlView
Controller에서 registerForm이라는 문자열을 반환하면
DispatcherServlet은 InternalResourceViewResolver에 해당 문자열을 전달하여 실제로 어떤 파일인지 알려줌
/WEB-INF/views/registerForm.jsp 라는 파일임을 JstlView에 전달하고 JstlView는 registerForm.jsp에게 Model을 넘겨줌
registerForm.jsp 에서 최종적으로 응답을 하게 됨.
4. InternalResourceView
Controller가 forward:/register/add 를 DispatcherServlet에 반환하고, 이것을 InternalResourceView에 전달함
InternalResourceView는 /register/add를 다시 DispatcherServlet에 전달하게 됨.
그 이후는 일반적인 처리과정과 같음. 마치 처음부터 /register/add를 요청받은 것 처럼.
쿠키(Cookie)란?
1. Cookie
이름(name)과 값(value)의 쌍으로 구성된 작은 정보. ASCII 문자만 가능
서버에서 생성 후 전송, 브라우저에 저장. 유효기간 이후 자동 삭제
서버에 요청시 domain, path가 일치하는 경우(하위 경로도 포함)에만 자동 전송
2. 쿠키의 작동 과정
서버에 요청을 하면, 서버가 쿠키를 만드는 코드를 실행하고 응답헤더에 쿠키를 담아서 응답함.
브라우저에 쿠키가 저장되고, 나중에 다시 서버에 요청할 때 요청헤더에 쿠키정보도 같이 전송하게 됨.
서버는 그 쿠키를 보고 클라이언트를 식별할 수 있게 됨.
즉, 쿠키는 클라이언트 식별 기술.
3. 쿠키의 생성
Cookie cookie = new Cookie("id", "asdf"); // 쿠키 생성
cookie.setMaxAge(60*60*24); // 유효기간 설정(초)
response.addCookie(cookie); // 응답에 쿠키 추가
(서버에서 실행되는 코드)
응답헤더)
HTTP/1.1 200 Set-Cookie: id=asdf; Max-Age=86400; Expires=Tue, 16-Nov-2021 11:12:15 GMT Content-Type : text/html; charset=UTF-8 Content-Language: ko-KR Content-Length: 175 Date: Mon, 15 Nov 2021 11:12:15 GMT |
(Max-Age=86400; 는 상대시간,
Expires=Tue, 16-Nov-2021 11:12:15 GMT 는 절대시간이다.)
이렇게 해서 쿠키가 생성되고 브라우저에 저장이 된다.
4. 쿠키의 삭제와 변경
쿠키의 삭제)
Cookie cookie = new Cookie("id", ""); // 변경할 쿠키와 같은 이름의 쿠키를 생성
cookie.setMaxAge(0); // 유효기간을 0으로 설정(삭제)
response.addCookie(cookie); // 응답에 쿠키 추가
쿠키의 변경)
Cookie cookie = new Cookie("id", ""); // 변경할 쿠키와 같은 이름의 쿠키 생성.
cookie.setValue(URLEncoder.encode("홍길동")); // 값의 변경
cookie.setDomain("www.fastcampus.co.kr"); // 도메인의 변경
cookie.setPath("/ch2"); // 경로의 변경
cookie.setMaxAge(60*60*24*7); // 유효기간의 변경
response.addCookie(cookie); // 응답에 쿠키 추가
5. 쿠키 읽어오기
Cookie[] cookies = request.getCookies(); // 쿠키 읽기, 없으면 null
for(Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.printf("[cookie]name=%s, value=%s%n", name, value);
}
ex)
<%@ page contentType="text/html;charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="java.net.URLDecoder" %>
<%@ page session="false" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
<style>
* { box-sizing:border-box; }
a { text-decoration: none; }
form {
width:400px;
height:500px;
display : flex;
flex-direction: column;
align-items:center;
position : absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%) ;
border: 1px solid rgb(89,117,196);
border-radius: 10px;
}
input[type='text'], input[type='password'] {
width: 300px;
height: 40px;
border : 1px solid rgb(89,117,196);
border-radius:5px;
padding: 0 10px;
margin-bottom: 10px;
}
button {
background-color: rgb(89,117,196);
color : white;
width:300px;
height:50px;
font-size: 17px;
border : none;
border-radius: 5px;
margin : 20px 0 30px 0;
}
#title {
font-size : 50px;
margin: 40px 0 30px 0;
}
#msg {
height: 30px;
text-align:center;
font-size:16px;
color:red;
margin-bottom: 20px;
}
</style>
</head>
<body>
<form action="<c:url value='/login/login'/>" method="post" onsubmit="return formCheck(this);">
<h3 id="title">Login</h3>
<div id="msg">
<c:if test="${not empty param.msg}">
<i class="fa fa-exclamation-circle"> ${URLDecoder.decode(param.msg)}</i>
</c:if>
</div>
<input type="text" name="id" value="${cookie.id.value}" placeholder="이메일 입력" autofocus>
<input type="password" name="pwd" placeholder="비밀번호">
<input type="hidden" name="toURL" value="${param.toURL}">
<button>로그인</button>
<div>
<label><input type="checkbox" name="rememberId" value="on" ${empty cookie.id.value ? "":"checked"}> 아이디 기억</label> |
<a href="">비밀번호 찾기</a> |
<a href="">회원가입</a>
</div>
<script>
function formCheck(frm) {
let msg ='';
if(frm.id.value.length==0) {
setMessage('id를 입력해주세요.', frm.id);
return false;
}
if(frm.pwd.value.length==0) {
setMessage('password를 입력해주세요.', frm.pwd);
return false;
}
return true;
}
function setMessage(msg, element){
document.getElementById("msg").innerHTML = ` ${'${msg}'}`;
if(element) {
element.select();
}
}
</script>
</form>
</body>
</html>
아이디 기억 (rememberID) 체크 여부에 따라 아이디 값이 자동으로 나타나도록 한다.
${cookie.id.value} 는 내가 생성한 쿠키 객체(이름을 cookie로 하였음)에 저장된 이름이 "id"에 해당하는 value값을 가져온다.
아이디 기억에 체크를 하게 되면 쿠키를 생성하고, 로그인할 때 사용한 id를 쿠키에 저장한다.
package com.fastcampus.ch2;
import java.net.URLEncoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/login")
public class LoginController {
@GetMapping("/login")
public String loginForm() {
return "loginForm";
}
@PostMapping("/login")
public String login(String id, String pwd, boolean rememberId, HttpServletResponse response) throws Exception {
System.out.println("id="+id);
System.out.println("pwd="+pwd);
System.out.println("rememberId="+rememberId);
// 1. id와 pwd를 확인
if(!loginCheck(id, pwd)) {
// 2-1 일치하지 않으면, loginForm으로 이동
String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "utf-8");
return "redirect:/login/login?msg="+msg;
}
// 2-2. id와 pwd가 일치하면,
if(rememberId) {
// 쿠키를 생성
Cookie cookie = new Cookie("id", id);
// 응답에 저장
response.addCookie(cookie);
} else {
// 쿠키를 삭제
Cookie cookie = new Cookie("id", id);
cookie.setMaxAge(0);
// 응답에 저장
response.addCookie(cookie);
}
// 3. 홈으로 이동
return "redirect:/";
}
private boolean loginCheck(String id, String pwd) {
return "asdf".equals(id) && "1234".equals(pwd);
}
}
'Spring & SpringBoot > Spring' 카테고리의 다른 글
220428 Spring - Chapter 2. Spring MVC (Part 7) (0) | 2022.04.29 |
---|---|
220427 Spring - Chapter 2. Spring MVC (Part 6) (0) | 2022.04.27 |
220425 Spring - Chapter 2. Spring MVC (Part 4) (0) | 2022.04.25 |
220423 Spring - Chapter 2. Spring MVC (Part 3) (0) | 2022.04.23 |
220422 Spring - Chapter 2. Spring MVC (Part 2) (0) | 2022.04.23 |