我目前正在开展一个教育项目。这意味着两个Spring Boot REST服务器。一个是实际的服务器,它进行一些处理。
我感兴趣的是另一个。它是一个将所有呼叫重定向到第一个呼叫的代理。因此,当我拨打http://localhost:8080/foo时,我的代理服务器将依次调用http://localhost:8090/foo。如果第一台服务器返回A
,代理将返回{"proxied": A, "someInformationAboutThisCall": B}
。
我设法用一些可能不优雅但功能正常的代码来实现这一点,我将在下面摘录。这里的关键是我使用@RequestMapping("**")
来实现这一目标。下一步是设计一个界面,使我的附加信息立即清晰,这基本上是这个项目的重点。如果我删除所有@RequestMapping("**")
,它就可以正常使用。
现在我的问题如下:使用@RequestMapping("**")
,我无法提供静态内容(调用会重定向到另一个REST服务器,它不提供静态内容)。 如何配置Spring Boot / Spring MVC以在映射请求时忽略可用作静态内容的资源,或者使PathResourceResolver
优先于我的控制器?或者我应该提供静态内容来自又一个JVM /服务器?
提前感谢您的帮助!
感兴趣的编辑:在进行一些测试时,我发现静态内容是,如果我使用
@RequestMapping("*")
,则会有一些限制。
/index.html
生成错误页面(更常见的是直接在public
中的任何静态内容)/itf/index.html
可以使用(更常见的是public/itf
中的任何文件或public
的任何其他子目录)/itf
不工作:Spring Boot似乎不知道其中的索引文件。我必须指定一个完整的URI,直到我想要显示的特定文件。然而,对于我需要的
@RequestMapping("**")
,这根本不起作用。
我尝试使用WebMvcConfigurerAdapter
HandlerInterceptorAdapter
(在SO,SO again和互联网上的许多其他位置找到),但无法启动我的项目,因为然后Spring启动找不到InterceptorRegistry
bean(Spring Boot最近有变化吗?我使用版本1.5.3.RELEASE)。
我也尝试了一些反匹配,但不仅不起作用,而且感觉非常非常脏(整个项目可能不是最佳的,所以说了很多)。
注意:您可以建议更好的方法在评论中实现 。请记住,虽然我总是愿意接受改进建议,但这不是我的问题。
@RestController
public class ProxyController {
@Value("${monitored.url.base}") // "http://localhost:8090"
private String redirectBase;
@RequestMapping(value = "**", method = {RequestMethod.POST, RequestMethod.PUT})
public ProxiedResponse proxifyRequestsWithBody(HttpServletRequest request, @RequestHeader HttpHeaders headers, @RequestBody Object body) throws URISyntaxException {
return proxifyRequest(request, headers, body);
}
@RequestMapping(value = "**")
public ProxiedResponse proxifyRequestsWithoutBody(HttpServletRequest request, @RequestHeader HttpHeaders headers) throws URISyntaxException {
return proxifyRequest(request, headers, null);
}
private ProxiedResponse proxifyRequest(HttpServletRequest request, @RequestHeader HttpHeaders headers, @RequestBody Object body) throws URISyntaxException {
final RequestEntity<Object> requestEntity = convertToRequestEntity(request, headers, body);
// call remote service
final ResponseEntity<Object> proxied = restTemplate.exchange(requestEntity, Object.class);
// Return service result + monitoring information
final ProxiedResponse response = new ProxiedResponse();
response.setProxied(proxied.getBody());
// set additional information
return response;
}
// Won't work properly for POST yet
private <T> RequestEntity<T> convertToRequestEntity(HttpServletRequest request, HttpHeaders headers, T body) throws URISyntaxException {
// Build proxied URL
final StringBuilder redirectUrl = new StringBuilder(redirectBase).append(request.getRequestURI());
final String queryString = request.getQueryString();
if (queryString != null) {
redirectUrl.append("?").append(queryString);
}
// TODO enhancement: transmit headers and request body to make this a real proxy
final HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
return new RequestEntity<>(body, headers, httpMethod, new URI(redirectUrl.toString()));
}
}
@Configuration // adding @EnableWebMvc did not solve the problem
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
private static class StaticResourcesHandlerInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final String requestURI = request.getRequestURI();
if (requestURI == null || "/".equals(requestURI) || "/index.html".equals(requestURI) || requestURI.startsWith("/assets")) {
return super.preHandle(request, response, null);
}
return super.preHandle(request, response, handler);
}
}
@Autowired
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new StaticResourcesHandlerInterceptor()).addPathPatterns("/**");
}
}
答案 0 :(得分:0)
尝试将@EnableWebMvc
注释添加到您的配置中:
@Configuration
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
...
}
答案 1 :(得分:0)
您可以将路径拆分为通配符和必须与否定的前瞻正则表达式匹配的命名路径变量。
@RequestMapping("/{variable:(?!static).*}/**")
然后,如果需要传递变量,则可以使用@PathVariable String variable
作为控制器方法的参数来获取变量的值。
(宁愿写评论,但我的声誉不够)