[Spring] 03. @RequestParam과 @ModelAttribute/@GetMapping, @PostMapping/redirect와 forward

Hyeongmin Jung·2023년 5월 2일
0

Spring

목록 보기
3/17

🐥 @RequestParam과 @ModelAttribute

  • 컨트롤러 매개변수
    ✅ @RequestParam: 타입이 기본형(int, char 등0), String일 때 생략가능
    ✅ @ModelAttribute: 타입이 참조형일 때는 생략가능

@RequestParam

요청의 파라미터를 연결할 매개변수에 붙이는 애너테이션
✔️ @RequestParam(name="year", required=false) 생략가능
✔️ name="파라미터 이름", required=필수여부(t/f)
✔️ defaultValue="기본값"

@RequestMapping("/requestParam2")
//public String main2(@RequestParam(name="year", required=false) String year) {   // 아래와 동일 
public String main2(String year) {   
...

✅ @RequestParam(name="year", required=false) String year:
http://localhost/ch2/requestParam2 ---->> year=null
http://localhost/ch2/requestParam2?year=
http://localhost/ch2/requestParam2?year ---->> year="" (빈문자열, null != "")

✅ @RequestParam(name="year", required=true) String year: year을 필수입력, 빈문자열은 에러X
🐦 필수입력의 경우 예외처리

@ExceptionHandler(Exception.class)
	public String catcher(Exception ex) {
 	    ex.printStackTrace(); // 에러 출력
		return "yoilError";
	}

✔️ year=null | [400 Bad Request java.lang.NumberFormatException] required=true이기 때문

✅ @RequestParam(name="year", required=false) int year: null이나 ""를 int로 변환할 수 없음
🐦 필수 입력이 아닐때는 defaultValue="기본값"
✔️ year=null | 서버 에러 [500 java.lang.IllegalStateException]
✔️ year="" | 클라이언트 에러 [400 Bad Request]

✅ @RequestParam(name="year", required=true) int year:
✔️ year=null | [400 Bad Request]
✔️ year="" | [400 Bad Request]

@ModelAttribute

: 적용 대상을 Model의 속성으로 자동추가(자동저장)해주는 애너테이션
✔️ 반환 타입 또는 컨트롤러 메서드의 매개변수에 적용 가능
✔️ @ModelAttribute("키")와 같이 키를 적어주어야하지만 생략할 시 첫번째 타입의 앞글자를 소문자로 한 key 자동생성
ex. Mydate date -> mydate

  • 매개변수에 적용
@RequestMapping("/getYoilMVC5") 
//  public String main(@ModelAttribute("myDate") MyDate date, Model m) { // 아래와 동일 
public String main(@ModelAttribute MyDate date, Model m) { // @ModelAttribute사용, 반환 타입은 String  
System.out.println("myDate="+date);

	// 1. 유효성 검사 
	if(!isValid(date))
		return "yoilError";
    	
	// 2. 처리
	char yoil = getYoil(date);

	// 3. Model에 작업한 결과를 저장 
	// @ModelAttribute 덕분에 MyDate를 저장안해도 됨. View로 자동 전달됨.
//  m.addAttribute("myDate", date);     	
//  m.addAttribute("yoil", yoil);        
        
    // 4. 작업 결과를 보여줄 뷰의 이름을 반환  
    return "yoil";
}
  • 반환타입에 적용: 호출결과(return값)을 key에 대응되는 value에 저장
private @ModelAttribute("yoil") char getYoil(MyDate date) { 
	return getYoil(date.getYear(), date.getMonth(),date.getDay());
}

WebDataBinder

타입변환, 데이터검증 -> 결과&에러 BindingResult에 저장
✔️ 컨트롤러 메서드 바로 뒤에 작성해야 함


🐤 회원가입 화면 작성

✅ autofocus: 페이지 로드 시 자동으로 input요소로 focus(커서)
✅ onsubmit: form 전송 전에 입력된 데이터의 유효성 체크 이벤트, true 전송/false 전송X
✅ <c:url>: Context root 자동추가, Seesion id 자동추가
/ch2/register/save (=) <c:url value="/register/save"/>

✅ GET/POST: < form action="/ch2/registerInfo.jsp" method="GET/POST">

<!-- registerInfo.jsp -->
<h1>id=${param.id}</h1>
<h1>pwd=${param.pwd}</h1>
<h1>name=${param.name}</h1>
<h1>email=${param.email}</h1>
<h1>birth=${param.birth}</h1>
<!-- checkbox string 배열로 받아와서 출력 -->
<h1>sns=${paramValues.sns[0]} ${paramValues.sns[1]} ${paramValues.sns[2]}</h1>

function formCheck(frm) {
	var msg ='';

	if(frm.id.value.length<3) {
		setMessage('id의 길이는 3이상이어야 합니다.', frm.id);
        return false;
    }
    return true;
}

function setMessage(msg, element){
    document.getElementById("msg").innerHTML = `<i class="fa fa-exclamation-circle"> ${msg}</i>`;
  
    /* 잘못 입력한 값 선택 */
    if(element) {
         element.select();
    }
}

🐥 @GetMapping, @PostMapping

✅ spring 4.3부터 사용 가능, Maven 업데이트
✅ url이 같으면 충돌나지만 method가 다르면 같아도 충돌X
✅ 매핑할 url 공통부분을 @requestMapping으로 클래스에 적용

// 매핑할 url 공통부분을 @requestMapping으로 클래스에 적용
// register/add  or register/save
@RequestMapping("register")  
public class RegisterController {
	@GetMapping("/add") 
	public String register() {}
    
	@PostMapping("/save")
    public String save(@ModelAttribute("user") User user, Model m) throws Exception {}
}

@GetMapping

@RequestMapping(value="/register/add", method={RequestMethod.GET, RequestMethod.POST})
@GetMapping("/register/add")

@GetMapping("/register/add")
public String register() { 
	return"registerForm"; // WEB-INF/views/registerForm.jsp
}
  • 메서드가 다른 기능없이 registerForm로 연결하여 신규회원가입 화면 보여주므로 view-controller로 변경
    🥕 servlet-context에 view-controller을 이용하면 404, 아직 에러원인 발견 못함•••
    src > main > webapp > WEB-INF > spring > appServlet > servlet-context.xml

    <mvc:view-controller path="/register/add" view-name="registerForm">

@PostMapping

@RequestMapping(value="/register/save", method=RequestMethod.POST)
@PostMapping("/register/save")

@PostMapping("/save")
public String save(@ModelAttribute("user") 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 "redirect:/register/add?msg="+msg; //url재작성(rewriting)
	}
		 
	return "registerInfo";
}	

