我有一个 spring boot、java 8 API,我想添加一个 React 前端,以使 API 操作更易于导航和使用。我用过JHipster生成器来生成 React 应用程序。然后我只是将 Web 部分放入我的应用程序中,但是每当我运行 Spring Boot 应用程序并尝试导航到端口 :8080
时,我都会看到以下页面:
控制台中出现以下错误:
2019-07-15 15:07:21.414 INFO 29145 --- [)-10.15.114.229] o.a.c.c.C.[.[.[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-07-15 15:07:21.414 INFO 29145 --- [)-10.15.114.229] o.s.w.s.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-07-15 15:07:21.414 DEBUG 29145 --- [)-10.15.114.229] o.s.w.s.DispatcherServlet : Detected StandardServletMultipartResolver
2019-07-15 15:07:21.426 DEBUG 29145 --- [)-10.15.114.229] o.s.w.s.DispatcherServlet : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2019-07-15 15:07:21.426 INFO 29145 --- [)-10.15.114.229] o.s.w.s.DispatcherServlet : Completed initialization in 12 ms
2019-07-15 15:07:25.079 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet : GET "/", parameters={}
2019-07-15 15:07:25.093 DEBUG 29145 --- [nio-8080-exec-1] s.d.s.w.PropertySourcedRequestMappingHandlerMapping : looking up handler for path: /
2019-07-15 15:07:25.128 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.h.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
2019-07-15 15:07:25.130 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2019-07-15 15:07:25.131 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet : Completed 404 NOT_FOUND
2019-07-15 15:07:25.152 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
2019-07-15 15:07:25.153 DEBUG 29145 --- [nio-8080-exec-1] s.d.s.w.PropertySourcedRequestMappingHandlerMapping : looking up handler for path: /error
2019-07-15 15:07:25.167 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-07-15 15:07:25.199 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2019-07-15 15:07:25.208 DEBUG 29145 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
这是我的项目结构:
FooApplication
├── build.gradle
├── api/
├── src.main.java.com.foo/
├── FooApplication.java
└── build.gradle
├── web/
├── node_modules/
├── src.main.webapp/
├── app/
├── index.tsx
├── routes.tsx
└── app.tsx
└── index.html
├── webpack/
└── webpack.common.js
└── build.gradle
这是我的 webpack.common.js
文件:
const webpack = require('webpack');
const {BaseHrefWebpackPlugin} = require('base-href-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const path = require('path');
const utils = require('./utils.js');
const getTsLoaderRule = env => {
const rules = [
{
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve('build/cache-loader')
}
},
{
loader: 'thread-loader',
options: {
// There should be 1 cpu for the fork-ts-checker-webpack-plugin.
// The value may need to be adjusted (e.g. to 1) in some CI environments,
// as cpus() may report more cores than what are available to the build.
workers: require('os').cpus().length - 1
}
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
happyPackMode: true
}
}
];
if (env === 'development') {
rules.unshift({
loader: 'react-hot-loader/webpack'
});
}
return rules;
};
module.exports = options => ({
cache: options.env !== 'production',
resolve: {
extensions: [
'.js', '.jsx', '.ts', '.tsx', '.json'
],
modules: ['node_modules'],
alias: {
app: utils.root('src/main/webapp/app/')
}
},
module: {
rules: [
{
test: /\.tsx?$/,
use: getTsLoaderRule(options.env),
include: [utils.root('./src/main/webapp/app')],
exclude: [utils.root('node_modules')]
},
{
test: /\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/i,
loader: 'file-loader',
options: {
digest: 'hex',
hash: 'sha512',
name: 'content/[hash].[ext]'
}
},
{
enforce: 'pre',
test: /\.jsx?$/,
loader: 'source-map-loader'
},
{
test: /\.tsx?$/,
enforce: 'pre',
loader: 'tslint-loader',
exclude: [utils.root('node_modules')]
}
]
},
stats: {
children: false
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: `'${options.env}'`,
VERSION: `'${utils.parseVersion()}'`,
DEBUG_INFO_ENABLED: options.env === 'development',
// The root URL for API calls, ending with a '/' - for example: `"https://www.jhipster.tech:8081/myservice/"`.
// If this URL is left empty (""), then it will be relative to the current context.
// If you use an API server, in `prod` mode, you will need to enable CORS
// (see the `jhipster.cors` common JHipster property in the `application-*.yml` configurations)
SERVER_API_URL: `''`
}
}),
new ForkTsCheckerWebpackPlugin({tslint: true}),
new CopyWebpackPlugin([
{from: './node_modules/swagger-ui/dist/css', to: 'swagger-ui/dist/css'},
{from: './node_modules/swagger-ui/dist/lib', to: 'swagger-ui/dist/lib'},
{from: './node_modules/swagger-ui/dist/swagger-ui.min.js', to: 'swagger-ui/dist/swagger-ui.min.js'},
{from: './src/main/webapp//swagger-ui/', to: 'swagger-ui'},
{from: './src/main/webapp/static/', to: 'content'},
{from: './src/main/webapp/favicon.ico', to: 'favicon.ico'},
{from: './src/main/webapp/manifest.webapp', to: 'manifest.webapp'},
// jhipster-needle-add-assets-to-webpack - JHipster will add/remove third-party resources in this array
{from: './src/main/webapp/robots.txt', to: 'robots.txt'}
]),
new HtmlWebpackPlugin({
template: './src/main/webapp/index.html',
chunksSortMode: 'dependency',
inject: 'body'
}),
new BaseHrefWebpackPlugin({baseHref: '/'}),
]
});
如何让 Spring Boot 在导航到 localhost:8080
时提供 index.html
文件?我知道我必须覆盖一些默认的 Spring Boot 配置才能使其正常工作,但我不清楚哪些配置。
我可以根据要求提供更多文件的详细信息,只是不想在帖子中添加不必要的信息。
最佳答案
请求应用程序入口点的映射、读取文件并返回内容。就我而言,React 代码存储在/tmp/build/index.html 中。简化并忽略错误,它可能看起来像这样:
@RequestMapping(
value = "",
method = RequestMethod.GET)
public ResponseEntity<String> getIndexContent() {
final File file = new File("/tmp/build/index.html");
final String content =
FileUtils.readFileToString(
file,
StandardCharsets.UTF_8);
return ResponseEntity
.ok()
.contentType(MediaType.TEXT_HTML)
.body(content);
}
关于java - Spring Boot React 在单独的包中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57046856/