ㅁ 요청시 전달값(parameter)들을 뽑아서 변수에 담거나 dto에 담아서 넘겼었다.
ㅁ 요청시 전달되는 데이터들이 많은데 그 데이터들을 어떻게 처리할지 (요청시 데이터를 뽑는 과정)
ㅁ 요청시 파라미터를 처리하는 방법 3가지
(1) HttpServletRequest 방법
(2) @RequestParam 방법
(3) 커맨드 객체 방법
- 1번째 기능은 스프링 이전의 전통적인 방법이다. 2번째 기능부터 스프링 프레임워크의 기능이라고 생각하면 된다.
(1) HttpServletRequest 방법
ㅁ main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="${ contextPath }/resources/js/sample.js"></script>
<script src="${ contextPath }/assets/js/jquery-3.7.1.min.js"></script>
</head>
<body>
<!-- / 또는 /main.do라는 url mapping으로 요청시 해당 /WEB-INF/views/main.jsp가 보여지도록 한다. -->
<h1>메인페이지입니다</h1>
<h3>1. 정적 자원 확인</h3>
<img src="${ contextPath }/resources/images/1.jpeg" width="100" onclick="test();">
<img src="${ contextPath }/assets/images/2.jpg" width="100" id="img">
<script>
$(function(){
$('#img').on("click", () => {
alert("어서오세요");
})
})
</script>
<hr>
<h3>2. 응답페이지 보여지게 하는 연습 (포워딩, redirect)</h3>
<!-- <a href="${contextPath}/list.bk">도서목록페이지로 이동</a> -->
<a href="${contextPath}/book/list.do">도서목록페이지로 이동</a> <br>
<a href="${contextPath}/book/enrollForm.do">도서등록페이지로 이동</a>
<hr>
<h3>3. 요청시 전달되는 파라미터 처리하는 연습 (request의 parameter)</h3>
<!-- <a href="${contextPath}/detail.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail.do?no=1">회원상세조회</a> <br>
</body>
</html>
ㅁ controller 패키지에 MemberController 일반 클래스를 만든다.
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
}
- 컨트롤러 패키지는 항상 클래스 상단에 @Controller를 써서 빈으로 등록한다.
- @RequestMapping("/member")
- 기존에 하던 방식대로 request에서 값을 뽑아서, 형변환해서 변수에 대입시켰다.
- 이번엔 하나의 데이터 말고 다수의 데이터를 요청시 넘겨본다.
ㅁ main.jsp 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="${ contextPath }/resources/js/sample.js"></script>
<script src="${ contextPath }/assets/js/jquery-3.7.1.min.js"></script>
</head>
<body>
<!-- / 또는 /main.do라는 url mapping으로 요청시 해당 /WEB-INF/views/main.jsp가 보여지도록 한다. -->
<h1>메인페이지입니다</h1>
<h3>1. 정적 자원 확인</h3>
<img src="${ contextPath }/resources/images/1.jpeg" width="100" onclick="test();">
<img src="${ contextPath }/assets/images/2.jpg" width="100" id="img">
<script>
$(function(){
$('#img').on("click", () => {
alert("어서오세요");
})
})
</script>
<hr>
<h3>2. 응답페이지 보여지게 하는 연습 (포워딩, redirect)</h3>
<!-- <a href="${contextPath}/list.bk">도서목록페이지로 이동</a> -->
<a href="${contextPath}/book/list.do">도서목록페이지로 이동</a> <br>
<a href="${contextPath}/book/enrollForm.do">도서등록페이지로 이동</a>
<hr>
<h3>3. 요청시 전달되는 파라미터 처리하는 연습 (request의 parameter)</h3>
<!-- <a href="${contextPath}/detail.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail.do?no=1">회원상세조회</a> <br><br><br>
<!-- (1) HttpServletRequest 방법 -->
<form action="${ contextPath }/member/enroll1.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
</body>
</html>
ㅁ MemberController 수정
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
// @RequestMapping(value="/enroll1.do", method=RequestMethod.GET) - 405 에러 발생
// @RequestMapping(value="/enroll1.do", method=RequestMethod.POST) - 이렇게 해도 되고,
@PostMapping("/enroll1.do") // 스프링이 버전업되며 새로 나온 방식
public String memberEnroll1(HttpServletRequest request) {
// request.setCharacterEncoding("utf-8"); -> 스프링에서 제공하는 인코딩 필터 등록 (web.xml)
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String address = request.getParameter("address");
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + address);
return "main";
}
}
- Sping이 버전업 되면서 @GetMapping, @PostMapping을 지원한다.
메소드 속성을 생략할 수 있다.
- Spring Boot에서는 HTTP 메서드에 따라 더 명확한 @GetMapping, @PostMapping 같은 어노테이션이 제공되기 때문에, 이러한 어노테이션을 사용하는 것이 권장된다.
- request.setCharacterEncoding("utf-8")
빨간줄 뜬다. 서블릿에서 할 때는 throws로 던졌다.
- 필터 클래스를 등록한다. 직접 만들 필요 없이 스프링이 제공하는 인코딩 필터를 web.xml에 등록한다.
- post방식 요청인데 메소드를 get으로 설정해본다.
- 요청 전송 방식이 맞지 않을 경우 405 에러가 발생한다.
ㅁ web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 스프링에서 제공하는 인코딩 필터 등록 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- 서블릿 등록에 <servlet>, <servlet-mapping> 태그를 사용하듯이
필터 등록엔 <filter>, <filter-mapping> 태그를 사용한다.
- 서버가 시작될 때 해당 설정이 바로 로드되므로, 설정 파일에 오타나 오류가 있으면 애플리케이션이 시작되지 않고 오류가 발생할 수 있다.
- Spring Boot는 자동으로 UTF-8 인코딩을 설정하므로, 별도의 설정이 필요하지 않습니다.
ㅁ 회원등록 해보기
- 이름, 나이, 주소를 입력하고 '등록' 버튼을 누른다.
ㅁ
- 스프링을 쓰는 이유가 별로 없다. 내가 직접 뽑고 직접 변수에 담았다.
==================================================================================
(2) @RequestParam 방법
ㅁ main.jsp 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="${ contextPath }/resources/js/sample.js"></script>
<script src="${ contextPath }/assets/js/jquery-3.7.1.min.js"></script>
</head>
<body>
<!-- / 또는 /main.do라는 url mapping으로 요청시 해당 /WEB-INF/views/main.jsp가 보여지도록 한다. -->
<h1>메인페이지입니다</h1>
<h3>1. 정적 자원 확인</h3>
<img src="${ contextPath }/resources/images/1.jpeg" width="100" onclick="test();">
<img src="${ contextPath }/assets/images/2.jpg" width="100" id="img">
<script>
$(function(){
$('#img').on("click", () => {
alert("어서오세요");
})
})
</script>
<hr>
<h3>2. 응답페이지 보여지게 하는 연습 (포워딩, redirect)</h3>
<!-- <a href="${contextPath}/list.bk">도서목록페이지로 이동</a> -->
<a href="${contextPath}/book/list.do">도서목록페이지로 이동</a> <br>
<a href="${contextPath}/book/enrollForm.do">도서등록페이지로 이동</a>
<hr>
<h3>3. 요청시 전달되는 파라미터 처리하는 연습 (request의 parameter)</h3>
<!-- <a href="${contextPath}/detail.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail.do?no=1">회원상세조회</a> <br><br><br>
<!-- (1) HttpServletRequest 방법 -->
<form action="${ contextPath }/member/enroll1.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
<br><br>
<!-- (2) @RequestParam 방법 -->
<form action="${ contextPath }/member/enroll2.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
</body>
</html>
ㅁ MemberController 수정
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
// @RequestMapping(value="/enroll1.do", method=RequestMethod.GET) - 405 에러 발생
// @RequestMapping(value="/enroll1.do", method=RequestMethod.POST) - 이렇게 해도 되고,
@PostMapping("/enroll1.do") // 스프링이 버전업되며 새로 나온 방식
public String memberEnroll1(HttpServletRequest request) {
// request.setCharacterEncoding("utf-8"); -> 스프링에서 제공하는 인코딩 필터 등록 (web.xml)
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String address = request.getParameter("address");
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + address);
return "main";
}
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(@RequestParam(value="name") String name
, @RequestParam(value="age") int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
return "main";
}
}
- @RequestParam 어노테이션 하나하나가 곧 request.getPrameter()다.
- 내가 형변환하지 않아도 자동으로 parsing되서 담긴다.
- 이름, 나이, 주소를 입력하고 '등록' 버튼을 누른다.
ㅁ MemberController 수정
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, @RequestParam(value="age") int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
return "main";
}
- 매개변수 name 처럼 요청시 전달되는 key값과 매개변수의 이름이 같으면 @RequestParam 어노테이션을 생략할 수 있다.
- 매개변수 addr은 요청시 전달되는 key값과 매개변수 이름이 달라서 @RequestParam 어노테이션을 생략할 수 없다.
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, /*@RequestParam(value="age")*/ int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
return "main";
}
- 그런데 String형이 아닌 int형 변수는 @RequestParam 어노테이션을 생략하면 오류가 발생할 수 있다.
int형은 null이 담길 수가 없고 숫자만 담긴다.
자동으로 파싱되는 과정이 있기 때문에 null이 오면 오류가 발생할 수 있다.
- int형 변수 age의 @RequestParam 어노테이션을 생략했을 때, 숫자
- 텍스트 상자에 아무 값도 입력하지 않고 요청을 보내면 빈 문자열이 담긴다.
- 400 오류가 발생한다.
- 콘솔에도 MethodArgumentTypeMismatchException이 발생했다고 출력된다.
- HTTP 요청에서 받은 파라미터의 타입이 메서드에서 요구한 타입과 맞지 않아서 발생.
- String 타입을 int로 변환하려고 했는데, 변환하려는 값이 빈 문자열이어서, 정수형(int)으로 변환할 수 없기 때문에 발생.
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, @RequestParam(value="age", defaultValue="10") int age
, @RequestParam("address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
return "main";
}
- 그런데 @RequestParam 어노테이션을 생략했을 때만 400에러가 발생하는 것은 아니다.
@RequestParam 어노테이션이 있어도 내부적으로 파싱돼서 매개변수에 담기기 때문에 빈문자열이 올 경우 400 에러가 발생한다.
- defaultValue 속성으로 기본값을 지정하면 오류가 나지 않는다.
- 그리고 value 속성 하나만 사용할거면 "value="을 생략할 수 있다. 알아서 value로 인식된다.
- 마이바티스를 쓰면 데이터를 하나만 넘길 수 있다. DTO에 담거나 Map에 담아서 넘긴다.
ㅁ com.br.mvc.dto 패키지에 MemberDto 일반 클래스 생성
package com.br.mvc.dto;
public class MemberDto {
private String name;
private int age;
private String addr;
public MemberDto() {
super();
}
public MemberDto(String name, int age, String addr) {
super();
this.name = name;
this.age = age;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "MemberDto [name=" + name + ", age=" + age + ", addr=" + addr + "]";
}
}
- 스프링 넘어오면서 필드명을 제시하면 내가 직접 게터 세터 메소드를 호출하지 않아도 내부적으로 실행되는 경우가 있다. 그래서 명명규칙을 잘 지켜야 한다. 이클립스는 자동완성 기능을 제공한다.
ㅁ MemberController 수정
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.br.mvc.dto.MemberDto;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
// @RequestMapping(value="/enroll1.do", method=RequestMethod.GET) - 405 에러 발생
// @RequestMapping(value="/enroll1.do", method=RequestMethod.POST) - 이렇게 해도 되고,
@PostMapping("/enroll1.do") // 스프링이 버전업되며 새로 나온 방식
public String memberEnroll1(HttpServletRequest request) {
// request.setCharacterEncoding("utf-8"); -> 스프링에서 제공하는 인코딩 필터 등록 (web.xml)
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String address = request.getParameter("address");
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + address);
return "main";
}
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, @RequestParam(value="age", defaultValue="10") int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
MemberDto mem = new MemberDto();
mem.setName(name);
mem.setAge(age);
mem.setAddr(addr);
System.out.println(mem);
return "main";
}
@GetMapping("/detail2.do")
public String memberDetail2(int no) {
System.out.println("조회할 회원번호: " + no);
return "main";
}
}
- main의 2번째 form 가지고 요청해본다.
=====================================================================================
ㅁ main.jsp 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="${ contextPath }/resources/js/sample.js"></script>
<script src="${ contextPath }/assets/js/jquery-3.7.1.min.js"></script>
</head>
<body>
<!-- / 또는 /main.do라는 url mapping으로 요청시 해당 /WEB-INF/views/main.jsp가 보여지도록 한다. -->
<h1>메인페이지입니다</h1>
<h3>1. 정적 자원 확인</h3>
<img src="${ contextPath }/resources/images/1.jpeg" width="100" onclick="test();">
<img src="${ contextPath }/assets/images/2.jpg" width="100" id="img">
<script>
$(function(){
$('#img').on("click", () => {
alert("어서오세요");
})
})
</script>
<hr>
<h3>2. 응답페이지 보여지게 하는 연습 (포워딩, redirect)</h3>
<!-- <a href="${contextPath}/list.bk">도서목록페이지로 이동</a> -->
<a href="${contextPath}/book/list.do">도서목록페이지로 이동</a> <br>
<a href="${contextPath}/book/enrollForm.do">도서등록페이지로 이동</a>
<hr>
<h3>3. 요청시 전달되는 파라미터 처리하는 연습 (request의 parameter)</h3>
<!-- <a href="${contextPath}/detail.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail.do?no=1">회원상세조회</a> <br><br><br>
<!-- (1) HttpServletRequest 방법 -->
<form action="${ contextPath }/member/enroll1.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
<br><br>
<!-- (2) @RequestParam 방법 -->
<form action="${ contextPath }/member/enroll2.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
<!-- <a href="${contextPath}/detail2.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail2.do?no=1">회원상세조회</a> <br><br><br>
</body>
</html>
- detail2.do 만들었음.
ㅁ MemberController 수정
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
// @RequestMapping(value="/enroll1.do", method=RequestMethod.GET) - 405 에러 발생
// @RequestMapping(value="/enroll1.do", method=RequestMethod.POST) - 이렇게 해도 되고,
@PostMapping("/enroll1.do") // 스프링이 버전업되며 새로 나온 방식
public String memberEnroll1(HttpServletRequest request) {
// request.setCharacterEncoding("utf-8"); -> 스프링에서 제공하는 인코딩 필터 등록 (web.xml)
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String address = request.getParameter("address");
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + address);
return "main";
}
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, @RequestParam(value="age", defaultValue="10") int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
return "main";
}
@GetMapping("/detail2.do")
public String memberDetail2(int no) {
System.out.println("조회할 회원번호: " + no);
return "main";
}
}
- detail2.do 만들었음.
=======================================================================================
(3) 커맨드 객체 방법
- 요청 파라미터들을 각 필드에 담고자하는 객체에, 즉 전달값들을 특정 dto 객체에 바로 담는 경우 사용한다.
- 메소드의 매개변수로 전달값들을 담고자하는 객체를 작성하고,
요청 파라미터의 key값을 담고자하는 객체의 필드명으로 작성한다.
ㅁ 커맨드 객체는 ~다.
ㅁ 이제부턴 key값(name 속성값)도 중요하다.
어떤 필드에 담고 싶은지에 맞춰서 key값을 작성한다.
스프링이 내부적으로 setter메소드를 수행한다.
- /member/enroll3.do?name=홍길동&age=20&addr=서울 이라는 url 요청시
매개변수로 있는 DTO 객체를 기본생성자로 생성하고,
파라미터의 key값을 가지고 setter 메소드를 찾아서 실행한다.
(내부적으로 실행되는 내용)
MemberDto mem = new MemberDto();
mem.setName("홍길동");
mem.setAge(Integer.parseInt("20"));
mem.setAddr("서울");
- 그래서 dto 객체에 기본생성자와 setter 메소드가 존재해야 한다.
ㅁ main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="${ contextPath }/resources/js/sample.js"></script>
<script src="${ contextPath }/assets/js/jquery-3.7.1.min.js"></script>
</head>
<body>
<!-- / 또는 /main.do라는 url mapping으로 요청시 해당 /WEB-INF/views/main.jsp가 보여지도록 한다. -->
<h1>메인페이지입니다</h1>
<h3>1. 정적 자원 확인</h3>
<img src="${ contextPath }/resources/images/1.jpeg" width="100" onclick="test();">
<img src="${ contextPath }/assets/images/2.jpg" width="100" id="img">
<script>
$(function(){
$('#img').on("click", () => {
alert("어서오세요");
})
})
</script>
<hr>
<h3>2. 응답페이지 보여지게 하는 연습 (포워딩, redirect)</h3>
<!-- <a href="${contextPath}/list.bk">도서목록페이지로 이동</a> -->
<a href="${contextPath}/book/list.do">도서목록페이지로 이동</a> <br>
<a href="${contextPath}/book/enrollForm.do">도서등록페이지로 이동</a>
<hr>
<h3>3. 요청시 전달되는 파라미터 처리하는 연습 (request의 parameter)</h3>
<!-- <a href="${contextPath}/detail.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail.do?no=1">회원상세조회</a> <br><br><br>
<!-- (1) HttpServletRequest 방법 -->
<form action="${ contextPath }/member/enroll1.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
<br><br>
<!-- (2) @RequestParam 방법 -->
<form action="${ contextPath }/member/enroll2.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
<!-- <a href="${contextPath}/detail2.mem?no=1">회원상세조회</a> -->
<a href="${contextPath}/member/detail2.do?no=1">회원상세조회</a> <br><br><br>
<br><br>
<!-- (3) 커맨드 객체 방법 -->
<form action="${ contextPath }/member/enroll3.do" method="post">
이름 : <input type="text" name="name"> <br>
나이 : <input type="text" name="age"> <br>
주소 : <input type="text" name="address"> <br>
<button>등록</button>
</form>
</body>
</html>
ㅁ MemberController 수정
package com.br.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.br.mvc.dto.MemberDto;
@RequestMapping("/member")
@Controller
public class MemberController {
// 1. HttpServletRequest 방법
@RequestMapping("/detail.do")
public String memberDetail(HttpServletRequest request) {
int no = Integer.parseInt(request.getParameter("no"));
System.out.println("조회할 회원번호: " + no);
return "main"; // 응답은 메인페이지로 포워딩. 이게 중요한 건아닌데 404 거슬리니까.
}
// @RequestMapping(value="/enroll1.do", method=RequestMethod.GET) - 405 에러 발생
// @RequestMapping(value="/enroll1.do", method=RequestMethod.POST) - 이렇게 해도 되고,
@PostMapping("/enroll1.do") // 스프링이 버전업되며 새로 나온 방식
public String memberEnroll1(HttpServletRequest request) {
// request.setCharacterEncoding("utf-8"); -> 스프링에서 제공하는 인코딩 필터 등록 (web.xml)
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String address = request.getParameter("address");
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + address);
return "main";
}
// (2) @RequestParam 방법
// request.getParameter()를 자동으로 실행하는 어노테이션
@PostMapping("/enroll2.do")
public String memberEnroll2(/*@RequestParam(value="name")*/ String name
, @RequestParam(value="age", defaultValue="10") int age
, @RequestParam(value="address") String addr) {
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("주소: " + addr);
MemberDto mem = new MemberDto();
mem.setName(name);
mem.setAge(age);
mem.setAddr(addr);
System.out.println(mem);
return "main";
}
@GetMapping("/detail2.do")
public String memberDetail2(int no) {
System.out.println("조회할 회원번호: " + no);
return "main";
}
// (3) 커맨드 객체 방법
@PostMapping("/enroll3.do")
public String memberEnroll3(MemberDto mem){
System.out.println(mem);
return "main";
}
}
- 그냥 매개변수에 dto 객체만 주면 끝이다.
- main의 3번째 form 가지고 요청해본다.
- 그런데 주소는 안담겼다.
- key값과 dto 객체의 필드명이 달라서 담기지 않았다.
넘어오는 key값을 바꾸든지 dto의 필드명을 바꾸든지 일치시키면 주소값도 잘 담긴다.
ㅁ 그런데 input 태그에 required 속성이 없어서 특정값을 입력하지 않을 수도 있다.
- 이름과 주소는 입력하지 않아도 텍스트 상자는 빈 문자열이 온다. null이 아니다.
- 그런데 나이를 입력하지 않으면 400 에러가 발생한다. 보통 parsing에서 문제가 생기면 400에러가 발생한다.
빈 문자열을 parsing하려해서 오류가 발생했다. 빈 문자열에 숫자가 없으니 parsing할 수 없다.
- 나이를 입력하지 않으면 빈 문자열을 숫자로 parsing하려해서 오류가 발생한다.
- dto 객체의 age 필드가 int형이어서 문제가 된다. String형이었으면 그냥 빈 문자열이 담기고 끝이다.
값이 누락되면 이런 오류가 빈번하게 발생해서 dto의 필드들을 다 String형으로 두는 경우가 많다.
db에서 number타입이어도 크게 상관 없다.
- MemberDto에서 age 필드만 수정하면 되는게 아니고, 매개변수 생성자, getter, setter 등 int age가 쓰인 곳은 모두 수정해야 한다.
- 뒤늦게 필드를 수정할 때 그 필드만 수정하면 되는게 아니고 매개변수 생성자, getter, setter 등 그 필드가 쓰인 모든 곳을 수정해야 한다.
뒤늦게 필드를 추가할 때도 생성자, getter, setter를 전부 추가해야 한다.
- Lombok이라는 라이브러리를 사용하면 생성자, getter, setter 등을 일일이 작성하지 않아도 된다.
Lombok을 사용하지 않는 회사면 일일이 작성해야 한다.
- Lombok은 스프링의 기능이 아니다.
- 이제부터는 DTO 객체에 필드만 작성한다. 그러면 필드를 바탕으로 자동으로 생성자, getter, setter를 만들어 준다.
필드를 수정하면 알아서 생성자, getter, setter도 전부 바뀐다.