到目前为止,我一直在为我的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
个文件。
答案 0 :(得分:4)
让我们看一下简单的案例:没有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下的两个单独的文件夹中有两个不同的应用程序
在我看来,这是两个证明概念,但它可能是一个微前端架构。