[英]Serve static folder with Spring Boot and React Router
我有一個 React 客戶端應用程序,它被構建並編譯到 Java 資源文件夾中
src/main/resources/static
然后靜態文件夾的內容由標准 Spring Boot 應用程序提供,沒有問題。
但是,當我開始使用 React Router 時,我需要能夠解析此路徑:
localhost:8080/userSettingsPage
進入index.html :
src/resource/static/index.html
我知道我可以在 Controller 中執行以下操作:
@Controller
public class MyController {
@RequestMapping("/userSettingsPage")
public String getIndex() {
return "index.html";
}
}
但是我想以更通用的方式指定我的控制器:
我怎樣才能實現它?
經過大量研究和嘗試各種方法后,我得出結論,最簡單的解決方案是實現過濾器並自行處理靜態 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());
}
}
Jurass 的回答對我有用,但我需要設置 ContentType 標頭。 如果沒有正確的標題,瀏覽器會將 HTML 打印為引號中的文本。 這就是我在 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());
}
}
如果您找到了更好的解決方案,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.