โ๏ธ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฐ๊ฒฐํ ๋ ๋งค๊ฐ๋ณ์์ ๋ถ์ด๋ ์ ๋ํ ์ด์
@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";
}
โก๏ธ public String main2(@RequestParam(name="year", required=false) String year)
: ์๋ต๋ ๊ฒ. year๋ฅผ ํ์๋ก ์
๋ ฅ์ํด๋ ๋จ
@RequestParam
์ ๋ถ์ด๋ฉด required๋ true๊ฐ ๋จ @RequestMapping("/requestParam3")
// public String main3(@RequestParam(name="year", required=true) String year) { // ์๋์ ๋์ผ
public String main3(@RequestParam String year) {
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
http://localhost/ch2/requestParam3?year
โก๏ธ year = ""
http://localhost/ch2/requestParam3
โก๏ธ 400 Bad Request.
: required=true๋ผ์ ํด๋ผ์ด์ธํธ ์๋ชป. ๋ฌด์กฐ๊ฑด year์ ๊ฐ์ ๋ฃ์ด์ค์ผ ํจ
โ๏ธ defaultValue: ํ์์ ๋ ฅ์ด ์๋ ํ๋ผ๋ฏธํฐ๋ ๊ธฐ๋ณธ๊ฐ์ ๋ฃ์ด์ค๋ค.
@RequestMapping("/requestParam8")
public String main8(@RequestParam(required = false, defaultValue = "2021") int year) {
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
ํ์๊ฐ ์๋. ๊ทธ๋์ ์๋ฒ ์ค๋ฅ ํ์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ด ๊ฐ์ด ์ ๋ค์ด์์ ๋์ ๋๋น๊ฐ ๋์ด์์ด์ผ ํ๋ค.
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.
: ํ์์
๋ ฅ์ด ์๋ โก๏ธ ์๋ฒ ์๋ชป
: year ์์ฒด๊ฐ ์์ด์ null
์ด ๋์ค๊ณ ์ด null
๊ฐ์ int
๋ก ๋ณํ โ
http://localhost/ch2/requestParam8?year
โก๏ธ 400 Bad Request, nested exception is java.lang.NumberFormatException
: For input string: ""
: ๋น๋ฌธ์์ด ์ซ์ ๋ณํ โ โก๏ธ ํด๋ผ์ด์ธํธ ์๋ชป
String
์ผ๋ก ๋ฐ๋ก ๋ฐ๋ ๊ฒ์ด ์๋ int
๋ก ๋ณํ๋๋ ๊ฑฐ๋ผ์ ์๋ฌ๊ฐ ๋ค๋ฅธ ๊ฒ
โ๏ธ ํ์์ ๋ ฅ์ผ ๋๋ ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฐ์ ๋ฃ์ ์ ์์ผ๋ฏ๋ก ์์ธ ์ฒ๋ฆฌ๋ฅผ ํด ์ค๋ค.
@RequestMapping("/requestParam9")
public String main9(@RequestParam(required = true) int year) {
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return "yoil";
}
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: ""
: ๋น๋ฌธ์์ด ์ซ์ ๋ณํ โ โก๏ธ ํด๋ผ์ด์ธํธ ์๋ชป
์์ธ ์ฒ๋ฆฌ๋ฅผ ํด์ ์ฌ์ฉ์๊ฐ ์ฌ๋ฐ๋ฅธ ์ ๋ ฅ ๊ฐ์ ๋ฃ์ ์ ์๊ฒ ํด์ค๋ค.
โ๏ธ YoilTellerMVC.java
package kr.ac.jipark09.ch2;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
// ๋
,์,์ผ์ ์
๋ ฅํ๋ฉด ์์ผ์ ์๋ ค์ฃผ๋ ํ๋ก๊ทธ๋จ
@Controller
public class YoilTellerMVC {
@RequestMapping("/getYoilMVC")
// required = true ํด์ค
public String main(
@RequestParam(required = true) int year,
@RequestParam(required = true) int month,
@RequestParam(required = true) int day,
Model model
) throws IOException {
//1. ์ ํจ์ฑ ๊ฒ์ฌ
if(!isVaild(year, month, day)) {
return "yoilError";
}
// 2. ์์ผ ๊ณ์ฐ
char yoil = getYoil(year, month, day);
getYoil(year, month, day);
// 3. ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ model์ ์ ์ฅ
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", day);
model.addAttribute("yoil", yoil);
return "yoil"; // yoil.jsp๋ฅผ ๋ณด์ฌ์ค๋ผ
}
private boolean isVaild(int year, int month, int day) {
return true;
}
private char getYoil(int year, int month, int day) {
Calendar cal = Calendar.getInstance();
cal.set(year, month - 1, day);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek);
}
}
โ๏ธ @ExceptionHandler๋ฅผ ๋ถ์ด๋ฉด ํ๋ผ๋ฏธํฐ์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค๋ค.
@ExceptionHandler(Exception.class)
public String catcher(Exception e) {
e.printStackTrace();
return "yoilError";
}
year, month, day๋ก ํ๋ํ๋ ๋ฃ์ด์ฃผ๋ ๊ฒ์ด ์๋, ์ด๊ฒ๋ค์ ํ๋๋ก ํฉ์น ๊ฐ์ฒด๋ก ๋ง๋ค์ด๋ณด์.
โ๏ธ YoilTellerMVC4.java
package kr.ac.jipark09.ch2;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
// year, month, day๋ฅผ ํ๋๋ก ํฉ์ณ๋ด => ๊ฐ์ฒด๋ก ๋ง๋ค๊ธฐ(dto)
@Controller
public class YoilTellerMVC4 {
@ExceptionHandler(Exception.class)
public String catcher(Exception e) {
e.printStackTrace();
return "yoilError";
}
@RequestMapping("/getYoilMVC4")
public String main(MyDate date, Model model) throws IOException {
//1. ์ ํจ์ฑ ๊ฒ์ฌ
if(!isVaild(date)) {
return "yoilError";
}
// 2. ์์ผ ๊ณ์ฐ
char yoil = getYoil(date);
// 3. ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ model์ ์ ์ฅ
model.addAttribute("date", date);
model.addAttribute("yoil", yoil);
return "yoil"; // yoil.jsp๋ฅผ ๋ณด์ฌ์ค๋ผ
}
private boolean isVaild(MyDate date) {
return isVaild(date.getYear(), date.getMonth(), date.getDay());
}
private boolean isVaild(int year, int month, int day) {
if(year == 1 || month == 1 || day == 1) {
return false;
}
return (1 <= month && month <= 12) && (1 <= day && day <= 31);
}
private char getYoil(MyDate date) {
int year = date.getYear();
int month = date.getMonth();
int day = date.getDay();
Calendar cal = Calendar.getInstance();
cal.set(year, month - 1, day);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek);
}
}
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>year=<%=request.getParameter("year") %></h1>
<!-- EL -->
<p>${myDate.year }๋
${myDate.month }์ ${myDate.day }์ผ์ ${yoil }์
๋๋ค.</p>
</body>
</html>
โ ์ ๋ ฅ๋๋ ๊ฐ์ด year, month, day์ธ๋ฐ MyDate๋ก ์ ๋์ค๋ ์ด์ ๊ฐ ๋ญ๊น?
์ด๋ฌํ ๋ถ๋ถ๋ ์คํ๋ง์ด ์์์ ์ฐพ์๊ฐ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
์์ ๋ฅผ ๋ณด๋ฉฐ ์ดํด๋ณด์.
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]
์์ฒญํ ๊ฐ๋ค์ด HashMap์ผ๋ก ๋ด๊ธด๋ค.
MyDate
๋ผ๋ ํ์
์ด ์์ ๋ bind()
๋ฉ์๋๊ฐ Mapํ๊ณ ์ฐ๊ฒฐํด์ค๋ค.
1) ํ์ ์ผ๋ก ๋์ด์จ ํด๋์ค ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
2) MyDate ์ธ์คํด์ค์ setter๋ฅผ ํธ์ถํด์, Map์ ๊ฐ์ผ๋ก MyDate๋ฅผ ์ด๊ธฐํํ๋ค.
2-1. myDate์ ๋ชจ๋ iv(์ธ์คํด์ค ๋ณ์)๋ฅผ ๋๋ฉด์ Map์ ์กด์ฌํ๋์ง ์ฐพ๋๋ค.
2-2. ์ฐพ์ผ๋ฉด, ์ฐพ์ ๊ฐ์ setter๋ก ๊ฐ์ฒด์ ์ ์ฅํ๋ค.
โก๏ธ setter๊ฐ ์์ผ๋ฉด ์คํ๋ง์ด ์๋์ผ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ๋ชปํจ. setter ํ์!
Reference
: https://fastcampus.co.kr/dev_academy_nks