URL인코딩 - 퍼센트 인코딩

✔️ URL에 포함된 non-ASCII문자를 문자코드(16진수) ↔ 문자열 변환
✔️ ≠Base64(바이너리→text 변환)


🐣 redirect와 forward

redirect

✔️ 300 Redirect: 다른 URL로 재요청
✔️ 요청이 2번이며 각 요청은 서로 다른 객체, 응답 2번
✔️ 첫번째 요청은 수동 GET/POST, 두번째 요청은 자동 GET
✔️ 재요청하므로 주소가 자동으로 변경

forward

✔️ 클라이언트가 보낸 요청을 다음 jsp로 그대로 전달, 두번 request할 필요 없음
✔️ 재요청하지 않으므로 주소가 변경되지 않음

RedirectView

✔️ redirect로 응답할 때 RedirectView를 통해 응답헤더 생성
💻client --(/ch/register/save 요청)--> 📃DispatcherServlet
---> 🕹️Controller --(redirect:/register/add)--> 📃DispatcherServlet
---> 📑RedirectView 응답헤더생성 --(응답)-->💻client

JstlView

✔️ jsp 뷰 처리
✔️ InternalResourcViewResolver는 뷰 이름을 해석하여 jsp주소로 넘겨줌
💻client --(/ch/register/add 요청)--> 📃DispatcherServlet ---> 🕹️Controller
--(registerForm_뷰이름)--> 📃DispatcherServlet
--(registerForm)--> 📜InternalResourceViewResolver
--(/WEB-INF/views/registerForm.jsp)--> 📃DispatcherServlet
--(/WEB-INF/views/registerForm.jsp)--> 📑JstlView
--(데이터를 모델로 전달)--> registerForm.jsp --(응답)--> 💻client

InternalResourceView

✔️ 내부적 forwarding
💻client --(/ch/register/save 요청)--> 📃DispatcherServlet ---> 🕹️Controller
--(forward:/register/add)--> 📃DispatcherServlet
--(/register/add)--> InternalResourceView
--(registerForm)--> 📃DispatcherServlet

--(registerForm)--> 📜InternalResourceViewResolver
--(/WEB-INF/views/registerForm.jsp)--> 📃DispatcherServlet
--(/WEB-INF/views/registerForm.jsp)--> 📑JstlView
---> registerForm.jsp --(응답)--> 💻client

실습


참고) 자바의 정석 | 남궁성과 끝까지 간다

0개의 댓글