@RequestParam
요청의 파라미터를 연결할 때 매개변수에 붙이는 어노테이션
예제
required가 false일 때 에러가 나는 경우
required가 false인데,
에러가 나는 경우
-500에러가 나는 경우는 << null >> 값이기 때문에 정수로 변환 가능하므로 서버 에러
-400에러가 나는 경우는 << "" >> 값이기 때문에 값을 넣어줬으므로 클라이언트 에러
그러므로 필수 입력이 아닐 때는 기본 값을 주어야한다
위 두 URL은 에러가 안난다!
required가 true일 때 에러가 나는 경우
실습
@Controller
public class RequestParamTest {
@RequestMapping("/requestParam")
public String main(HttpServletRequest request) {
String year = request.getParameter("year");
// http://localhost/ch2/requestParam ---->> year=null
// http://localhost/ch2/requestParam?year= ---->> year=""
// http://localhost/ch2/requestParam?year ---->> year=""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam2")
// public String main2(@RequestParam(name="year", required=false) String year) { // 아래와 동일
public String main2(String year) {
// http://localhost/ch2/requestParam2 ---->> year=null
// http://localhost/ch2/requestParam2?year ---->> year=""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam3")
// public String main3(@RequestParam(name="year", required=true) String year) { // 아래와 동일
public String main3(@RequestParam String year) {
// http://localhost/ch2/requestParam3 ---->> year=null 400 Bad Request. required=true라서
// http://localhost/ch2/requestParam3?year ---->> year=""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam4")
public String main4(@RequestParam(required=false) String year) {
// http://localhost/ch2/requestParam4 ---->> year=null
// http://localhost/ch2/requestParam4?year ---->> year=""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam5")
public String main5(@RequestParam(required=false, defaultValue="1") String year) {
// http://localhost/ch2/requestParam5 ---->> year=1
// http://localhost/ch2/requestParam5?year ---->> year=1
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
// =======================================================================
@RequestMapping("/requestParam6")
public String main6(int year) {
// http://localhost/ch2/requestParam6 ---->> 500 java.lang.IllegalStateException: Optional int parameter 'year' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
// http://localhost/ch2/requestParam6?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: ""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam7")
public String main7(@RequestParam int year) {
// http://localhost/ch2/requestParam7 ---->> 400 Bad Request, Required int parameter 'year' is not present
// http://localhost/ch2/requestParam7?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: ""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam8")
public String main8(@RequestParam(required=false) int year) {
// http://localhost/ch2/requestParam8 ---->> 500 java.lang.IllegalStateException: Optional int parameter 'year' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
// http://localhost/ch2/requestParam8?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: ""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam9")
public String main9(@RequestParam(required=true) int year) {
// http://localhost/ch2/requestParam9 ---->> 400 Bad Request, Required int parameter 'year' is not present
// http://localhost/ch2/requestParam9?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: ""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam10")
public String main10(@RequestParam(required=true, defaultValue="1") int year) {
// http://localhost/ch2/requestParam10 ---->> year=1
// http://localhost/ch2/requestParam10?year ---->> year=1
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
@RequestMapping("/requestParam11")
public String main11(@RequestParam(required=false, defaultValue="1") int year) {
// http://localhost/ch2/requestParam11 ---->> year=1
// http://localhost/ch2/requestParam11?year ---->> year=1
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
} // class
yoil.jsp 수정
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>YoilTellerMVC</title>
</head>
<body>
year=<%=request.getParameter("year") %>
<h1>${year}년 ${month}월 ${day}일은 ${yoil}요일입니다.</h1>
</body>
</html>
예외 발생시 처리해주는 메소드 (필수 입력 시 무조건 추가!)
@ExceptionHandler(Exception.class) //Exception.class가 모든 에러의 조상이니 모든 에러를 잡는다
public String catcher(Exception e) {
return "YoilError";
}
실습
YoilTellerMVC.java 코드 변경
@Controller
public class YoilTellerMVC {
@RequestMapping("/getYoilMVC") // http://localhost/ch2/getYoilMVC
public String main(@RequestParam(required=true)int year,
@RequestParam(required=true)int month,
@RequestParam(required=true)int day, Model model) {
예외처리 코드 추가
위의 결과화면과 똑같이 에러처리가 된다!(yoilError view가 나온다)
입력받는 값이 너무 많을 때에는
매개변수를 너무 많이 적어주어야 하므로
클래스를 하나 정의하여 매개변수들을 하나로 합쳐준다
@RequestMapping("/getYoilMVC4") // http://localhost/ch2/getYoilMVC
public String main(MyDate date, Model model) {
MyDate.java
package com.fastcampus.ch2;
public class MyDate {
private int year;
private int month;
private int day;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "MyDate [year=" + year + ", month=" + month + ", day=" + day + "]";
}
}
yoil.jsp
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>YoilTellerMVC</title>
</head>
<body>
year=<%=request.getParameter("year") %>
<h1>${myDate.year}년 ${myDate.month}월 ${myDate.day}일은 ${yoil}요일입니다.</h1>
</body>
</html>
결과
어떻게 Mydate가 연결되는가?
Mydate라는
요청한 결과를 해쉬맵에 넣고
값을 myDate 객체에 어떻게 연결하는지 알려준다 -> dataBind
package com.fastcampus.ch2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.StringUtils;
public class SetterCall {
public static void main(String[] args) throws Exception{
Map<String, String> map = new HashMap<>();
map.put("year", "2021");
map.put("month", "10");
map.put("day", "1");
Class<?> type = Class.forName("com.fastcampus.ch2.MyDate");
// MyDate인스턴스를 생성하고, map의 값으로 초기화한다.
Object obj = dataBind(map, type);
System.out.println("obj="+obj); // obj=[year=2021, month=10, day=1]
} // main
private static Object dataBind(Map<String, String> map, Class<?> clazz) throws Exception {
// 1. MyDate인스턴스 생성
// Object obj = clazz.newInstance(); // deprecated method
Object obj = clazz.getDeclaredConstructor().newInstance(new Object[0]);
// 2. MyDate인스턴스의 setter를 호출해서, map의 값으로 MyDate를 초기화
// 2-1. MyDate의 모든 iv를 돌면서 map에 있는지 찾는다.
// 2-2. 찾으면, 찾은 값을 setter로 객체에 저장한다.
Field[] ivArr = clazz.getDeclaredFields();
for(int i=0;i<ivArr.length;i++) {
String name = ivArr[i].getName();
Class<?> type = ivArr[i].getType();
// map에 같은 이름의 key가 있으면 가져와서 setter호출
Object value = map.get(name); // 못찾으면 value의 값은 null
Method method = null;
try { // map에 iv와 일치하는 키가 있을 때만, setter를 호출
if(value==null) continue;
method = clazz.getDeclaredMethod(getSetterName(name), type); // setter의 정보 얻기
System.out.println("method="+method);
method.invoke(obj, convertTo(value, type)); // obj의 setter를 호출
} catch(Exception e) {
e.printStackTrace();
}
}
System.out.println(Arrays.toString(ivArr));
return obj;
}
private static Object convertTo(Object value, Class<?> type) {
// value의 타입과 type의 타입이 같으면 그대로 반환
if(value==null || type==null || type.isInstance(value))
return value;
// value의 타입과 type이 다르면, 변환해서 반환
if(String.class.isInstance(value) && type==int.class) // String -> int
return Integer.valueOf(""+value);
return value;
}
// iv의 이름으로 setter의 이름을 만들어서 반환하는 메서드("day" -> "setDay")
private static String getSetterName(String name) {
// return "set"+name.substring(0,1).toUpperCase()+name.substring(1);
return "set" + StringUtils.capitalize(name); // org.springframework.util.StringUtils
}
}
/*
[실행결과]
method=public void com.fastcampus.ch2.MyDate.setYear(int)
method=public void com.fastcampus.ch2.MyDate.setMonth(int)
method=public void com.fastcampus.ch2.MyDate.setDay(int)
[private int com.fastcampus.ch2.MyDate.year, private int com.fastcampus.ch2.MyDate.month, private int com.fastcampus.ch2.MyDate.day]
obj=[year=2021, month=10, day=1]
*/
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스 [직장인 실무교육]
프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.
fastcampus.co.kr
'패캠 챌린지' 카테고리의 다른 글
패스트캠퍼스 챌린지 - 14일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.05 |
---|---|
패스트캠퍼스 챌린지 - 13일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.04 |
패스트캠퍼스 챌린지 - 11일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.02 |
패스트캠퍼스 챌린지 - 10일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.03.01 |
패스트캠퍼스 챌린지 - 9일차 [스프링의 정석:남궁성과 끝까지 간다] (0) | 2023.02.28 |