0

I want to write something like (simplified)

@MyAnnnotationForPrefix("/foo1")
@RestController
@RequestMapping("/bar")
public class Test1Controller{
    ...
}

@MyAnnnotationForPrefix("/foo2")
@RestController
@RequestMapping("/bar")
public class Test2Controller{
    ...
}

And access them via url /foo1/bar and /foo2/bar urls. Where should I place logic for handling @MyAnnnotationForPrefix?

Ivan Sopov
  • 2,300
  • 4
  • 21
  • 39
  • check this out https://stackoverflow.com/questions/5758504/is-it-possible-to-dynamically-set-requestmappings-in-spring-mvc – pvpkiran Jun 19 '18 at 11:17
  • Thanks - I'll dig into that way - however accepted answer is too broad (several classes are mentioned with no exact solution) and too narrow (for spring-webmvc and not spring-webflux) at the same time. So I want to leave this question active... – Ivan Sopov Jun 19 '18 at 11:20

1 Answers1

0

It seems to be done like this (please correct me if this solution has any drawbacks and I'll happily accept you answer)

import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

public class MyPrefixedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);
        if (mappingInfo == null) {
            return null;
        }
        MyAnnnotationForPrefix myAnnotation = handlerType.getAnnotation(MyAnnnotationForPrefix.class);
        if (myAnnotation == null) {
            return mappingInfo;
        }

        PatternsRequestCondition patternsRequestCondition =
            new PatternsRequestCondition(myAnnotation.getValue())
                .combine(mappingInfo.getPatternsCondition());

        return new RequestMappingInfo(mappingInfo.getName(),
            patternsRequestCondition,
            mappingInfo.getMethodsCondition(),
            mappingInfo.getParamsCondition(),
            mappingInfo.getHeadersCondition(),
            mappingInfo.getConsumesCondition(),
            mappingInfo.getProducesCondition(),
            mappingInfo.getCustomCondition()
        );
}

}

Also you need add this RequestMappingHandlerMapping to you webmvc config. In spring-boot this is done, defining bean:

@Component
public class MyPrefixedWebMvcRegistrations extends WebMvcRegistrationsAdapter {

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new MyPrefixedRequestMappingHandlerMapping();
    }
}
Ivan Sopov
  • 2,300
  • 4
  • 21
  • 39