파라미터 연결하기
✒️ 2025-05-28 13:02 내용 수정
사용하는 Annotation
1. @RequestParam
- 요청 파라미터를 연결할 매개변수에 사용한다.
@RequestParam("가져올데이터이름") 데이터타입 변수명으로 작성하며,@RequestParam 데이터타입 변수명으로 생략 가능하다.- Controller의 파라미터가 기본형이나 String이면 사용한다.
(@RequestParam(name="name", required=true, defaultValue="0") dataType name)
| 옵션 | 값 | 설명 |
|---|---|---|
| name | 이름 | 가져올 파라미터의 이름 |
| required | true/false | 파라미터 필수 여부. true라면 반드시 값이 넘어와야 하며, 값이 넘어오지 않으면 400 error 발생 |
| defaultValue | 기본값 | 넘어온 값이 없을 때 기본값 설정 |
@Controller
public class RequestParamTest {
public static final String VIEW_PATH = "/WEB-INF/views/";
@RequestMapping("requestParam")
public String main(HttpServletRequest request) {
String year = request.getParameter("year");
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return VIEW_PATH + "date.jsp";
}
@RequestMapping("requestParam2")
//public String main2(@RequestParam(name="year", required=false) String year) {
public String main2(String year) { // 위와 동일
// localhost/requestParam --> year=null : 400 error
// localhost/requestParam?year --> year=""
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return VIEW_PATH + "date.jsp";
}
@RequestMapping("requestParam3")
public String main3(@RequestParam String year) {
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return VIEW_PATH + "date.jsp";
}
@RequestMapping("requestParam4")
public String main4(@RequestParam(required=false, defaultValue="1") String year) {
// localhost/requestParam --> year=1
// localhost/requestParam?year --> year=1
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return VIEW_PATH + "date.jsp";
}
// ===============================================
// year가 int로 넘어올 때
@RequestMapping("requestParam5")
public String main5(int year) {
// localhost/requestParam --> year=null : 500 error
// localhost/requestParam?year --> year="" : 400 error
System.out.printf("[%s]year=[%s]%n", new Date(), year);
return VIEW_PATH + "date.jsp";
}
}
2. @ModelAttribute
- 적용 대상을 Model 속성으로 자동 추가한다.
- 메소드의 반환 타입 앞, Controller의 메소드의 매개변수에 사용할 수 있다.
- Controller의 매개변수가 참조형일 때 사용한다.
@ModelAttribute("name") 데이터타입 이름으로 작성하며@ModelAttribute 데이터타입 이름으로 생략 가능하다.- 노출을 원하지 않는 정보까지 공개될 수 있기 때문에 사용 시 주의해야 한다.
- 참고 자료 : Spring ModelAttribute
- Argument가 기본 데이터타입이 아니거나 다른 Argument resolver에 의해 처리되는 것이 아닌 경우라면 @ModelAttribute가 적용되는 것으로 처리된다.
public String test(@ModelAttribute("dto") PersonDTO dto) {}
public @ModelAttribute("name") int test() {}
실습
0. 프로젝트 설정
1. DTO 클래스 생성
package dto;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class PersonDTO {
private String name, tel;
private int age;
@Override
public String toString() {
return "PersonDTO[name="+name+", tel="+tel+", age="+age+"]";
}
}
2. 데이터를 받을 jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
function send1(f) {
let name = f.name.value;
let tel = f.tel.value;
let age = f.age.value;
if(name==''){
alert('이름을 입력해주세요');
return;
}
if(tel==''){
alert('전화번호를 입력해주세요');
return;
}
if(age==''){
alert('나이를 입력해주세요');
return;
}
f.action = "insert1";
f.method = "post";
f.submit();
}
function send2(f) {
let name = f.name.value;
let tel = f.tel.value;
let age = f.age.value;
if(name==''){
alert('이름을 입력해주세요');
return;
}
if(tel==''){
alert('전화번호를 입력해주세요');
return;
}
if(age==''){
alert('나이를 입력해주세요');
return;
}
f.action = "insert2";
f.method = "post";
f.submit();
}
</script>
</head>
<body>
<form>
<table border="1" align="center">
<caption>:::개인정보 입력:::</caption>
<tr>
<th>이름</th>
<td><input name="name"></td>
</tr>
<tr>
<th>전화번호</th>
<td><input name="tel"></td>
</tr>
<tr>
<th>나이</th>
<td><input name="age"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" value="낱개로 받기" onclick="send1(this.form)">
<input type="button" value="객체로 받기" onclick="send2(this.form)">
</td>
</tr>
</table>
</form>
</body>
</html>
3. 파라미터를 받아 바인딩과 포워딩을 할 Controller
package com.nogroup.mvc;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import dto.PersonDTO;
import util.MyPath.HomeClass;
@Controller
public class ParamController {
@RequestMapping(value= {"/", "insert_form"})
public String inset_form() {
return HomeClass.VIEW_PATH + "insert_form.jsp";
}
// insert1?name=이름&tel=전화번호&age=40
@RequestMapping("insert1")
public String insert1(@RequestParam String name,
@RequestParam String tel,
@RequestParam int age,
Model model) {
PersonDTO dto = new PersonDTO();
dto.setName(name);
dto.setTel(tel);
dto.setAge(age);
model.addAttribute("dto", dto);
return HomeClass.VIEW_PATH + "insert_result.jsp";
}
@RequestMapping("insert2")
public String insert2(@ModelAttribute("dto") PersonDTO dto) {
getYear(dto);
return HomeClass.VIEW_PATH + "insert_result.jsp";
}
// 메소드를 실행하고 난 결과를 annotation에 붙은 단어를 key값으로 model에 바인딩
private @ModelAttribute("year") int getYear(PersonDTO dto) {
return 2024-dto.getAge();
}
}
4. 결과를 확인할 jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>이름 : ${dto.name }</p>
<p>나이 : ${dto.age }</p>
<p>전화번호 : ${dto.tel }</p>
<p>년도 : ${year} <p>
<input type="button" value="돌아가기" onclick="location.href='insert_form'">
</body>
</html>
- 낱개로 받으면 이전부터 해왔던 것처럼 정보를 따로 받아 출력된다.
- 객체로 받기를 선택하면 낱개로 받는것보다 훨씬 간편하게 정보를 저장해서 출력할 수 있다.
데이터를 객체에 묶은 방법
package com.nogroup.mvc;
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 {
// 요청한 값이 HashMap에 담겨있다 하면
Map<String, String> map = new HashMap<String, String>();
map.put("name", "홍길동");
map.put("tel", "010-111-1111");
map.put("age", "10");
Class<?> type = Class.forName("dto.PersonDTO");
// PersonDTO 인스턴스를 생성하고, map의 값으로 초기화
Object obj = dataBind(map,type);
System.out.println("obj="+obj);
}
private static Object dataBind(Map<String, String> map, Class<?> clazz) throws Exception {
// 1. PersonDTO 인스턴스 생성
Object obj = clazz.getDeclaredConstructor().newInstance(new Object[0]);
// 2. PersonDTO 인스턴스의 setter를 호출해서 map의 값으로 PersonDTO를 초기화
// 2-1. PersonDTO의 모든 필드를 돌면서 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.invoke(obj, convertTo(value, type)); //obj의 setter호출
} catch (Exception e) {
// TODO: handle exception
}
}
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) {
return Integer.valueOf(""+value);
}
return value;
}
// iv의 이름으로 setter의 이름을 만들어서 반환하는 메소드("name" --> "setName")
private static String getSetterName(String name) {
return "set"+StringUtils.capitalize(name);
}
}