본문 바로가기

학원/복기

[Spring] @RequestMapping, @RequestParam, @ModelAttribute (Request)

예제1)

 

MethodController

@Controller
public class MethodController {
	//사용자에게 값을 입력받기 위한 JSP 문서에 대한 ViewName을 반환하는 요청 처리 메소드
	// => 클라이언트의 요청방식에 상관없이 무조건 요청 처리 메소드를 호출
	@RequestMapping("/method_input")
	public String inputOne() {
		return "method_input1";
	}
	
	//전달값을 반환받아 Request Scope 속성값으로 저장하고 속성값을 출력하기 위한 JSP 문서의 
	//뷰이름(ViewName)을 반환하는 요청 처리 메소드
	@RequestMapping("/method_output")
	public String outputOne(HttpServletRequest request, HttpServletResponse response) throws IOException {
		//클라이언트가 현재 페이지를 GET 방식으로 요청한 경우 - 비정상적인 요청
		if(request.getMethod().equals("GET")) {
			response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);//클라이언트에게 405 에러 전달
			response.sendRedirect("method_input");//클라이언트에게 재요청할 수 있는 URL 주소 전달
			return null;
		}
		
		//POST 방식으로 요청되어 전달된 값에 대한 캐릭터셋 변경 (반드시 예외 처리)
		request.setCharacterEncoding("utf-8");
		//전달값을 반환받아 저장 
		String name=request.getParameter("name");
		//전달값을 request 객체의 속성값으로 저장 
		request.setAttribute("name", name);
		return "method_output";
	}
}

 

 

method_input1.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>입력페이지</title>
</head>
<body>
	<h1>입력페이지</h1>
	<hr>
	<form action="method_output" method="post">
		이름: <input type="text" name="name">
		<button type="submit">제출</button>
	</form>
</body>
</html>

 

method_output

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>출력페이지</h1>
	<hr>
	<h2>${name }님, 환영합니다.</h2>
</body>
</html>

 


 

스프링에서는 클라이언트가 GET방식, POST 방식으로 요청한 경우를 각각 다르게 처리할 수 있다.

위의 예시에서는 비정상적인 요청(GET 방식 요청)을 따로 처리해주어야 했는데 스프링을 이용하면 그러지 않아도 되기 때문에 편리하다.

 

1. 클라이언트가 GET 방식으로 요청한 경우 

 

이번엔 마찬가지로 사용자에게 값을 입력받기 위한 JSP 문서에 대한 ViewName을 반환하는 요청 처리 메소드를 선언할 건데, 클라이언트가 현재 페이지를 [GET] 방식으로 요청한 경우 요청 처리 메소드 호출하도록 만들어 볼 것이다.

 

method 속성

  • method 속성에는 RequestMethod 자료형(Enum)의 상수(Constant) 중 하나를 설정한다.
    • RequestMethod 자료형(Enum)은 클라이언트의 요청방식을 상수로 제공하는 자료형이다.
    • method 속성값으로 설정된 요청방식이 아닌 형태로 요청한 경우 클라이언트에게 405 에러코드를 전달한다. (자동)

 

GET 방식으로 요청 처리 메소드를 호출하기 위해 @RequestMapping 어노테이션 대신 @GetMapping 어노테이션을 사용하는 것도 가능하다.

@RequestMapping(value = "/method", method = RequestMethod.GET)
public String inputTwo() {
	return "method_input2";
}

 

2. 클라이언트가 POST 방식으로 요청한 경우 

 

전달값을 반환받아 Request Scope 속성값으로 저장하고 속성값을 출력하기 위한 JSP 문서의 뷰이름(ViewName)을 반환하는 요청 처리 메소드를 선언할 것인데, 클라이언트가 현재 페이지를 [POST] 방식으로 요청한 경우 요청 처리 메소드를 호출하도록 만들 것이다.

 

요청 처리 메소드를 호출하는 요청 URL 주소가 같아도 요청방식을 다르게 설정하면 다르게 매핑 처리된다.

@RequestMapping(value = "/method", method = RequestMethod.POST)
public String outputTwo(HttpServletRequest request) throws UnsupportedEncodingException {
	request.setCharacterEncoding("utf-8");
	String name=request.getParameter("name");
	request.setAttribute("name", name);
	return "method_output";
}

 


