java 如何在 Spring Boot + Angular 2 项目中使用 Gradle 构建将静态文件添加到 jar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45146201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add static files to jar using Gradle build in Spring Boot + Angular 2 project
提问by fpezzini
I have a Spring Boot + Angular 2 project. I want to deploy it to Heroku. I'm able to run the npm build then copy the generated files over to the public folder (src/resources/public) manually, then run the backend build. What I want to do is to set up a gradle build that will do all of that at once. What I have so far is a gradle build that will build the front end, build the backend, however it does not copy the static files before generating the jar. Since the jar does not contain said static files, it won't work on Heroku.
我有一个 Spring Boot + Angular 2 项目。我想将它部署到 Heroku。我可以运行 npm build,然后手动将生成的文件复制到公共文件夹 (src/resources/public),然后运行后端构建。我想要做的是设置一个 gradle 构建,它可以一次完成所有这些。到目前为止,我所拥有的是一个 gradle 构建,它将构建前端,构建后端,但是它不会在生成 jar 之前复制静态文件。由于 jar 不包含上述静态文件,因此它不适用于 Heroku。
Here's the project folder structure:
这是项目文件夹结构:
root
backend
src/main/java
src/main/resources
frontend
--> angular files go here
build/libs -> where the JAR file goes
The gradle build file:
gradle 构建文件:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// spring
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE')
classpath('org.springframework:springloaded:1.2.6.RELEASE')
}
}
plugins {
id "com.moowork.node" version "1.2.0"
}
// gradle wrapper
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
// configure gradle-node-plugin
node {
version = '8.1.4'
npmVersion = '5.0.3'
download = true
workDir = file("${project.projectDir}/node")
nodeModulesDir = file("${project.projectDir}/")
}
// clean node/node_modules/dist
task npmClean(type: Delete) {
final def webDir = "${rootDir}/frontend"
delete "${webDir}/node"
delete "${webDir}/node_modules"
delete "${webDir}/dist"
delete "${webDir}/coverage"
delete "${rootDir}/backend/src/main/resources/public"
}
// clean task for npm
task copyFiles {
doLast {
copy {
from "${rootDir}/frontend/dist"
into "${rootDir}/backend/src/main/resources/public"
}
}
}
// build task for npm
task frontendBuild {}
frontendBuild.dependsOn(npm_install)
frontendBuild.dependsOn(npm_run_build)
npm_install {
args = ['--prefix', './frontend']
}
npm_run_build {
args = ['--prefix', './frontend']
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
sourceSets {
main {
java {
srcDirs = ['backend/src/main/java']
}
resources {
srcDirs = ['backend/src/main/resources']
}
}
}
copyFiles.dependsOn(frontendBuild);
compileJava.dependsOn(frontendBuild);
task backendBuild {}
backendBuild.dependsOn(compileJava)
backendBuild.dependsOn(jar)
jar.dependsOn(copyFiles)
repositories {
mavenCentral()
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
}
}
idea {
module {
inheritOutputDirs = false
outputDir = file("${buildDir}/classes/main/")
}
}
jar {
baseName = 'expense-splitter'
version = '0.0.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
configurations {
dev
}
dependencies {
// spring
compile('org.springframework.boot:spring-boot-starter-web:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:1.5.2.RELEASE')
compile('org.apache.commons:commons-lang3:3.3.2')
// to make hibernate handle java 8 date and time types correctly
// it's marked as deprecated but we need to keep it until
// spring boot jpa starts using hibernate 5.2
compile('org.hibernate:hibernate-java8:5.1.0.Final')
// json web tokens
compile ('io.jsonwebtoken:jjwt:0.7.0')
compile 'mysql:mysql-connector-java'
// google gson
compile('com.google.code.gson:gson:2.8.0')
// Hymanson - parsing of java 8 date and time types
compile('com.fasterxml.Hymanson.datatype:Hymanson-datatype-jsr310:2.8.7')
// spring dev tools
dev('org.springframework.boot:spring-boot-devtools:1.5.2.RELEASE')
// testing
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.2.RELEASE')
}
// run spring boot app
bootRun {
//addResources = true
classpath = sourceSets.main.runtimeClasspath + configurations.dev
jvmArgs = ["-Xdebug -agentlib:jdwp=transport=dt_socket,address=8080,server=y,suspend=n"]
}
// run all task
task runAll {}
runAll.dependsOn(bootRun)
Thanks in advance,
提前致谢,
回答by nickb
Try a different approach. Instead of manually copying the resources, tell Gradle that when it processes resources for the JAR, also take into consideration what is in frontend/dist/
:
尝试不同的方法。不要手动复制资源,而是告诉 Gradle 在处理 JAR 的资源时,还要考虑其中的内容frontend/dist/
:
processResources {
from ('frontend/dist/') {
into 'public'
}
}
This should result in a JAR containing a public/
directory, with the contents of frontend/dist/
inside of it.
这应该会生成一个包含public/
目录的 JAR,其中包含其中的内容frontend/dist/
。
回答by Evgeny Lebedev
Gradle configuration for Spring Boot 1.5\2.x + Angular 2-6
Spring Boot 1.5\2.x + Angular 2-6 的 Gradle 配置
Angular in sub-folder frontend
子文件夹中的角度 frontend
Frontend module
前端模块
Crate build.gradle
:
板条箱build.gradle
:
plugins {
id "com.moowork.node" version "1.2.0"
}
node {
version = '8.11.3'
npmVersion = '5.6.0'
download = true
workDir = file("${project.buildDir}/node")
nodeModulesDir = file("${project.projectDir}")
}
task build(type: NpmTask) {
args = ['run', 'build']
}
build.dependsOn(npm_install)
Note for Angular 6
Angular 6 的注意事项
Update outputPath
value in angular.json
to 'dist'
将outputPath
值更新angular.json
为“dist”
Backend module
后端模块
Edit build.gradle
for backend module:
编辑build.gradle
后端模块:
Spring Boot 2.X:
春季启动 2.X:
bootJar {
archiveName = "yourapp.jar"
mainClassName = 'com.company.app.Application'
from('frontend/dist') {
into 'static'
}
}
Spring Boot 1.5.X:
春季启动 1.5.X:
jar {
archiveName = "yourapp.jar"
manifest {
attributes 'Main-Class': 'com.company.app.Application'
}
from('frontend/dist') {
into 'static'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Finally execute bootRepackage
or bootJar
task and check results in builds/libs
最后执行bootRepackage
或bootJar
任务并检查结果builds/libs
回答by mr.M
Assume that front end is located at the following folder: src/main/webapp/fe-ui/
, the following solution for the Spring Boot version 2.1.1.RELEASE could be considered:
假设前端位于以下文件夹:src/main/webapp/fe-ui/
,Spring Boot 2.1.1.RELEASE版本可以考虑以下解决方案:
bootJar {
baseName = 'jar-name'
version = '0.1.0'
from('src/main/webapp/fe-ui/build') {
into 'public'
}
}
task installFeDependencies(type: NpmTask) {
args = ['install']
}
task buildFe(type: NpmTask) {
args = ['run', 'build']
dependsOn installFeDependencies
}
compileJava {
dependsOn buildFe
}
Running gradlew build
will install, build front end as well as will invoke bootJar
. The latter will package built front end bundle.
运行gradlew build
将安装、构建前端以及调用bootJar
. 后者将打包构建的前端包。