最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - SpringBoot RestController @GetMapping route configurable - Stack Overflow

programmeradmin2浏览0评论
  • What I would like to achieve:

I want to be able to configure the @GetMapping route with some properties.

  • What I have tried:

We have a service whose business logic is the same. But we deploy it in different companies, and each of the companies has its rest API routes.

For example, the company A would like our service exposed to /api/v1.1/bar

Company B would like our service exposed to: /api/foo

etc

Therefore, we went to try this piece of code:

@RestController
public class DummyController {

    @Value("${configuration.route}")
    private String route;

    @GetMapping(value = route)
    String doSomeBusinessLogic() {
        doSomeVeryCoolBusinessLogic();

Expected:

With the code above, we were expecting that it would work, making the route configurable

Actual: we are getting this compilation error: Attribute value must be constant

The current workaround, we are creating an N version of the same apps, just to change one line, the get mapping line

App for company A

@GetMapping(value = "/api/v1.1/bar")
String doSomeBusinessLogic() {
    doSomeVeryCoolBusinessLogic();

app for company B

@GetMapping(value = "/api/foo")
String doSomeBusinessLogic() {
    doSomeVeryCoolBusinessLogic();

We believe this is not the way to go, therefore:

Question:

how to make the route configurable with SpringBoot ?

  • What I would like to achieve:

I want to be able to configure the @GetMapping route with some properties.

  • What I have tried:

We have a service whose business logic is the same. But we deploy it in different companies, and each of the companies has its rest API routes.

For example, the company A would like our service exposed to /api/v1.1/bar

Company B would like our service exposed to: /api/foo

etc

Therefore, we went to try this piece of code:

@RestController
public class DummyController {

    @Value("${configuration.route}")
    private String route;

    @GetMapping(value = route)
    String doSomeBusinessLogic() {
        doSomeVeryCoolBusinessLogic();

Expected:

With the code above, we were expecting that it would work, making the route configurable

Actual: we are getting this compilation error: Attribute value must be constant

The current workaround, we are creating an N version of the same apps, just to change one line, the get mapping line

App for company A

@GetMapping(value = "/api/v1.1/bar")
String doSomeBusinessLogic() {
    doSomeVeryCoolBusinessLogic();

app for company B

@GetMapping(value = "/api/foo")
String doSomeBusinessLogic() {
    doSomeVeryCoolBusinessLogic();

We believe this is not the way to go, therefore:

Question:

how to make the route configurable with SpringBoot ?

Share Improve this question asked Mar 18 at 7:49 PatPandaPatPanda 5,13029 gold badges119 silver badges256 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I am not saying this is necessarily a good idea :) but here are some options

1. Use Router Function

You should of course consider using RouterFunctions instead. But if for whatever reason you don't want to use option #2

2. Update the route with BeanPostProcessor

The problem is that the annotations (like @GetMapping) have to have constant values, therefore hard to change at runtime. We can use a BeanPostProcessor to do that:

@Component
public class DemoBeanPostProcessor implements BeanPostProcessor {

    @Value("${configuration.route}")
    private String newUrl;

    @SneakyThrows
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if (bean instanceof DummyController myController) {
            GetMapping annotation = myController.getClass().getAnnotation(GetMapping.class);
            InvocationHandler handler = Proxy.getInvocationHandler(annotation);
            Field field = handler.getClass().getDeclaredField("memberValues");
            field.setAccessible(true);
            Map<String, Object> memberValues = (Map) field.get(handler);
            memberValues.put("value", newUrl);
            return bean;
        }

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
}

since we are changing private members, for this to work you would need to allow reflection with:

--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED
发布评论

评论列表(0)

  1. 暂无评论