【发布时间】:2017-10-24 06:13:18
【问题描述】:
上下文
我目前正在从事一个教育项目。这意味着两个 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的任何其他子目录中的任何文件)/itfnot 工作:Spring Boot 似乎不知道其中的索引文件。我必须指定一个完整的 URI,直到我要显示的特定文件。然而,这对我需要的
@RequestMapping("**")根本不起作用。
暂定
我尝试使用WebMvcConfigurerAdapter 和HandlerInterceptorAdapter(在SO、SO again 和 Internet 上的许多其他地方找到),但无法再启动我的项目,因为 Spring boot 然后找不到 @ 987654341@bean(Spring Boot最近有变化吗?我用的是1.5.3.RELEASE版本)。
我也尝试了一些反匹配,但不仅不起作用,而且感觉非常非常脏(而且整个项目可能不是最优的,所以说了很多)。
好奇的代码示例
我的“代理”控制器
注意:您可以提出更好的方法来实现这一点在 cmets 中。请记住,尽管我总是对改进建议持开放态度,但这不是我的问题。
@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()));
}
}
我排除静态资源 URL 的肮脏尝试
@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("/**");
}
}
【问题讨论】: