配置响应以在Spring启动应用程序上提供

时间:2017-11-19 19:56:24

标签: java spring

到目前为止,我一直在为我的Spring启动应用编写一堆端点,没有html UI端。现在,我想提供包含反应代码的HTML文件和js文件。

当我访问http://localhost:8443时,我得到了:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Nov 19 11:54:01 PST 2017
There was an unexpected error (type=Not Found, status=404).
Not Found

到目前为止我做了什么:

1.添加了一个扩展WebMvcConfigurerAdapter的网络配置类:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public ViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/resources/static/");
        bean.setSuffix(".html");
        return bean;
    }
}

2.添加了一个休息控制器端点:

@RestController
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView getdata() {
        ModelAndView model = new ModelAndView("index");
        return model;
    }
}

我的项目中有myproject/src/main/resources/static/index.html个文件。

4 个答案:

答案 0 :(得分:4)

这实际上取决于您的设置。让我们假设您需要以下内容: enter image description here

让我们看一下简单的案例:没有thymeleaf模板或spring静态文件。 Spring用于服务休息api,剩下的就是反应。但您可以在任何请求映射网址时使用控制器。

一种选择是使用ResourceResolver并将其配置为:

@Configuration
public class Config implements WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        ResourceResolver resolver = new ReactResourceResolver();
        registry.addResourceHandler("/**")
                .resourceChain(true)
                .addResolver(resolver);

        // Can try to play with
        // registry.addResourceHandler("/**")
        //        .addResourceLocations("classpath:/static/");
        // But this option can't map every path to index.html
        // Can try https://stackoverflow.com/a/42998817/1032167
        // to resolve this, but then you loose /api/** => rest
        // and to be honest it is some regex madness, so
        // it was easier for me to setup custom resource resolver


    }

    public class ReactResourceResolver implements ResourceResolver {
        // root dir of react files
        // example REACT_DIR/index.html
        private static final String REACT_DIR = "/static/";

        // this is directory inside REACT_DIR for react static files
        // example REACT_DIR/REACT_STATIC_DIR/js/
        // example REACT_DIR/REACT_STATIC_DIR/css/
        private static final String REACT_STATIC_DIR = "static";

        private Resource index = new ClassPathResource(REACT_DIR + "index.html");
        private List<String> rootStaticFiles = Arrays.asList("favicon.io",
                "asset-manifest.json", "manifest.json", "service-worker.js");

        @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 (rootStaticFiles.contains(requestPath)
                    || requestPath.startsWith(REACT_STATIC_DIR)) {
                return new ClassPathResource(REACT_DIR + requestPath);
            } else
                return index;
        }

    }
}

以下是Spring 2.0.0.M4的完整工作演示: https://github.com/varren/SpringBootReactExample

我遇到了类似设置的问题:Spring single page for every url route and subroute "/a/** => /a/index.html except /a/static/**"

还有一个选项可以使用正则表达式Spring catch all route for index.html来解决问题,但我没有运气这个方法

答案 1 :(得分:3)

Spring Boot可以自动处理静态文件(按照惯例),只需将所有html,js,css等文件放到src/main/resources/static,删除ViewResolver和Controller for&#39; /&#39 ;并且它将起作用,index.html也将被Spring Boot映射到/

除此之外,您当然可以通过在@RequestMapping上使用正确的@RestController来使用api前缀创建REST端点

答案 2 :(得分:1)

你需要一个返回ModelAndView

的@Controller
    @Controller
    public class HomeController {

        @RequestMapping(value = {"/", "/index.html"})
        public ModelAndView sellerHome(HttpServletRequest request, 
                                       HttpServletResponse response) {
             return new ModelAndView("../static/index");
        }

    }

然后,您可以访问http://localhost:8443,并且在您正确配置端口的情况下应该看到您的索引页面。

答案 3 :(得分:0)

您知道,在Spring Boot 2.1.4中,新配置为:

package com.simplicity.resourceserver.configs;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/", "classpath:/resources/",
            "classpath:/static/", "classpath:/public/" };



    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);

        registry.addResourceHandler("/vanilla/**")
                .addResourceLocations("classpath:/vanilla/");

            registry.addResourceHandler("/react/**")
                    .addResourceLocations("classpath:/react/")
                .resourceChain(true);
    }

    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setSuffix(".html");
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseTrailingSlashMatch(true);
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/react")
                .setViewName("forward:/react/index.html");
        registry.addViewController("/react/{path:[^\\.]*}")
                .setViewName("forward:/react/index.html");
        registry.addViewController("/react/**/{path:[^\\.]*}")
                .setViewName("forward:/react/index.html");

    }
}

Spring Boot应该被定义为基于“视频扑克”的编程:尝试几千次(例如,当您玩视频扑克时),几乎没有什么不同,直到它起作用为止。

就我而言,我在src / main / resources下的两个单独的文件夹中有两个不同的应用程序

  • src / main / resources / vanilla
  • src / main / resources / react

在我看来,这是两个证明概念,但它可能是一个微前端架构。