2021-05-21-TIL

Sorbet·2021년 5월 21일
0

Spring Controller에서 데이터를 받아오는 방법

httpServletRequest.getParameter()

// httpServletRequest.getParameter()
@RequestMapping("/test") 
public String test(HttpServletRequest req) {

	String userId = req.getParameter("userId");
	return "test"; 
}
  • getParameter()는 String 값을 반환합니다.


httpServletRequest.getAttribute()

// httpServletRequest.getAttribute()
@RequestMapping("/test") 
public String test(HttpServletRequest req) {

	String userId = req.getParameter("userId");
	return "test"; 
}
  • getAttribute()는 getParameter()와 비슷하지만 String 값이 아닌 Object 값을 반환한다는 차이가 있습니다.


@RequestParam

@RequestParam
@RequestMapping("/test", method=RequestMethod.GET)
public String test(@RequestParam(value="userId", defaultValue="ooeunz") String userId) {

	return "test"; 
}
  • query string 방식으로 url을 통해 parameter로 값을 받아옵니다. 갖고있는 속성으로는 value, required, defaultValue가 있습니다.
  • value는 위의 코드에서 알 수 있듯이 query string으로 받아오는 key값을 의미하고 뒤에 오는 변수에 해당 값을 바인딩합니다.
    required값은 true일 경우 parameter가 반드시 url에 담겨있어야 합니다. 없을경우 400값을 반환하게 됩니다.
    defaultValue는 디폴트 값을 의미합니다.
  • Query String 방식과 path value 방식이 무엇인지 모른다면 검색해서 공부하세요


@Pathvariable

@PathVariable
@RequestMapping("/test/{email}", method=RequestMethod.GET)
public String test(@PathVariable("email") String email) {

	return "test"; 
}
  • Pathvariable 애노테이션은 RequestMapping에 {email} 이라는 부분에 맵핑됩니다. query string 방식과 path value 방식을 이해하고 있다면 별로 어렵지 않게 사용하실 수 있을거라 생각합니다.


@RequestBody

@RequestMapping("/test")
public String test(@RequestBody Map<String, Obejct> obj) {
	Account account = obj.get("account"); 
	return "test"; 
}
  • GET방식은 request packet에 http body가 존재하지 않습니다. 따라서 @RequestBody로받으려면 반드시 POST 방식을 사용해야 합니다. @RequestBody는 JSON이나 XML과 같은 데이터를 받거나 DTO/VO 객체 전체를 받을 경우 사용합니다.


@ModelAttribute

@RequestMapping("/test")
public String test(@ModelAttribute UserDto user) {
	
    System.out.println(user.getUserId());
	return "test"; 
}
  • @RequestParam과 비슷한데 1:1로 parameter를 받을 경우엔 @RequestParam을 사용하고 DTO/VO와 같이 객체 전체로 받을 경우 @ModelAttribute로 받을 수 있습니다.
  • 예를들어 form에서 데이터를 받을 경우 form name과 DTO/VO의 변수 명을 같게 해줌으로써 자동으로 데이터를 바인딩할 수 있습니다.


    출처 : https://ooeunz.tistory.com/99













@RequestParam 자세히 알아보기 & 주의할점

0) 인트로

@GetMapping("/user")
@ResponseBody
public String getUserName(@RequestParam String name) {
  return name;
}
  • @RequestParam을 통해 name 변수에 "hellozin"이라는 문자열을 받아 처리할 수 있습니다.
  • 하지만 저대로 사용하게 되면 요청 쿼리 스트링에 "name" 필드가 없을 경우
    • 즉, /user 와 같이 @RequestParam이 적용된 필드가 없으면 Bad Request예외가 발생합니다
      예외 : Required String parameter 'name' is not present
  • 이를 해결하기 위해 @RequestParam(required = false) 와 같이 required 속성을 추가하면 해당 필드가 쿼리스트링에 존재하지 않아도 예외가 발생하지 않습니다.

1) 단일 파라미터 변환

