티스토리 뷰
Date, DateTime, Boolean, enum, Number 타입 등 요청 값을 적절하게 포맷팅하고 컨버팅할 필요가 있습니다.
이런 처리는 크게 세가지 방법으로 처리 가능합니다.
1. 요청레벨 : 요청시 파라미터에서 설정으로 통해 처리하는 방법.
2. 클래스레벨 : @InitBinder를 통해 해당 컨트롤러 전체에 동일 적용하는 방법.
3. 프로젝트레벨 : WebMvcConfigurationSupport 설정을 통해 프로젝트 전체에 적용하는 방법
요청레벨에 따른 처리 방법은 이전 글에 정리를 했고 이번에는 @InitBinder 부분입니다.
실무에서는 주로 환경 설정을 통해 전체 적용하는 방법을 많이 쓰기 때문에 간단한 예제만 만들어 봤습니다.
예제
@Slf4j
@RestController
@RequestMapping("/controller/request/initbinder")
public class RequestParam02APIController {
/**
* class level convert : class 전체 적용
* @param webDataBinder
* @param request
*/
@InitBinder
private void initBinder(WebDataBinder webDataBinder, WebRequest request) {
// datetime format 설정
DateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
datetimeFormat.setLenient(false);
webDataBinder.registerCustomEditor(Timestamp.class, new CustomDateEditor(datetimeFormat, true));
// date format 설정
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
// trim 설정
webDataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
// number 관련 설정
NumberStyleFormatter numberFormatter = new NumberStyleFormatter();
numberFormatter.setPattern("#,###,###,###.##");
webDataBinder.addCustomFormatter(numberFormatter);
}
/**
* date 타입 받기 yyyy-MM-dd
* @return
*/
@PostMapping("/date")
public ResponseEntity<String> dateMapping(@RequestParam final Date param) {
String strDate = DateUtil.formatDate(param, "yyyy/MM/dd");
log(strDate);
return ResponseEntity.ok(strDate);
}
/**
* 12,000.12 형태로 전달 받으면 12000.12로 변환
* @param pDouble
* @return
*/
@PostMapping("/double")
public ResponseEntity<Double> doubleMapping(@RequestParam final Double param) {
log(param.toString());
return ResponseEntity.ok(param);
}
/**
* 12,000.12 형태로 전달 받으면 12000로 변환
* @param pLong
* @return
*/
@PostMapping("/long")
public ResponseEntity<Long> longMapping(@RequestParam final Long param) {
log(param.toString());
return ResponseEntity.ok(param);
}
/**
* trim 처리
* @param pString
* @return
*/
@PostMapping("/trim")
public ResponseEntity<String> trimMapping(@RequestParam final String param) {
log(param);
return ResponseEntity.ok(param);
}
@PostMapping("/params")
public ResponseEntity<RequestParams02> requestParamObject(final RequestParams02 params) {
log(params.toString());
return ResponseEntity.ok(params);
}
/**
* request parameters를 객체에서 받고 date 타입은 formate 지정을 한다.
* request level에서 convert 처리
* @return
*/
@PostMapping("/body")
public ResponseEntity<RequestParams02> requestParamBody(@RequestBody final RequestParams02 params) {
return requestParamObject(params);
}
private void log(String message) {
log.debug("parameters : "+message);
}
@Getter
@Setter
@ToString
@Builder
public static class RequestParams02 {
private String id;
private String name;
private Boolean test;
private Date created;
}
}
이전 코드와 비교해 봤을 때 코그다 좀 더 간략하게 변한걸 확인 할 수 있습니다.
테스트
@WebMvcTest(controllers = RequestParam02APIController.class)
class RequestParam02APIControllerTest {
@Autowired
private MockMvc mockMvc;
private RequestParams02 getRequestParams02() {
return new RequestParams02("test", "테스트", true, DateUtil.parseDate("2022-05-12"));
}
@ParameterizedTest
@CsvSource(value = {
"/controller/request/initbinder/date#2022-05-12#2022/05/12"
,"/controller/request/initbinder/double#12,000.12#12000.12"
,"/controller/request/initbinder/long#12,000.12#12000"
,"/controller/request/initbinder/trim# 12,000.12 #12,000.12"
}, delimiterString="#")
void dateMapping(String uri, String param, String expected) throws Exception {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post(uri)
.param("param", param)
.contentType(MediaType.APPLICATION_JSON))
// .andDo(print())
.andExpect(status().isOk())
.andReturn();
assertThat(result.getResponse().getContentAsString()).isEqualTo(expected);
}
/**
* 객체 매핑 테스트
* @throws Exception
*/
@Test
void objectMapping() throws Exception {
RequestParams02 params = getRequestParams02();
mockMvc.perform(MockMvcRequestBuilders.post("/controller/request/initbinder/params")
.param("id", params.getId())
.param("name", params.getName())
.param("created", DateUtil.formatDate(params.getCreated()))
.param("test", (params.getTest())? "yes":"no")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value(params.getName().trim()))
.andExpect(jsonPath("$.id").value(params.getId()));
}
/**
* @RequestBody 테스트
* @throws Exception
*/
@Test
void bodyMapping() throws Exception {
RequestParams02 params = getRequestParams02();
ObjectMapper objectMapper = new ObjectMapper();
String body = objectMapper.writeValueAsString(params);
mockMvc.perform(MockMvcRequestBuilders.post("/controller/request/initbinder/body")
.contentType(MediaType.APPLICATION_JSON)
.content(body))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value(params.getName()))
.andExpect(jsonPath("$.id").value(params.getId()));
}
}
코드를 작성해 보고 실행해 보면 @InitBinder가 어떤 역할을 하고 어떻게 작동하는지 확인이 될 겁니다.
'study > springboot' 카테고리의 다른 글
013. Content-type, Accept를 통한 요청 및 결과 처리 (0) | 2022.05.16 |
---|---|
012. Request Parameter에 converter 및 formatter 전체 적용 (0) | 2022.05.14 |
010. Request parameter 처리 (0) | 2022.05.14 |
009. controller pathvariable 처리 (0) | 2022.05.12 |
008. Controller request mapping (0) | 2022.05.11 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Spring Boot
- 스프링
- thymeleaf
- 메시지
- ag grid
- mybatis
- restful서비스
- 샘플
- 스프링부트
- SHEETJS
- oracle
- UI
- 엑셀
- mapToList
- 타임리프
- springboot
- java
- Javascript
- RESTful
- sample
- example
- 예제
- listToMap
- AG-GRID
- 설정
- REST
- spring
- cache
- lombok
- 그리드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함