java - 每个 url 路由和子路由的 Spring 单页 "/a/** =>/a/index.html except/a/static/**"

标签 java spring reactjs spring-mvc single-page-application

我正在构建 spring 网站,该网站在子路径下具有 React 单页应用程序,我当前的 url 结构应该如下所示

localhost/admin/** => react app
localhost/**       => spring thymeleaf/rest/websocket app for everything else

react app mapping:
localhost/admin/static/**  => static react files
localhost/admin/**         => react index.html for everything else

Example of project resources structure:  
resources/
    admin/         <= my admin react files is here
        index.html
        static/    <= react css, js,  statics
    templates/     <= thymeleaf templates
    static/        <= theamleaf static
    ...

所以我需要为每个 url 路由及其子路由转发 react index.html 文件。除了静态文件之外的所有内容基本上都是单页应用

看起来像是一项常见的任务,以下是我已经尝试过的一些事情:


项目 spring + react + gradle 如何构建项目的完整工作演示以及为什么我不能将 react 文件放在不同的目录中(例如/resources/static):https://github.com/varren/spring-react-example


不能将 forward:/admin/index.html 用于 /admin/** 因为这会创建递归,因为 admin/index.html 也在 admin/** 下,必须以某种方式拦截 admin/static/**


无法在 WebMvcConfigurerAdapter

中使用 addResourceHandlers
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/admin/**")
            .addResourceLocations("classpath:/admin/");
}

index.html 仅映射到 /admin/index.html url,此选项几乎有效,但前提是您从 localhost/访问 React 应用程序admin/index.html


thisthisthis和许多其他链接,我也有一些解决方案,但也许有我看不到的通用选项

最佳答案

现在我正在使用自定义 ResourceResolver 来解决这个问题

演示:https://github.com/varren/spring-react-example

@Configuration
public class BaseWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        ResourceResolver resolver = new AdminResourceResolver();
        registry.addResourceHandler("/admin/**")
                .resourceChain(false)
                .addResolver(resolver);


        registry.addResourceHandler("/admin/")
                .resourceChain(false)
                .addResolver(resolver);
    }


    private class AdminResourceResolver implements ResourceResolver {
        private Resource index = new ClassPathResource("/admin/index.html");

        @Override
        public Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) {
            return resolve(requestPath, locations);
        }

        @Override
        public String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain) {
            Resource resolvedResource = resolve(resourcePath, locations);
            if (resolvedResource == null) {
                return null;
            }
            try {
                return resolvedResource.getURL().toString();
            } catch (IOException e) {
                return resolvedResource.getFilename();
            }
        }

        private Resource resolve(String requestPath, List<? extends Resource> locations) {

            if(requestPath == null) return null;

            if (!requestPath.startsWith("static")) {
                return index;
            }else{
                return new ClassPathResource("/admin/" + requestPath);
            }
        }
    }
}

关于java - 每个 url 路由和子路由的 Spring 单页 "/a/** =>/a/index.html except/a/static/**",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46000685/

相关文章:

Java spring map 无法推断类型变量 R

java - 将 sql 中的多个列映射到 java 对象

java - 如何在渲染 View 之前预加载java方法

node.js - 使用 MERN 堆栈构建相对路径的最合适方法是什么?

javascript - 更新状态和后端

java - 如何编写接受二进制文件的 Restful 网络服务 (pdf)

java - 并行数组排序时出现问题

java - 在应用程序中包含软键盘

java - OkHttpClient 与 Java Future java.io.InterruptedIOException

reactjs - 将参数传递给 `connect()` 中的 mapStateToProps