private ModelAndView request_TEST(@RequestParam("test") int num,

@RequestParam("test2") String str)){
//위처럼 하나이상의 타입을 적용할수 있습니다. 스프링에서 지원하는 변환기에서 지원되는 모든타입을 변환가능합니다.
//RequestParam은 하나이상 파라미터에서 사용가능합니다.
}

참편리하죠? 하지만 단점이 있습니다.
위처럼 사용하게 된다면 만약에 넘어오는 requestParam중에
@RequestParam 지정한 키값이 존재하지 않다면
BadRequest로 http 4** 에러가 발생합니다.

2) 이를 방지하기 위하여 필수적이지 않도록

그리고 존재하지 않다면 DefaultValue를 지정할수 있습니다.

private ModelAndView request_TEST(@RequestParam(value="test", required=false, defaultValue= "0") int num,
@RequestParam("test2") String str)){
//required=false로 지정하면 해당 키값이 존재하지 않다고 해서 BadRequest가 발생하지 않게 됩니다.
//그리고 존재하지 않다면 num변수에 default로 0이 들어가게됩니다.
}

파라미터가 많아지게 되면 일일이 파라미터를 지정하는게 귀찮아 집니다.
이를 Map으로 간단하게 받아올수 있습니다.

3) RequestParam을 map에 지정하여 사용하기.

private ModelAndView request_TEST(@RequestParam HashMap<string,string> paramMap)){
String data = paramMap.get("testParam");
}
위의 예시처럼 map을 통해서도 파라미터를 컨트롤 할수 있습니다.
대규모의 파라미터를 받는데 map을 사용하기엔 편합니다.

4) 주의할 점

  • Argument Resolver에 등록한 CustomArgument에 @RequestParam(required = false)을 적용하면 Spring이 해당 Argument를 무시합니다.
  • CustomArgument는 다음과 같이 정의됩니다.
    • CustomArgument 클래스 작성
    • HandlerMethodArgumentResolver 인터페이스 구현체 작성
    • WebMvcConfigure.addArgumentResolvers에서 구현한 Resolver 등록
  • 여기까지 하면 해당 Argument를 처리할 때 HandlerMethodArgumentResolver에 정의한 resolveArgument() 메소드에 위임해주게 됩니다.
  • 하지만 다음과 같이 CustomArgument에 @RequestParam(required=false) 를 적용하면
@GetMapping("/user")
@ResponseBody
public String getUserName(@RequestParam(required = false) CustomUser user) {
  return user.getName();
}
  • HandlerMethodArgumentResolver가 처리 하는 과정에서 아까 등록한 resolver가 불리지 않고 처리가 종료됩니다. 이 동안 어떠한 에러나 경고도 주어지지 않아 실수를 파악하는데 오랜 시간이 걸렸습니다.
  • 결국 Map<K,V> 형태나 CustomArgument의 경우 required=false 속성 없이도 예외가 발생하지 않기 때문에 직접 null 체크나 원하는 처리를 할 수 있습니다.

    출처
    https://velog.io/@hellozin/RequestParamrequired-false-주의할-점
    https://heavenly-appear.tistory.com/302

벨로퍼트 님 인터뷰

  • 리디 다니시는 벨로퍼트님 영상을 봤는데, 진짜 이런사람도 있구나! 겸손하고, 말도 잘하고, 인상도 좋다.
  • 더 잘하고싶고 빨리하고싶고 실수없이 완벽하게 서비스를 만들어낼 수 있는 사람이 되고 싶은데 아직은 그러지 못하고 있다.
  • 더 열심히, 의식적인 노력과 충분한 연습으로 리액트의 벨로퍼트님 만큼 벡엔드 개발자로써 인정받고 싶다
  • 링크 : https://youtu.be/hzzp3HN9OOs

결론 : 인터뷰를 보면서 설레는걸 보니 꿈이자 목표는 벨로그같은 서비스를 만드는건가보다

profile
Sorbet is good...!

0개의 댓글