@RequestMapping value에 property values 주입하기

프로그래밍|2014. 12. 5. 12:03

@RequestMapping의 value에 선언하는 스트링 값을 프로퍼티에서 관리할 수 있는 방법에 대해서 알아보았다.


아래와 같이 Controller에 선언되어 있는 @RequestMapping 이 존재한다.

@RequestMapping(value = "/loginPage", method = RequestMethod.GET)

public String loginPage() {

return "login/loginPage";

}


위의 맵핑 애노테이션 정보를 다음과 같이 수정한 후 테스트를 진행해 보았다.

물론, properties 파일에는 cont.req.name=loginPage 라고 선언이 되어 있는 상태이다.

@RequestMapping(value = "/${cont.req.name}", method = RequestMethod.GET)

public String loginPage() {

return "login/loginPage";

}


서버를 띄우고 로그를 확인해 보니 ${cont.req.name} 값을 loginPage로 치환하지 못하는 현상이 발생한다.

[2014-12-05 11:06:44 INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping][179] - Mapped "{[/${cont.req.name}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.kyu.svc.component.user.controller.LoginController.loginPage()


치환이 가능하게 하기 위해서는 PropertyPlaceholderConfigurer 에 프로퍼티 설정 파일을 연결 시켜줘야 하는데 간단하게 context:property-placeholder 태그를 이용하여 등록을 해주었다.

<util:properties id="appConfig" location="classpath:conf/dev-config.properties" />

<context:property-placeholder properties-ref="appConfig" />


context:property-placeholder 태그에 프로퍼티를 연결시켜 주니 정상적으로 ${cont.req.name} 값이 치환되는 것을 확인할 수 있었다.

[2014-12-05 11:13:44 INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping][179] - Mapped "{[/loginPage],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.kyu.svc.component.user.controller.LoginController.loginPage()


헌데 이상한 현상이 발생했다.

팀 동료는 위와 같이 설정을 추가하고 따라해봤지만 정상적으로 값이 치환되지 않는 다는 것이었다.

차이점은 내가 테스트한 환경은 스프링 3.2 버전이었고, 팀 동료가 테스트한 환경은 스프링 3.1 이었다.


설정 파일의 문제가 있는 것인가 싶어 등록된 설정을 변경해 가며 원인 분석을 해보았지만 문제의 원인을 파악하지 못하였고, 혹시나 싶어 스프링 소스를 열어보기로 했다.


3.2 버전의 소스를 기준으로 ${cont.req.name} 값을 치환하는 로직이 어디있는지 찾아보았다.

RequestMappingHandlerMapping 클래스의 createRequestMappingInfo 메소드에서 값을 치환하는 로직을 찾게 되었는데 다음은 일부 코드다. annotation.value() 값이 ${cont.req.name} 로 들어가 있는 것을 확인하였고 resolveEmbeddedValuesInPatterns 메소드를 통과하면 loginPage로 값이 치환된다.

private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {

String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());

return new RequestMappingInfo(

new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),

this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions),

new RequestMethodsRequestCondition(annotation.method()),

new ParamsRequestCondition(annotation.params()),

new HeadersRequestCondition(annotation.headers()),

new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),

new ProducesRequestCondition(annotation.produces(), annotation.headers(), getContentNegotiationManager()),

customCondition);

}


일단 치환되는 부분을 찾았으니 팀 동료가 테스트 했다던 스프링 3.1의 RequestMappingHandlerMapping 클래스를 열어보았다.

설마 했지만 createRequestMappingInfo 메소드의 구현 부분이 달랐다. ${cont.req.name} 값을 치환시키는 resolveEmbeddedValuesInPatterns 메소드 구현 부분이 없는 것이다.

private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {

return new RequestMappingInfo(

new PatternsRequestCondition(annotation.value(),

getUrlPathHelper(), getPathMatcher(), this.useSuffixPatternMatch, this.useTrailingSlashMatch),

new RequestMethodsRequestCondition(annotation.method()),

new ParamsRequestCondition(annotation.params()),

new HeadersRequestCondition(annotation.headers()),

new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),

new ProducesRequestCondition(annotation.produces(), annotation.headers()),

customCondition);

}


3.1.x 모든 버전의 소스를 열어보니 위의 코드와 동일했다.



결국 RequestMapping value에 property values를 주입하기 위해서는 스프링 3.2 부터 사용을 해야 한다는 결론이다.

댓글()