Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 454 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to set base url for rest in spring boot?

#1
I'm trying to to mix mvc and rest in a single spring boot project.

I want to set base path for all rest controllers (eg. example.com/api)
in a single place (I don't want annotate each controller with `@RequestMapping('api/products')`, instead, just `@RequestMapping('/products')`.

Mvc controllers should be accessible by example.com/whatever

Is it possible?

(I don't use spring data rest, just spring mvc)
Reply

#2
You can create a custom annotation for your controllers:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}

Use it instead of the usual @RestController on your controller classes and annotate methods with @RequestMapping.

Just tested - works in Spring 4.2!
Reply

#3
A bit late but the same question brought me here before reaching the answer so I post it here.
Create (if you still don't have it) an application.properties and add

server.contextPath=/api

So in the previous example if you have a RestController with `@RequestMapping("/test")` you will access it like `localhost:8080/api/test/{your_rest_method}`

question source: [how do i choose the url for my spring boot webapp][1]


[1]:

[To see links please register here]

Reply

#4
I found a clean solution, which affects only rest controllers.

@SpringBootApplication
public class WebApp extends SpringBootServletInitializer {

@Autowired
private ApplicationContext context;

@Bean
public ServletRegistrationBean restApi() {
XmlWebApplicationContext applicationContext = new XmlWebApplicationContext();
applicationContext.setParent(context);
applicationContext.setConfigLocation("classpath:/META-INF/rest.xml");

DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setApplicationContext(applicationContext);

ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/rest/*");
servletRegistrationBean.setName("restApi");

return servletRegistrationBean;
}

static public void main(String[] args) throws Exception {
SpringApplication.run(WebApp.class,args);
}
}


Spring boot will register two dispatcher servlets - default `dispatcherServlet` for controllers, and `restApi` dispatcher for `@RestControllers` defined in `rest.xml`:

2016-06-07 09:06:16.205 INFO 17270 --- [ main] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'restApi' to [/rest/*]
2016-06-07 09:06:16.206 INFO 17270 --- [ main] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]

The example `rest.xml`:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="

[To see links please register here]

[To see links please register here]

[To see links please register here]

[To see links please register here]

[To see links please register here]

[To see links please register here]

;

<context:component-scan base-package="org.example.web.rest"/>
<mvc:annotation-driven/>

<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>

<!-- Configure bean to convert JSON to POJO and vice versa -->
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
</beans>

But, you're **not limited to**:

- use `XmlWebApplicationContext`, you may use any else context type available, ie. `AnnotationConfigWebApplicationContext`, `GenericWebApplicationContext`, `GroovyWebApplicationContext`, ...
- define `jsonMessageConverter`, `messageConverters` beans in rest context, they may be defined in parent context
Reply

#5
Since this is the first google hit for the problem and I assume more people will search for this. There is a new option since Spring Boot '1.4.0'.
It is now possible to define a custom *RequestMappingHandlerMapping* that allows to define a different path for classes annotated with *@RestController*

A different version with custom annotations that combines *@RestController* with *@RequestMapping* can be found at this [blog post][1]

@Configuration
public class WebConfig {

@Bean
public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
return new WebMvcRegistrationsAdapter() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new RequestMappingHandlerMapping() {
private final static String API_BASE_PATH = "api";

@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
Class<?> beanType = method.getDeclaringClass();
if (AnnotationUtils.findAnnotation(beanType, RestController.class) != null) {
PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_BASE_PATH)
.combine(mapping.getPatternsCondition());

mapping = new RequestMappingInfo(mapping.getName(), apiPattern,
mapping.getMethodsCondition(), mapping.getParamsCondition(),
mapping.getHeadersCondition(), mapping.getConsumesCondition(),
mapping.getProducesCondition(), mapping.getCustomCondition());
}

super.registerHandlerMethod(handler, method, mapping);
}
};
}
};
}
}

[1]:

[To see links please register here]

Reply

#6
You can create a base class with `@RequestMapping("rest")` annotations and extend all you other classes with this base class.

@RequestMapping("rest")
public abstract class BaseController {}

Now all classes that extend this base class will be accessible at `rest/**`.
Reply

#7
I couldn't believe how complicate the answer to this seemingly simple question is. Here are some references:

- [Spring JIRA Ticket][1]
- [Another SO question][2]
- [Yet another SO question][3]
- [Very nice GitRepository that showcases the problem][4]

There are many differnt things to consider:

1. By setting` server.context-path=/api` in `application.properties` you can configure a prefix for *everything*.(Its server.context-path not server.contextPath !)
2. Spring Data controllers annotated with @RepositoryRestController that expose a repository as rest endpoint will use the environment variable `spring.data.rest.base-path` in `application.properties`. But plain `@RestController` won't take this into account. According to the [spring data rest documentation][5] there is an annotation `@BasePathAwareController` that you can use for that. But I do have problems in connection with Spring-security when I try to secure such a controller. It is not found anymore.

Another workaround is a simple trick. You cannot prefix a static String in an annotation, but you can use expressions like this:

@RestController
public class PingController {

/**
* Simple is alive test
* @return <pre>{"Hello":"World"}</pre>
*/
@RequestMapping("${spring.data.rest.base-path}/_ping")
public String isAlive() {
return "{\"Hello\":\"World\"}";
}
}

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

[5]:

[To see links please register here]

Reply

#8
For Boot 2.0.0+ this works for me: server.servlet.context-path = /api
Reply

#9
This solution applies if:

1. You want to prefix `RestController` but not `Controller`.
2. You are not using Spring Data Rest.

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new ApiAwareRequestMappingHandlerMapping();
}

private static class ApiAwareRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

private static final String API_PATH_PREFIX = "api";

@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
Class<?> beanType = method.getDeclaringClass();
if (AnnotationUtils.findAnnotation(beanType, RestController.class) != null) {
PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_PATH_PREFIX)
.combine(mapping.getPatternsCondition());

mapping = new RequestMappingInfo(mapping.getName(), apiPattern, mapping.getMethodsCondition(),
mapping.getParamsCondition(), mapping.getHeadersCondition(), mapping.getConsumesCondition(),
mapping.getProducesCondition(), mapping.getCustomCondition());
}
super.registerHandlerMethod(handler, method, mapping);
}
}

}

This is similar to the [solution][1] posted by mh-dev, but I think this is a little cleaner and this should be supported on any version of Spring Boot 1.4.0+, including 2.0.0+.




[1]:

[To see links please register here]

Reply

#10
For spring boot framework version `2.0.4.RELEASE+`. Add this line to `application.properties`

server.servlet.context-path=/api
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through