예제2)

 

ParamController

@Controller
public class ParamController {
	@RequestMapping(value = "/param", method=RequestMethod.GET)
	public String form() {
		return "param_form";
	}
	
	//요청 처리 메소드의 매개변수에 HttpServletRequest 인터페이스로 매개변수를 선언하면 Front Controller에게
	//클라이언트의 요청정보가 저장된 HttpServletRequest 객체를 제공받아 사용 가능
	// => HttpServletRequest 객체의 메소드를 호출하여 현재 페이지 요청시 전달된 값을 반환받아 사용
	@RequestMapping(value = "/param", method = RequestMethod.POST)
	public String result(HttpServletRequest request) throws UnsupportedEncodingException {
		request.setCharacterEncoding("utf-8");
		String food=request.getParameter("food");
		request.setAttribute("food", food);
		return "param_display";
	}
}

 

 

param_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>입력페이지</h1>
	<hr>
	<form action="param" method="post">
		내가 좋아하는 음식 : <input type="text" name="food">
		<button type="submit">제출</button>
	</form>
</body>
</html>

 

param_display.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRINF</title>
</head>
<body>
	<h1>출력페이지</h1>
	<hr>
	<h2>오늘의 점심은 [${food }]로 결정 하였습니다.</h2>
</body>
</html>


 

요청 처리 메소드에서 현재 페이지를 요청할 때 전달된 값의 이름과 같은 이름으로 원시형 또는 String 클래스의 매개변수를 선언하면 Front Controller는 전달값을 매개변수에 자동으로 저장하여 제공한다.

  • 전달값의 이름과 매개변수의 이름이 같지 않은 경우 String 자료형의 매개변수에는 [null]이 저장된다.
  • 원시형의 매개변수는 전달값의 이름과 매개변수의 이름이 같지 않은 경우 또는 원시형에 맞지 않은 값이 전달된 경우 400 에러코드가 발생한다.

매개변수를 이용하여 전달값을 제공받아 사용하기 전에 리퀘스트 메세지 몸체부에 저장되어 전달되는 값에 대한 문자형태(캐릭터셋) 변경 처리할 수 있다. (인코딩 필드 사용)

 

필터(Filter) : 웹프로그램 실행 전과 후에 실행될 명령을 제공하는 기능의 프로그램

  • Filter 인터페이스를 상속받은 자식클래스(Filter 클래스)를 생성하여 [web.xml] 파일에 필터로 등록하여 사용한다.
  • 필터는 Front Controller 실행 전에 위치하여 필요한 기능을 제공해준다. - WAS 프로그램으로 제어

 

클라이언트의 모든 요청에 대해 리퀘스트 메세지 몸체부에 저장되어 전달되는 값에 대한 문자형태(캐릭터셋)을 변경하는 인코딩 필터가 사용되도록 [web.xml] 파일을 설정

 

web.xml

