"연동"과 관련된 이슈중 하나는 요청 방법에 따른 데이터 매핑과 관련된 이슈 입니다.
스프링 프레임워크에서 사용 할 수 있는 에노테이션인 @RequestBody, @RequestParam 및 @ModelAttribute등을 사용하면 사용자의 요청 데이터를 쉽게 매핑할 수 있습니다.
대신 이러한 에노테이션을 사용하려면 방법을 정해야 합니다.
헤더에서의 content-type에 따라 json방식, application/x-www-form-urlencoded 방식 및 text/plain방식 등 다양한 방법이 존재하며,
마찬가지로 get과 post에 따라서 요청하는 body가 있을수도 있고 없을 수도 있습니다.
간단한 예로 @RequestBody 에노테이션은 json 형식의 데이터 값만 매핑 할 수 있으며, @RequestParam 은 json형식의 데이터를 매핑 할 수 없습니다.
* 참고 : lts0606.tistory.com/436
일반적인 application과 같은 요청 방식에서는 아래처럼 쉽게 요청한 key, value를 가져올 수 있습니다.
private static Map<Object, Object> getBodyItor(HttpServletRequest webRequest){
Map<Object, Object> _param = new HashMap<>();
webRequest.getParameterMap().forEach((key, value)->{ //forEach를 통해서 key와 value를 받습니다.
if(value != null && value.length > 1) {
_param.put(key, value);
} else {
_param.put(key, value[0]);
}
});
return _param;
}
그런데 만약 요청하는 방식이 json이라면 조금 달라집니다.
json방식으로 요청한 경우에는 getParameterMap() 메소드를 호출 하여 보았자 데이터가 존재하지 않습니다.
이럴 때는 request객체에서 getInputStream() 메소드를 호출하여 데이터를 전부 읽은 다음에 json을 파싱하여주면 쉽게 가능 합니다.
private static Map<Object, Object> getBody(HttpServletRequest request) {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream(); //스트림에서 데이터를 전부 읽습니다.
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { ex.printStackTrace(); } }
}
body = stringBuilder.toString();
try {
org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
org.json.simple.JSONObject jsonObj = (org.json.simple.JSONObject) parser.parse(body);
return jsonObj;
} catch (Exception e) {
e.printStackTrace();
}
return new HashMap<>();
}
이렇게 2개의 메소드를 준비하고 나면 컨트롤러에서 할 일은 해당 데이터가 json방식인지 아닌지를 판별 하는 것 입니다.
요청한 헤더에서의 컨텐트(content-type) 타입을 확인하여 위 2개의 메소드를 적절하게 동작하도록 하여 줍니다.
@RequestMapping(value="/요청")
@ResponseBody
public Map<Object, Object> test(HttpServletRequest request){ //HttpServletRequest객체로 받습니다.
Map<Object, Object> param = null;
if(request.getHeader("content-type") == null || request.getHeader("content-type").indexOf("json") == -1 ){ //json이 아닌 요청
param = getBodyItor(request);
} else if(request.getHeader("content-type").indexOf("json") > -1){ //json 요청
param = getBody(request);
}
return param;
}
에노테이션 @RequestBody, @RequestParam 등이 없이도 위 방식을 통해서 작업을 하면 사용자가 어떠한 요청을(Multipart제외) 하던지 간에 데이터를 Map형태로 받아서 표현 할 수 있습니다.
패키지(package) 대부분이 Spring과 java에서 제공하는 기본 패키지라 따로 명시하지는 않았습니다.
만약 해당 기능을 특정 에노테이션으로 만들고 HandlerMethodArgumentResolver같은 에노테이션 감지용 클래스에 붙여준다면 조금 더 깔끔해지지 않을 까 합니다.
응답 형태에 따른 매핑방법에 대해서 살펴보았습니다!
궁금한 점이나 틀린점은 언제든지 연락주세요. ^^
'Spring framework' 카테고리의 다른 글
Spring 자주 사용되는 비지니스 로직, 컨트롤러 파일 업로드(Spring file upload, contoller) (1) | 2021.06.03 |
---|---|
Spring RSS Feed 기능 만들기(전자정부 RSS Feed) (0) | 2021.05.31 |
Spring RequestBody RequestParam(스프링 RequestParam RequestBody) (0) | 2020.11.17 |
Spring 컴포넌트 스캔(Spring component scan, RootContext와 ServletContext)에 대한 간단 정리 (0) | 2020.07.28 |
스프링, 전자정부 프레임워크에서 중복 로그인 확인하기(HttpSessionListener 사용) (0) | 2020.04.29 |
댓글