본문 바로가기
Backend 개발자/Springboot

Spring Request 처리 방법 ModelAttribute, RequestParam, RequestBody, ArgumentResolver

by by 앵과장 2022. 4. 6.
반응형

안녕하세요
앵과장입니다.


프로젝트를 신규로 개발하다보니 Server Api 오랜만에 직접 구현할일이 생기다보니 하면서 정리가 필요할것같아서 공유드립니다.

Spring에서는 클라이언트 요청을 바인딩할 때 @RequestParam, @RequestBody, @ModelAttribute @JsonCreator 등으로 사용 가능합니다.

각 어노테이션 기능마다 역활이 다르기때문에 필요한 상황에 맞게 사용하시면 됩니다

Request 처리하는 방법 알아보기

@ModelAttribute
@RequestParam
@RequestBody
@ModelAttribute

클라이언트가 전송하는 multipart/form-data 형태의 HTTP Body 내용과 HTTP 파라미터 데이터를 Setter를 통해 Java 객체에 매핑합니다.

  • 객체의 필드에 접근해서 데이터를 바인딩할 수 있는 생성자 혹은 setter 메서드가 필요합니다
  • Query String 및 Form 형식이 아닌 데이터는 처리가 불가합니다.
RequestParam

1개의 HTT 요청 파라미터를 받기 위해서 사용합니다.

@GetMapping("/api/users")
@ResponseBody
public String getFoos(@RequestParam Long id) {
    return "ID: " + id;
}



  • RequestParam은 요청에 매개변수가 필수적이다. → @RequestParam(required = true)가 기본 설정입니다.
  • 해당 파라미터가 전송되지 않으면 400 Error을 반환합니다.
  • @RequestParam(required = false)로 설정하면 파라미터가 없어도 된다. → 이 경우 매개변수가 null로 바인딩됩니다.
  • defaultValue를 통해 기본값을 설정가능합니다.
RequestBody

클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환합니다

  • 그렇기 때문에 Body가 존재하지 않는 Get 메소드에서 사용하면 에러가 발생합니다.
  • HTTP 요청 본문 데이터는 Spring에서 제공하는 Http Message Converter를 통해 타입에 맞게 객체 반환합니다.
  • RequestBody를 사용할 객체는 필드를 바인딩할 생성자나 setter 메서드가 필요하지 않습니다.
Spring Custom ArgumentResolver

Spring ArgumentResolver 기능
Servlet 과 Controller 사이 전달값을 가공하거나 추가할 필요가 있을때 사용
중복 코드를 제거하는 리펙토링  방법

Custom ArgumentResolver 구성하기

 

DTO객체 클래스
@Data
public class UserDto {
    private String userId;
    private String userLocale;
    private String ipAddress;
}

 

 

 

 

 

ArgumentResolver


Custom ArgumentResolver 클래스 구성 HandlerMethodArgumentResolver 인터페이스
implements 구현

2개의 메소드 기능 Override
supportsParameter
resolveArgument

supportsParameter 우선순위 호출
MethodParameter 타입이 UserDto 타입인경우에 resolveArgument 호출함

resolveArgument
UserDto 에대한 정보 가공
HttpServletRequest는 기본 파라미터로 NativeWebRequest를 통해 생성 가능

@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().equals(UserDto.class);
    }

    public Object resolveArgument(
        MethodParameter methodParameter,
        ModelAndViewContainer modelAndViewContainer,
        NativeWebRequest nativeWebRequest,
        WebDataBinderFactory webDataBinderFactory
    ) throws Exception{
        HttpServletRequest httpServletRequest = 
            nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            
         UserDto userDto = new UserDto();
            userDto.setUserId(httpServletRequest.getSession().getId());
            userDto.setUserLocale(httpServletRequest.getLocale().toString());
            userDto.setIpAddress(httpServletRequest.getLocalAddr());
            return userDto; 
    } 
}

 

WebConfig

커스텀 구현한 ArgumentResolver 사용하기 위해

WebMvcConfigurer 를 implements 하여 addArgumentResolvers 로 추가하면됩니다.

@Configuration
public class WebConfig implements WebMvcConfigurer{
    @Autowired
    private UserArgumentResolver userArgumentResolver;
    
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    	argumentResolvers.add(userArgumentResolver);
    }
}

 

Controller

Controller 에서 argument 로 UserDto 를 추가하여 Request 처리하면

위에서 언급한 별도에 Annotation을 처리하지 않아도 ArgumentResolver가 Controller 실행전 Object를 구성합니다.

@RestController
public class UserController {
    @GetMapping("/user")
    public void testRestTemplate(UserDto userDto) {
        Gson gson = new Gson();
        System.out.println(gson.toJson(userDto));
    }
}

Response 결과값

{"userId":"DD35175022826DE18808DC0FCE47E9FD","userLocale":"ko_KR","ipAddress":"127.0.0.1"}

 

 

현실적인 GetMapping API 개발 방법이 궁금하다면 클릭

 

개방과페쇄 Springboot API @GetMapping 3가지 방법 @ModelAttribute, @RequestParam, 정적 메소드 static method 현실

안녕하세요 앵과장입니다. 이전시간에 Springboot 에서 API 개발에 필요한 Annotation 들에 대해서 가볍게 알아보았습니다. 이번에는 API구현하면서 실제로 어떻게 하는게 좋을지 고민을 한번 해보도록

angryfullstack.tistory.com