尽管使用了@RequestMapping(" **")

时间:2017-05-24 04:53:32

标签: spring-mvc spring-boot

上下文

我目前正在开展一个教育项目。这意味着两个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(在SOSO 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("/**");
    }
}

2 个答案:

答案 0 :(得分:0)

尝试将@EnableWebMvc注释添加到您的配置中:

@Configuration
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

...

}

答案 1 :(得分:0)

您可以将路径拆分为通配符和必须与否定的前瞻正则表达式匹配的命名路径变量。

@RequestMapping("/{variable:(?!static).*}/**")

然后,如果需要传递变量,则可以使用@PathVariable String variable作为控制器方法的参数来获取变量的值。

(宁愿写评论,但我的声誉不够)