본문 바로가기

TIL

TIL 240605 HTTP Request Parameter

어노테이션 기반 Spring의 Controller는 다양한 파라미터를 지원한다

 

@Controller 메서드 인수

 

- @PathVariable : URL 템플릿 변수에 액세스합니다

- RequestParam : 멀티파트 파일을 포함한 서블릿 요청 매개변수에 대한 액세스용. 매개 변수 값 선언된 메서드 인수 형식으로 변환됩니다

@RequestBody : HTTP 요청 본문에 액세스 본문 내용은 선언된 메서드로 변환

 

HTTP 헤더 조회

Spring에서의 Header 정보 조회

@Slf4j
@RestController
public class RequestHeaderController {

    @GetMapping("/request/headers")
    public String headers(
            HttpServletRequest request, // Servlet에서 사용한것과 같음
            HttpServletResponse response, // Servlet에서 사용한것과 같음
            @RequestHeader MultiValueMap<String, String> headerMap,
            @RequestHeader("host") String host,
            @CookieValue(value = "cookie", required = false) String cookie,
            HttpMethod httpMethod,
            Locale locale
    ) {
        log.info("request={}", request);
        log.info("response={}", response);
        log.info("headerMap={}", headerMap);
        log.info("host={}", host);
        log.info("cookie={}", cookie);
        log.info("httpMethod={}", httpMethod);
        log.info("Locale={}", locale);

        return "success";
    }
}

 

PostAPI 호출

 

log 출력 결과

 

  1. request : Servlet에서 사용한것과 같음
  2. response : Servlet에서 사용한것과 같음
  3. headerMap :
더보기

hashMap={
user-agent=[PostmanRuntime/7.35.0], 
accept=[*/*], 
postman-token=[5f324c1c-7902-4750-9e01-2c4d093e8ad6],
host=[localhost:8080],
accept-encoding=[gzip, deflate, br],
connection=[keep-alive]
}

4. host : host정보

5. cookie : Head의 Cookie

6. httpMethod : 호출에 사용한 HttpMethod

7. locale :  위치정보를 나타내는 헤더 우선순위가 존재한다. ( 한국기준 1순위 : ko, 2순위 : eng)

 

MultiValueMap

- Map과 유사하게 Key, Value 형식으로 구현되어 있지만, 하나의 Key가 여러 Value를 가질 수 있다

HTTP Header, Reqeust Parameter와 같이 하나의 Key에 여러 값을 받을 때 사용한다 ex) key1=value1&key1=value2

 

ex)

MultiValueMap<String, String> linkedMultiValuemap = new LinkedMultiValueMap();

// key1에 value1 저장
linkedMultiValuemap.add("key1", "value1");
// key1에 value2 저장
linkedMultiValuemap.add("key1", "value2");

// key1에 저장된 모든 value get
List<String> values = linkedMultiValuemap.get("key1");

 

Query Parameter, HTML Form Data

위 두가지 경우의 요청 파라미터 Spring에서 Mapping

HttpServletRequest.getParameter(”key”)

@RequestParam 어노테이션

 

Client에서 Server로 Data를 전달하는 3가지 방법

 

1. GET - Query Param

 - URL의 쿼리 파라미터를 사용하여 데이터 전달

<http://localhost:8080/param?**key1=value1&key2=value2**>

ex) Controller

@Slf4j
@Controller
public class RequestParamController {

    @GetMapping("/request/params")
    public void params(
						    HttpServletRequest request,
							HttpServletResponse response
								) throws IOException {
        String key1Value = request.getParameter("key1");
				String key2Value = request.getParameter("key2");
				log.info("key1Value={}, key2Value={}", key1Value, key2Value);
        response.getWriter().write("success");
    }
}

 

2. POST - HTML Form(x-www-form-urlencoded)

   - Request Body에 쿼리 파라미터 형태로 전달

POST /param

content-type: application/x-www-form-urlencoded

key1=value1&key2=value2

 

ex) Controller

@Slf4j
@Controller
public class RequestBodyController {

    @PostMapping("/request/body")
    public void requestBody(
						            HttpServletRequest request,
												HttpServletResponse response
											 ) throws IOException {
        String key1Value = request.getParameter("key1");
				String key2Value = request.getParameter("key2");
				log.info("key1Value={}, key2Value={}", key1Value, key2Value);
        response.getWriter().write("success");
    }
}

 

 

3. HTTP RequestBody - 데이터(JSON, TEXT, XML 등)를 직접 담아서 사용

- 주로 @RestController에서 사용한다, 대부분 JSON으로 데이터 전달 ex) POST, PUT, PATCH Method에서 사용 GET, DELETE는 거의 Body가 없음 → 권장X

 

 

@RequestParam

URL에서 파라미터 값과 이름을 함께 전달하는 방식으로 주로 HTTP 통신 Method 중 GET 방식의 통신을 할 때 많이 사용한다.

Spring이 제공하는 해당 어노테이션을 사용하면 요청 파라미터값에 아주 쉽고 간편하게 접근(바인딩)할 수 있다

 

ex)

@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					@RequestParam("name") String userName,
					@RequestParam("age") int userAge													
	) {
		// logic
		return "success";
	}

}

 

  1. @Controller 이지만 Method에 @ResponseBody를 붙이게되면 View를 찾는것이 아니라 ResponseBody 데이터에 “success”가 들어간다. → 위 코드가 @RestController의 원본코드라 생각하시면 됩니다.
  2. @RequestParam : 파라미터 이름으로 바인딩
  3. @RequestParam(”속성값”) : 속성값이 파라미터 이름으로 매핑된다
  4. “속성값”과 변수명이 같으면 생략이 가능하다. ex) @RequestParam(name) String name
// GET http://localhost:8080/request/param?name=wonuk&age=100
@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					@RequestParam String name,
					@RequestParam int age													
	) {
		// logic
		return "success";
	}

}

 

5. 충격적이게도 사실 모두 생략해도된다. 참고 : 생략하면 (required=false) 속성이 default로 설정된다

// GET http://localhost:8080/request/param?name=wonuk&age=100
@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					String name,
					int age													
	) {
		// logic
		return "success";
	}

}

 

  • 단, 요청 파라미터와 이름이 완전히 같아야함
  • 단순 타입(int, String, Integer 등)이어야 한다

하지만 위의 방식은 권장하지 않는다, 명시적으로 표시되어있지 않으면 팀의 협의가 있지 않다면, 다른 개발자들에게 혼동을주기 충분하다.

@RequestParam이 있어야 요청 파라미터에서 데이터를 읽는구나 하게된다

 

 

파라미터 필수 여부 설정 required 속성

API 스펙을 규정할 때 사용, 필수값 설정

@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					@RequestParam(required = true) String name, // 필수
					@RequestParam(required = false) int age	// 필수가 아님	
			 // @RequestParam(required = false) Integer age											
	) {
		// logic
		return "success";
	}

}
  • @RequestParam을 사용하면 기본 Default값은 True이다.
    • True 설정된 파라미터에 값이 존재하지 않으면 400 BadRequest Error
    • Exception이 발생하지 않는 경우
    • Exception이 발생하는 경우
      • ex) http://localhost:8080/request/param?age=100
      • ex) http://localhost:8080/request/param
  • required = false 설정이 되어있으면 해당 파라미터는 없어도 된다.
    • 하지만! 여기서 만약 http://localhost:8080/request/param?name=wonuk 로 요청한다면?
    • 500 Error가 발생한다
    • int Type에는 null을 넣을 수 없기 때문에! 0이라도 들어가야한다 Integer = null
    • 따라서 보통 null을 허용하는 Integer로 사용하거나 default 옵션을 사용한다.
  • 파라미터 Key값만 있고 Value가 없는 경우 http://localhost:8080/request/param?name=
    • null과 빈 문자열 “”은 다르다!
    • 위 형태는 빈 문자열 “” 로 인식한다, True지만 통과가 되어버린다. 주의해야함
  1. default 속성 적용 (기본값)
@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					@RequestParam(required = true, defaultValue = "wonuk") String name,
			    @RequestParam(required = false, defaultValue = "1") int age											
	) {
		// logic
		return "success";
	}

}

 

  • name Parameter 의 값이 없으면 기본적으로 “wonuk”으로 설정한다
    • ex) http://localhost:8080/request/param?age=100
    • ex) http://localhost:8080/request/param
  • age Parameter의 값이 없으면 기본적으로 0 으로 설정한다
    • ex) http://localhost:8080/request/param?name=wonuk
    • ex) http://localhost:8080/request/param
  • defaultValue 속성을 설정하게 되면 “” 빈문자열의 경우에도 기본값이 설정된다. 주의

8. Map 으로 조회

 

@Controller
public class RequestParamController {

	@ResponseBody
	@GetMapping("/request/param")
	public String requestParam (
					@RequestParam Map<String, Object> paramMap										
	) {
		// logic
		String name = paramMap.get("name");
		Integer age = paramMap.get("age");
		
		return "success";
	}

}

 

  1. Map 형태로 조회가 가능하다
    1. ex) key=value
    2. ex) http://localhost:8080/request/param?name=wonuk&age=100
  2. MultiValueMap 형태로 조회가 가능하다
    1. ex) key=[value1, value2]
    2. ex) http://localhost:8080/request/param?name=wonuk1&name=wonuk2&name=wonuk3

파라미터 Map의 Value가 1개인 경우에는 Map, 여러개인 경우 MultiValueMap을 사용한다 하지만 대부분 한개인 경우로 구성되어 있다.

 

 

'TIL' 카테고리의 다른 글

TIL 240610 예외 처리 변경  (0) 2024.06.11
TIL 240607 Spring Request Mapping  (0) 2024.06.10
TIL 240604 Annotation  (0) 2024.06.05
TIL 240603 인증, 인가  (0) 2024.06.04
TIL 240531 Validation  (0) 2024.05.31