[英]Serve static folder with Spring Boot and React Router
I have a React client application which is build and compiled into the Java resource folder我有一个 React 客户端应用程序,它被构建并编译到 Java 资源文件夹中
src/main/resources/static
Content of the static folder is then served by standard Spring Boot application with no issues.然后静态文件夹的内容由标准 Spring Boot 应用程序提供,没有问题。
However, when I will start to use React Router, I need to be able to resolve this path:但是,当我开始使用 React Router 时,我需要能够解析此路径:
localhost:8080/userSettingsPage
into index.html :进入index.html :
src/resource/static/index.html
I'm aware that I can do this in Controller as follow:我知道我可以在 Controller 中执行以下操作:
@Controller
public class MyController {
@RequestMapping("/userSettingsPage")
public String getIndex() {
return "index.html";
}
}
However I would like to specify my Controller in more generic way:但是我想以更通用的方式指定我的控制器:
How can I achieve it?我怎样才能实现它?
After lot of research and trying various approaches I have come to conclusion that the simplest solution would be to implement Filter and handle serving of static web files on my own, which bypasses the Spring's handling:经过大量研究和尝试各种方法后,我得出结论,最简单的解决方案是实现过滤器并自行处理静态 Web 文件的服务,这绕过了 Spring 的处理:
@Component
public class StaticContentFilter implements Filter {
private List<String> fileExtensions = Arrays.asList("html", "js", "json", "csv", "css", "png", "svg", "eot", "ttf", "woff", "appcache", "jpg", "jpeg", "gif", "ico");
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
}
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = request.getServletPath();
boolean isApi = path.startsWith("/api");
boolean isResourceFile = !isApi && fileExtensions.stream().anyMatch(path::contains);
if (isApi) {
chain.doFilter(request, response);
} else if (isResourceFile) {
resourceToResponse("static" + path, response);
} else {
resourceToResponse("static/index.html", response);
}
}
private void resourceToResponse(String resourcePath, HttpServletResponse response) throws IOException {
InputStream inputStream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(resourcePath);
if (inputStream == null) {
response.sendError(NOT_FOUND.value(), NOT_FOUND.getReasonPhrase());
return;
}
inputStream.transferTo(response.getOutputStream());
}
}
I think what you're looking for is a ResourceHandler https://www.baeldung.com/spring-mvc-static-resources#3-chaining-resourceresolvers resp.我认为您正在寻找的是 ResourceHandler https://www.baeldung.com/spring-mvc-static-resources#3-chaining-resourceresolvers resp。 https://github.com/eugenp/tutorials/blob/c9882f2090e918d0f441eeebf1f456e89dda2a17/spring-static-resources/src/main/java/com/baeldung/spring/MvcConfig.java#L57 https://github.com/eugenp/tutorials/blob/c9882f2090e918d0f441eeebf1f456e89dda2a17/spring-static-resources/src/main/java/com/baeldung/spring/MvcConfig.java#L57
Hope that helps you to have a starting point for your research :)希望这可以帮助您为研究找到一个起点:)
Jurass's answer worked for me, but I needed to set ContentType headers. Jurass 的回答对我有用,但我需要设置 ContentType 标头。 Without correct headers the browser would print the HTML as text in quotes.如果没有正确的标题,浏览器会将 HTML 打印为引号中的文本。 This is how I enabled natural paths in React.这就是我在 React 中启用自然路径的方式。
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
@Component
public class StaticContentFilter implements Filter {
private List<String> fileExtensions = Arrays.asList("html", "js", "json", "csv", "css", "png", "svg", "eot", "ttf", "woff", "appcache", "jpg", "jpeg", "gif", "ico");
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
}
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = request.getServletPath();
boolean isApi = path.startsWith("/api");
boolean isResourceFile = !isApi && fileExtensions.stream().anyMatch(path::contains);
if (isApi) {
chain.doFilter(request, response);
} else if (isResourceFile) {
resourceToResponse("static" + path, response);
} else {
resourceToResponse("static/index.html", response);
}
}
private void resourceToResponse(String resourcePath, HttpServletResponse response) throws IOException {
InputStream inputStream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(resourcePath);
if (inputStream == null) {
response.sendError(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.getReasonPhrase());
return;
}
//headers
if (resourcePath.endsWith(".html")) {
response.setContentType("text/html");
}
if (resourcePath.endsWith(".css")) {
response.setContentType("text/css");
}
if (resourcePath.endsWith(".js")) {
response.setContentType("text/javascript");
}
inputStream.transferTo(response.getOutputStream());
}
}
If you've found a better solution, please let me know.如果您找到了更好的解决方案,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.