티스토리 뷰

환경 설정을 통한 일괄 적용 

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    ... 
    
    @Autowired(required = false)
    private Converter<?, ?>[] converters;
    
    @Override
    public void addFormatters(FormatterRegistry registry) {
        if(converters != null) {
            for(final Converter<?, ?> converter : converters) {
                registry.addConverter(converter);
            }
        }
        NumberStyleFormatter numberFormatter = new NumberStyleFormatter();
        numberFormatter.setPattern("#,###,###,###.##");
        registry.addFormatter(numberFormatter);
        
    }

}

WebMvcConfiguration에서 addFormatters에 사용자 Converter를 설정하면 전체 요청에 대해 일괄 적용이 가능합니다. 

@Component
public class StringToDateConverter implements Converter<String, Date> {
    
    private final static String DATE_FORMAT = "yyyyy-MM-dd";
    
    @Override
    public Date convert(String source) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
        try {
            return format.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        } 
    }
}
@Component
public class StringToDateTimeConverter implements Converter<String, Timestamp> {
    
    private final static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
    @Override
    public Timestamp convert(String source) {
        SimpleDateFormat format = new SimpleDateFormat(DATETIME_FORMAT);
        try {
            Date parsedDate = format.parse(source);
            return new java.sql.Timestamp(parsedDate.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        } 
    }

}
@Component
public class StringTrimConverter implements Converter<String, String> {
    
    @Override
    public String convert(String source) {
        if(source == null) return source;
        return source.trim();
    }

}

위에 예제 소스를 보면 정말 간단하게 만들어졌다는 걸 알 수 있습니다. 

개발자가 요청을 받아서 처리하는 반복적인 작업들이 있다면 Converter로 만들어 두면 정말 편리합니다.   

Converter는 @Component로 만들어서 @Configuration에서 자동 injection이 되게 합니다. 

@Autowired(required = false)
private Converter<?, ?>[] converters;

이렇게 설정을 하면 number format, date 관련 설정 등을 완료 한 것입니다. 

 

예제 코드 

@Slf4j
@RestController
@RequestMapping("/controller/request/config")
public class RequestParam03APIController {

    /**
     * date 타입 받기 yyyy-MM-dd 
     * @return
     */
    @PostMapping("/date")
    public ResponseEntity<String> dateMapping(@RequestParam final Date param) {
        return ResponseEntity.ok(DateUtil.formatDate(param, "yyyy/MM/dd"));
    }

    /**
     * 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<RequestParams03> requestParamObject(final RequestParams03 params) {
        log(params.toString());
        return ResponseEntity.ok(params);
    }
    
    private void log(String message) {
        log.debug("parameters : " + message);
    }

    @Getter
    @Setter
    @ToString
    public static class RequestParams03 {
        private String id;
        private String name;
        private Boolean test;
        private Date created;
        private Double dbl;
        private Long lng;
        public RequestParams03() {
            super();
        }
        public RequestParams03(String id, String name, Date created) {
            super();
            this.id = id;
            this.name = name;
            this.created = created;
        }
        
    }
}

위에 코드를 보면 이전에 보이던 format, convert, @InitBinder 관련 설정이 모두 제거 된것을 확인 할 수 있습니다. 

그래도 정상 작동하는지 테스트해 봅니다. 

@SpringBootTest
@AutoConfigureMockMvc
class RequestParam03APIControllerTest {

    @Autowired 
    private MockMvc mockMvc;

    private RequestParams03 getRequestParams03() {
        return new RequestParams03("test", " 테스트 ", DateUtil.parseDate("2022-05-12"));
    }

    @Test
    void dateMapping() throws Exception {
        RequestParams03 param = getRequestParams03();
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/controller/request/config/date")
                .param("param", DateUtil.formatDate(param.getCreated()))
                .accept(MediaType.TEXT_PLAIN)
                )
                .andExpect(status().isOk())
                .andReturn();
        assertThat(result.getResponse().getContentAsString()).isEqualTo(DateUtil.formatDate(param.getCreated(), "yyyy/MM/dd"));
    }

    @Test
    void doubleMapping() throws Exception {
        String param = "12,000.12";
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/controller/request/config/double")
                .param("param", param)
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON))
//                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        assertThat(result.getResponse().getContentAsString()).isEqualTo("12000.12");
    }

    @Test
    void objectMapping() throws Exception {
        RequestParams03 params = getRequestParams03();
        mockMvc.perform(MockMvcRequestBuilders.post("/controller/request/config/params")
                .param("id", params.getId())
                .param("name", params.getName())
                .param("test", "yes")
                .param("created", DateUtil.formatDate(params.getCreated()))
                .param("dbl", "12,000.12")
                .param("lng", "12,000.12")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name").value(params.getName().trim()))
                .andExpect(jsonPath("$.id").value(params.getId()))
                .andExpect(jsonPath("$.dbl").value(12000.12))
                .andExpect(jsonPath("$.lng").value(12000))
                ;
    }

}

github : https://github.com/kkaok/study-springboot/tree/main/src/main/java/eblo/study/springboot/controller

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함