代码之家  ›  专栏  ›  技术社区  ›  Stefan Falk

如何在@Controller中传递静态内容并转发非静态内容请求?

  •  1
  • Stefan Falk  · 技术社区  · 6 年前

    我有一个项目,它运行一个Spring Boot应用程序,该应用程序服务于 static/ .

    为了使事情顺利进行,我不得不在一些端点附近移动( see my old question ).以下内容适用于以下两个应用程序: /a 和一个REST API /api :

    @Controller
    public class ForwardController {
    
        @RequestMapping(value = "/*", method = RequestMethod.GET)
        public String redirectRoot(HttpServletRequest request) {
            return "forward:/a/web/index.html";
        }
    
        @RequestMapping(value = "/a/**/{path:[^.]*}", method = RequestMethod.GET)
        public String redirectClients(HttpServletRequest request) {
    
            String requestURI = request.getRequestURI();
    
            if (requestURI.startsWith("/a/admin/")) {
                return "forward:/a/admin/index.html";
            }
    
            return "forward:/a/web/index.html";
        }
    
    }
    

    唯一的事 工作是在根目录下提供的任何静态内容 / 例如 sitemap.xml

    问题是我正在匹配 /* 在词根上,也就是任何请求 /sitemap.xml 会被抓到的 ForwardController 1.我试过了 /{path:[^.]*} -那我只能进入 /网站地图。xml 但是,它转向了 /a/web/index.html 再也联系不到了。

    事实上,我真的不明白为什么 /{路径:[^.]*} 在这里不起作用,因为它应该匹配任何看起来不像静态内容的内容,例如。 /a-song.wav .

    有没有办法让这一切顺利进行?


    总而言之:

    我有两个web应用程序客户端:

    /a/admin/index.html
    /a/web/index.html
    

    我想要 任何 请求根目录 / 转交 /a/web/index。html 仍然可以从根目录访问静态内容,例如。 /网站地图。xml 等等

    问题是 /{path:^[.]*} 只允许我访问静态文件,但会中断对客户端和服务器的转发 /* 将用于转发到客户端,但无法访问根目录上的静态文件。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Alex    6 年前

    IIRC spring MVC controller中方法的顺序很重要,您可以将其用于您的案例。如果您这样定义控制器:

    @Controller
    public class ForwardController {
    
        @RequestMapping(value = "/sitemap.xml", method = RequestMethod.GET)
        public String redirectSitemap(HttpServletRequest request) {
            return "forward:/a/web/sitemap.xml";
        }
    
        @RequestMapping(value = "/*", method = RequestMethod.GET)
        public String redirectRoot(HttpServletRequest request) {
            return "forward:/a/web/index.html";
        }
    
        ...
    
    }
    

    Spring将首先匹配sitemap。xml路径,如果不匹配,则转到第二个路径。如果顶级资源的数量没有那么多,可以将它们放在最上面进行优先级匹配。

        2
  •  -1
  •   Stefan Falk    6 年前

    除非我遗漏了什么,否则我会创建两个端点。

    @Controller
    public class ForwardController {
    
        @RequestMapping(value = {"/", "/**/{path:[^.]*}"}, method = RequestMethod.GET)
        public String redirectRoot(HttpServletRequest request) {
            return "forward:/a/web/index.html";
        }
    
        @RequestMapping(value = "/a/**/{path:[^.]*}", method = RequestMethod.GET)
        public String redirectClients(HttpServletRequest request) {
    
            String requestURI = request.getRequestURI();
    
            if (requestURI.startsWith("/a/admin/")) {
                return "forward:/a/admin/index.html";
            }
    
            return "forward:/a/web/index.html";
        }
    
    }
    

    下面是所有适用于我的模拟请求。

    除static之外的所有根请求(/web&/&/web/2)都与第一个端点匹配。

    所有静态请求(/sitemap.xml&/a/web/index.html)都不与任何端点匹配,而是由 ResourceHttpRequestHandler .在我的例子中,静态资源位于src/main/resources/static/a/web/index中。html&src/main/resources/static/sitemap。xml。

    所有web和管理员请求(/a/web&/a/admin)都与/a/**{path:[^.]*}