Light Blue Pointer
본문 바로가기
Developing/TIL(Develop)

Path Variable과 Request Param

by Greedy 2023. 11. 6.

Path Variable

  • Client 즉, 브라우저에서 서버로 HTTP 요청을 보낼 때 데이터를 함께 보낼 수 있다.
  • 서버에서는 이 데이터를 받아서 사용해야하는데 데이터를 보내는 방식이 한 가지가 아니라 여러 가지가 있기 때문에 모든 방식에 대한 처리 방법을 학습해야 한다.

templates→new→hello-request-form.html 생성

<!DOCTYPE html>
<html>
<head>
  <title>Hello Request</title>
</head>
<body>
<h2>GET /star/{name}/age/{age}</h2>
<form id="helloPathForm">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
</form>
<div>
  <button id="helloPathFormSend">전송</button>
</div>
<br>

<h2>GET /hello/request/form/param</h2>
<form method="GET" action="/hello/request/form/param">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>

<br>

<h2>POST /hello/request/form/param</h2>
<form method="POST" action="/hello/request/form/param">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>POST /hello/request/form/model</h2>
<form method="POST" action="/hello/request/form/model">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>GET /hello/request/form/param/model </h2>
<form method="GET" action="/hello/request/form/param/model">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
  <button>전송</button>
</form>
<br>

<h2>POST /hello/request/form/json</h2>
<form id="helloJsonForm">
  <div>
    이름: <input name="name" type="text">
  </div>
  <div>
    나이: <input name="age" type="text">
  </div>
</form>
<div>
  <button id="helloJsonSend">전송</button>
</div>
<div>
  <div id="helloJsonResult"></div>
</div>
</body>
<script>
  // GET /star/{name}/age/{age}
  const helloPathForm = document.querySelector("#helloPathFormSend")
  helloPathForm.onclick = (e) => {
    const form = document.querySelector("#helloPathForm");
    const name = form.querySelector('input[name="name"]').value;
    const age = form.querySelector('input[name="age"]').value;
    const relativeUrl = `/hello/request/star/${name}/age/${age}`;
    window.location.href = relativeUrl;
  }

  // POST /hello/request/form/json
  const helloJson = document.querySelector("#helloJsonSend")
  helloJson.onclick = async (e) => {
    const form = document.querySelector("#helloJsonForm");

    const data = {
      name: form.querySelector('input[name="name"]').value,
      age: form.querySelector('input[name="age"]').value
    }

    const response = await fetch('/hello/request/form/json', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    })

    const text = await response.text(); // read response body as text
    document.querySelector("#helloJsonResult").innerHTML = text;
  };
</script>
</html>

request 패키지 만들어줌

request 패키지 → RequestController 클래스 생성

package com.sparta.springmvc.request;

import org.springframework.stereotype.Controller;

@Controller
public class RequestController {
}

아까 만든 html을 반환해야해서 Controller 달아줌

package com.sparta.springmvc.request;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/hello/request")
public class RequestController {
    @GetMapping("/form/html")
    public String helloForm() {
        return "hello-request-form";
    }
}

브라우저 주소창에다 이거 입력한다

http://localhost:8080/hello/request/form/html

 

Path Variable 방식

data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==

GET http://localhost:8080/hello/request/star/Robbie/age/95

서버에 보내려는 데이터를 URL 경로에 추가할 수 있다.

/star/Robbie/age/95

‘Robbie’와 ‘95’ 데이터를 서버에 보내기 위해 URL 경로에 추가함

// [Request sample]
// GET <http://localhost:8080/hello/request/star/Robbie/age/95>
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age)
{
    return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
}

helloRequestPath method 추가해줌

// [Request sample]
// GET <http://localhost:8080/hello/request/star/Robbie/age/95>
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age)
{
    return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
}

URL 경로에서 데이터를 받고자 하는 위치의 경로에 {data} 중괄호를 사용

: /star/{name}/age/{age}

해당 요청 메서드 파라미터에 @PathVariable 애너테이션과 함께 {name} 중괄호에 선언한 변수명과 변수타입을 선언해서 해당 경로의 데이터를 받아옴

: (@PathVariable String name, @PathVariable int age)

Spring이 {name}을 @PathVariable String name 에다 넣어준다

 

@RequestParam(GET 방식)

helloGetRequestParam method 만듦

// [Request sample]
// GET <http://localhost:8080/hello/request/form/param?name=Robbie&age=95>
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
    return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
}

// GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95

// GET http://localhost:8080/hello/request/form/param → 여기서 일단 path 끝남

?name=Robbie&age=95 → ?는 QueryString 방식으로 데이터를 시작할때 쓴다, 앞이 key 뒤가 value

@RequestParam(POST 방식)

// [Request sample]
    // POST <http://localhost:8080/hello/request/form/param>
    // Header
    //  Content type: application/x-www-form-urlencoded
    // Body
    //  name=Robbie&age=95
    @PostMapping("/form/param")
    @ResponseBody
    public String helloPostRequestParam(@RequestParam String name, @RequestParam int age) {
        return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
    }

Post 방식으로 넘어오는걸 RequestParam으로 봄!

Post는 Get과는 다르게 Body 부분을 가지고 있다

form tag 방식으로 request param 을 보낼 수 있다고 함

html의 form tag

<form method="POST" action="/hello/request/form/model">
    <div>
        이름: <input name="name" type="text">
    </div>
    <div>
        나이: <input name="age" type="text">
    </div>
    <button>전송</button>
</form>

요청이 Body 부분으로 넘어간다고 함

전송 버튼을 누르면

이런 형태로 넘어온다

 

Request Param은 생략 가능하다

// [Request sample]
    // GET <http://localhost:8080/hello/request/form/param?name=Robbie&age=95>
    @GetMapping("/form/param")
    @ResponseBody
    public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
        return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
    }

여기서 int age에 붙은 @RequestParam을 없애봄

// [Request sample]
    // GET <http://localhost:8080/hello/request/form/param?name=Robbie&age=95>
    @GetMapping("/form/param")
    @ResponseBody
    public String helloGetRequestParam(@RequestParam String name, int age) {
        return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
    }

정상적으로 동작함

데이터를 넣지 않고 보냈을때

어떻게 되는지도 봄

 

 

2023-11-06T23:56:43.083+09:00  WARN 19956 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'name' for method parameter type String is not present]

2023-11-06T23:56:43.083+09:00 WARN 19956 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'name' for method parameter type String is not present]

 

생략은 가능한데 어떤 경우에 올 수도 있고 안 올수도 있는데 안 오는 경우의 api를 따로 만들면 비효율적이라 required 옵션을 넣어놨다고 함 

required=true가 디폴트인데 false옵션을 걸면 클라이언트에서 전달받은 값들에서 해당 값이 포함되어있지 않아도 오류가 발생하지 않는다고 함

@GetMapping("/form/param")
    @ResponseBody
    public String helloGetRequestParam(@RequestParam(required = false) String name, int age) {
        return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
    }

@PathVariable이나 받아줄때는 다 이 옵션이 있다고 함

아무것도 넣지 않으면 null이 들어간다