...
	<filter>
		<!-- filter-name : 필터를 구분하기 위한 식별자를 설정하기 위한 엘리먼트 -->
		<filter-name>encodingFilter</filter-name>
		<!-- filter-class : 필터로 구현하기 위한 클래스를 설정하는 엘리먼트  -->
		<!-- CharacterEncodingFilter : 리퀘스트 메세지 몸체부에 저장되어 전달되는 값에 대한 
		문자형태(캐릭터셋)를 변경하는 기능을 제공하는 필터 클래스 -->
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<!-- init-param 엘리먼트를 사용하여 CharacterEncodingFilter 클래스에 변경할 문자형태(캐릭터셋)를 제공 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	
	<!-- filter-mapping : 필터가 실행될 수 있는 웹프로그램의 URL 주소를 등록하기 위한 엘리먼트  -->
	<filter-mapping>
		<!-- filter-name : 설정된 URL 주소로 실행될 필터의 식별자를 설정하기 위한 엘리먼트 -->
		<filter-name>encodingFilter</filter-name>
		<!-- url-pattern : 필터를 실행하기 위한 URL 주소(패턴)를 설정하기 위한 엘리먼트 -->
		<!-- => 클라이언트의 모든 요청에 대해 필터가 실행되도록 등록 -->
		<url-pattern>/*</url-pattern>
	</filter-mapping>
 ...

 

ParamController

@Controller
public class ParamController {
	@RequestMapping(value = "/param", method=RequestMethod.GET)
	public String form() {
		return "param_form";
	}

	
	@RequestMapping(value = "/param", method = RequestMethod.POST)
	public String result(String food, Model model) {
		model.addAttribute("food", food);
		return "param_display";
	}	
}

 


@RequestParam 

 

전달값을 제공받아 저장하기 위한 매개변수에 @RequestParam 어노테이션을 사용할 수 있다. (권장하는 방법)

 

@RequestParam은 전달값을 제공받아 매개변수에 저장하기 위한 어노테이션이다. 

  • 매개변수의 이름과 같은 이름으로 전달된 값이 없는 경우 400 에러코드가 발생한다.
  • 전달값의 이름을 매개변수의 이름과 같도록 하여 매개변수에 반드시 전달값이 저장되도록 설정하기 위한 어노테이션이다.
@RequestMapping(value = "/param", method = RequestMethod.POST)
public String result(@RequestParam String food, Model model) {
	model.addAttribute("food", food);
	return "param_display";
}

 

 

@RequestParam의 required 속성에는 false(선택 전달값) 또는 true(필드 전달값 - 기본값) 중 하나를 속성값으로 설정한다.

  • required 속성값을 [true]로 설정하면 매개변수의 이름과 전달값의 이름을 동일하게 작성하여 매개변수에 전달값이 저장된다.
  • required 속성값을 [true]로 설정한 경우 전달값의 이름과 매개변수의 이름이 같아도 전달값이 없으면 매개변수에 [null]이 저장된다. - 400 에러코드 미발생 

@RequestParamvalue 속성에는 전달값의 이름을 속성값으로 설정한다.

  • @RequestParam 어노테이션의 value 속성값을 이용하여 전달값을 제공받아 매개변수에 저장한다.
  • 전달값의 이름과 매개변수의 이름을 다르게 작성할 경우 사용하는 속성이다.
  • 다른 속성이 없으면 속성값만 설정이 가능하다.
@RequestMapping(value = "/param", method = RequestMethod.POST)
public String result(@RequestParam(required = true, value = "foodname") String food, Model model) {
	model.addAttribute("food", food);
	return "param_display";
}

 

@RequestParamdefaultValue 속성에는전달값과 매개변수의 이름이 다른 경우 매개변수에 저장된 기본값을 속성값으로 설정한다.

  • 전달값이 없는 경우에도 매개변수에 [null] 대신 저장될 기본값으로 사용한다.
@RequestMapping(value = "/param", method = RequestMethod.POST)
public String result(@RequestParam(defaultValue = "된장찌개", value = "foodname") String food, Model model) {
	model.addAttribute("food", food);
	return "param_display";
}

 


예제3)

 

 

 

회원정보를 저장하기 위한 클래스 (VO 클래스 : 값을 저장할 목적의 객체를 생성하기 위한 클래스) 선언

  • DAO 클래스의 메소드에서 사용될 경우 DTO 클래스의 기능을 제공함
  • 페이지 요청시 전달된 값을 저장하기 위해 전달값의 이름과 동일한 이름으로 필드를 작성해주어야 함 

Member

@Data
public class Member {
	private String id;
	private String passwd;
	private String name;
	private String email;
}

 

JoinController

@Controller
public class JoinController {
	//회원정보를 입력받기 위한 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드	
	@RequestMapping(value = "/join", method = RequestMethod.GET)
	public String join() {
		return "join_form";
	}
	
	//전달값(회원정보)을 제공받아 Request Scope 속성값으로 저장하고 속성값을 출력하는 JSP 문서의
	//뷰이름을 반환하는 요청 처리 메소드
	// => 전달값과 같은 이름의 매개변수를 선언하여 전달값을 제공받아 요청 처리 메소드에서 사용
	// => 매개변수에 @RequestParam 어노테이션을 사용하여 전달값의 이름과 매개변수의 이름이 
	//다른 경우 400 에러코드가 발생되도록 작성
	@RequestMapping(value = "/join", method = RequestMethod.POST)
	public String join(@RequestParam String id, @RequestParam String passwd
			, @RequestParam String name, @RequestParam String email, Model model) {
		model.addAttribute("id", id);
		model.addAttribute("passwd", passwd);
		model.addAttribute("name", name);
		model.addAttribute("email", email);
		return "join_display";
	}
}

 

 

매개변수에 @RequestParam 어노테이션 대신 @ModelAttribute 어노테이션을 사용해도 된다.


@ModelAttribute 은 객체(값)을 뷰에게 제공하기 위한 어노테이션이다.

  • @ModelAttribute 어노테이션을 메소드에 사용하면 메소드의 반환값을 요청 처리 클래스의 모든 요청 처리 메소드의 뷰에게 제공한다.
  • @ModelAttribute 어노테이션을 매개변수에 사용하면 매개변수에 저장된 값을 현재 요청 처리 메소드의 뷰에게 제공한다. (Model 객체를 사용하지 않고 뷰에게 필요한 객체(값)을 속성값으로 제공)
    • value 속성 : 뷰에서 속성값을 사용하기 위한 속성명을 속성값으로 설정 (다른 속성이 없는 경우 속성값만 설정 가능)

 

..
@RequestMapping(value = "/join", method = RequestMethod.POST)
public String join(@ModelAttribute(value="id") String id, @ModelAttribute("passwd") String passwd
		, @ModelAttribute("name") String name, @ModelAttribute("email") String email) {
	return "join_display";
}
..

 

 

전달값(회원정보)를 제공받아 VO 클래스의 객체 필드값으로 저장하고, 객체를 Request Scope 속성값으로 저장하여 속성값을 출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드를 선언할 것이다.

 

Model.addAttribute(Object attributeValue) : 객체를 속성값을 저장하여 뷰에게 제공하는 메소드 - Request Scope

  • 매개변수에 속성값을 사용할 수 있는 속성명을 전달하지 않으면 속성값으로 저장되는 객체의 자료형(클래스)의 이름을 속성명으로 사용 (첫문자는 소문자로 변환되어 사용된다)
  • 속성값이 원시값(Wrapper 객체) 또는 문자열(String 객체)는 반드시 속성명을 설정

 

@RequestMapping(value="/join", method = RequestMethod.POST)
public String join(@RequestParam String id, @RequestParam String passwd 
		,@RequestParam String name, @RequestParam String email, Model model) {
	//VO(DTO) 클래스로 객체 생성하여 매개변수에 저장된 전달값으로 필드값 변경
	Member member=new Member();
	member.setId(id);
	member.setPasswd(passwd);
	member.setName(name);
	member.setEmail(email);
		
	model.addAttribute("member", member);
		
	return "join_display";
}

 

addAttribute() 메소드에서 attributeName(속성명)은 생략이 가능하다

model.addAttribute(member);//객체(값)을 속성값으로 저장하여 뷰에게 제공 - Request Scope

 

join_display.jsp

<ul>
	<li>아이디 = ${member.id }</li>
	<li>비밀번호 = ${member.passwd }</li>
	<li>이름 = ${member.name }</li>
	<li>이메일 = ${member.email }</li>
</ul>

 


 

요청 처리 메소드에 VO(STO) 클래스로 매개변수를 작성하면 Front Controller는 VO(DTO) 클래스로 객체를 생성하여 매개변수에 저장되도록 제공한다.

  •   매개변수에 저장된 VO(DTO) 클래스의 객체에는 페이지 요청시 전달된 값과 같은 이름의 필드에 전달값을 제공받아 저장한다.

Command 객체: 전달값을 제공받아 필드에 저장된 객체로 속성값으로 저장되어  요청 처리 메소드의 뷰에서 사용될 수 있도록 제공되는 객체이다. ex) Member 객체 

  • Command 객체를 저장하기 위한 매개변수에 @ModelAttribute 어노테이션을 사용한다.
  • @ModelAttribute 어노테이션을 생략해도 자동으로 @ModelAttribute 어노테이션이 설정된 것과 동일하게 처리된다. (하지만 사용하는 것을 권장한다.)
  • @ModelAttribute 어노테이션에 value 속성을 생략하면 Command 객체의 자료형(클래스)을 속성명으로 자동으로 설정한다. - 첫문자는 소문자로 변환 
@RequestMapping(value = "/join", method = RequestMethod.POST)
public String join(@ModelAttribute Member member) {
	return "join_display";
}

 

@ModelAttribute 어노테이션의 value 속성을 사용하여 뷰에게 제공될 속성값의 속성명을 변경할 수 있다. 

@RequestMapping(value = "/join", method = RequestMethod.POST)
public String join(@ModelAttribute("mem") Member member) {
	return "join_display";
}

 

이 예시의 경우 뷰에게 'mem'이라는 이름으로 제공될 것이다. 

 

join_display.jsp

<ul>
	<li>아이디 = ${mem.id }</li>
	<li>비밀번호 = ${mem.passwd }</li>
	<li>이름 = ${mem.name }</li>
	<li>이메일 = ${mem.email }</li>
</ul>

 

 

아이디가 중복된 경우 메세지를 출력하도록 만들어보자 

@RequestMapping(value = "/join", method = RequestMethod.POST)
public String join(@ModelAttribute("mem") Member member, Model model) {
	if(member.getId().equals("abc123")) {//아이디가 중복된 경우
		model.addAttribute("message", "이미 사용중인 아이디를 입력 하였습니다.");
		return "join_form";
	}
	return "join_display";
}

 

join_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원가입</h1>
	<hr>
	<form action="join" method="post">
	<table>
		<tr>
			<td>아이디</td>
			<td><input type="text" name="id" value="${mem.id }"></td>
		</tr>
		<tr>
			<td>비밀번호</td>
			<td><input type="password" name="passwd" value="${mem.passwd }"></td>
		</tr>
		<tr>
			<td>이름</td>
			<td><input type="text" name="name" value="${mem.name }"></td>
		</tr>
		<tr>
			<td>이메일</td>
			<td><input type="text" name="email" value="${mem.email }"></td>
		</tr>
		<tr>
			<td colspan="2"><button type="submit">회원가입</button></td>
		</tr>
	</table>
	</form>
	<p style="color: red;">${message }</p>
</body>
</html>

 

 


VO 클래스가 없는 경우(예제의 경우 Member 클래스) 요청 처리 메소드의 매개변수를 Map 인터페이스로 작성하면 Front Controller는 Map 객체를 생성하여 매개변수에 저장되도록 제공한다.

  • 페이지 요청시 모든 전달값을 Map 객체의 엔트리로 추가하여 매개변수에 Map 객체를 저장한다. 따라서 VO 클래스를 만들지 않아도 된다.
  • Map 객체에는 전달값의 이름을 맵키(MapKey - String)로 제공받고 전달값은 맵값(MapValue - String)으로 제공받아 추가된다.
  • 매개변수에 전달값이 저장된 Map 객체를 저장하기 위해서는 반드시 매개변수에 @RequestParam 어노테이션을 사용해야 한다. 
@RequestMapping(value = "/join", method = RequestMethod.POST)
public String join(@RequestParam Map<String, String> map, Model model) {
	model.addAttribute("mem",map);
	return "join_display";
}

 

같은 이름으로 전달된 값이 있는 경우 필드의 자료형을 배열로 해서 전달 받으면 된다.

@RequestMapping(value = "/same_param", method = RequestMethod.GET)
public String input() {
	return "same_form";
}
	
//같은 이름으로 전달된 값이 있는 경우 배열을 저장할 수 있는 매개변수를 작성하여 전달값을 문자열 배열로 제공받아 저장 
@RequestMapping(value = "/same_param", method = RequestMethod.POST)
public String input(@RequestParam String[] food, Model model) {
	model.addAttribute("food", food);
	return "same_display";
}

 

same_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>입력페이지</h1>
	<hr>
	<form action="same_param" method="post">
		좋아하는 음식-1 : <input type="text" name="food"><br>
		좋아하는 음식-2 : <input type="text" name="food"><br>
		<button type="submit">제출</button>
	</form>
</body>
</html>

 

same_display.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>입력페이지</h1>
	<hr>
	<h2>좋아하는 음식-1 : ${food[0]}</h2>
	<h2>좋아하는 음식-2 : ${food[1]}</h2>
</body>
</html>