文档说明如果我不在servlet调用线程中,但仍想使用UriComponentsBuilder
(例如在批量导入中),我可以使用ServletUriComponentsBuilder.fromCurrentContextPath()
。
@see https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-uri-building
我从文档中尝试了以下内容:
public String createUrl() {
UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
return uri.toString();
}
用于测试非servlet调用:
@PostConstruct
public void init() {
builder.createUrl();
}
但总是得到例外:
Caused by: java.lang.IllegalStateException: Could not find current request via RequestContextHolder
at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.web.servlet.support.ServletUriComponentsBuilder.getCurrentRequest(ServletUriComponentsBuilder.java:190) ~[spring-webmvc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.web.servlet.support.ServletUriComponentsBuilder.fromCurrentContextPath(ServletUriComponentsBuilder.java:158) ~[spring-webmvc-4.3.4.RELEASE.jar:4.3.4.RELEASE]
那么这里可能出现什么问题?
答案 0 :(得分:1)
您提到的文档明确指出静态方法适用于Servlet环境:
在 Servlet环境中的ServletUriComponentsBuilder子类 提供静态工厂方法[...]
因此,如果您不在所述Servlet环境中,则需要使用普通的UriComponentsBuilder:
UriComponentsBuilder.newInstance().scheme("http").host("example.com")
哪个适合您的代码
public String createUrl() {
UriComponentsBuilder base = UriComponentsBuilder.newInstance().scheme("http").host("example.com").path("/en");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
return uri.toString();
}
这背后的原因是在servlet环境中,您可以通过查询Servlet / ServletContext等来访问scheme和主机以及上下文路径。在webapp外部运行,此信息(方案,主机,上下文路径)需要来自其他地方。