spring-boot - Spring Boot Gradle 多模块项目找不到模板位置
问题描述
我正在使用 Gradle 管理我的项目,并且根项目中有 3 个模块(Spring Boot)。
每个模块在自定义模板位置都有自己的模板,/WEB-INF/templates/
我在每个模块上设置了这些属性application.yml
。
但是,当应用程序启动时出现警告日志
2021-09-16 22:53:39.153 WARN 17043 --- [ restartedMain] o.s.b.a.m.MustacheAutoConfiguration : Cannot find template location: /WEB-INF/templates/ (please add some templates, check your Mustache configuration, or set spring.mustache.check-template-location=false)
这很奇怪,因为我独立运行应用程序,它不是作为多模块项目打开的项目,只是将项目作为单个项目打开,它运行良好。
这是我的 build.gradle
// root project
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}
subprojects {
group = 'yes.youcan'
version = '0.0.1-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
compileJava {
sourceCompatibility = 1.8
}
test {
useJUnitPlatform()
}
project(':child2') {
apply plugin: 'war'
}
project(':child3') {
apply plugin: 'war'
}
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:2.5.4")
}
}
}
// child project 1
ext {
keycloakVersion = '15.0.2'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.boot:spring-boot-starter-log4j2"
modules {
module("org.springframework.boot:spring-boot-starter-logging") {
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
}
}
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.keycloak:keycloak-spring-boot-starter'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.rest-assured:rest-assured'
}
dependencyManagement {
imports {
mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keycloakVersion}"
}
}
// child project 2
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation "org.springframework.boot:spring-boot-starter-log4j2"
modules {
module("org.springframework.boot:spring-boot-starter-logging") {
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
}
}
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
compileOnly 'com.querydsl:querydsl-jpa'
compileOnly 'com.querydsl:querydsl-core'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'javax.persistence:javax.persistence-api'
annotationProcessor 'javax.annotation:javax.annotation-api'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'com.querydsl:querydsl-jpa'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.rest-assured:rest-assured'
}
def generated = 'src/main/generated'
sourceSets {
main.java.srcDirs += [ generated ]
}
tasks.withType(JavaCompile) {
options.annotationProcessorGeneratedSourcesDirectory(file(generated))
}
clean.doLast {
file(generated).deleteDir()
}
// child project 3
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.boot:spring-boot-starter-log4j2"
modules {
module("org.springframework.boot:spring-boot-starter-logging") {
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
}
}
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'com.querydsl:querydsl-jpa'
compileOnly 'com.querydsl:querydsl-core'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'javax.persistence:javax.persistence-api'
annotationProcessor 'javax.annotation:javax.annotation-api'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'com.querydsl:querydsl-jpa'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.rest-assured:rest-assured'
}
clean {
delete file('src/main/generated')
}
这是应用程序独立运行时的配置
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'war'
}
group = 'yes.youcan
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'com.querydsl:querydsl-jpa'
compileOnly 'com.querydsl:querydsl-core'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'javax.persistence:javax.persistence-api'
annotationProcessor 'javax.annotation:javax.annotation-api'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.rest-assured:rest-assured'
}
clean {
delete file('src/main/generated')
}
test {
useJUnitPlatform()
}
应用程序.yml
spring:
profiles:
active: local
mustache:
prefix: /WEB-INF/templates/
suffix: .html
data:
web:
pageable:
default-page-size: 5
server:
port: 8081
---
spring:
config:
activate:
on-profile: local
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password:
h2:
console:
enabled: true
path: /h2-console
jpa:
hibernate.ddl-auto: create-drop
properties.hibernate.format_sql: true
properties.hibernate.dialect: org.hibernate.dialect.H2Dialect
defer-datasource-initialization: true
logging:
level:
org.hibernate.SQL: debug
org.springframework.security: error
---
spring:
config:
activate:
on-profile: dev
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password:
h2:
console:
enabled: true
path: /h2-console
jpa:
hibernate.ddl-auto: create-drop
properties.hibernate.format_sql: true
properties.hibernate.dialect: org.hibernate.dialect.H2Dialect
logging.level.org.hibernate.SQL: debug
logging.level.org.springframework.security: error
这是我的项目结构
├── child1
│ ├── gradle
│ │ └── wrapper
│ └── src
│ └── main
│ ├── java
│ │ └── yes
│ │ └── youcan
│ ├── resources
│ └── webapp
│ ├── resources
│ │ └── css
│ └── WEB-INF
│ └── templates
├── child2
│ ├── gradle
│ │ └── wrapper
│ └── src
│ └── main
│ ├── generated
│ │ └── yes
│ │ └── youcan
│ ├── java
│ │ └── yes
│ │ └── youcan
│ ├── resources
│ └── webapp
│ ├── resources
│ │ ├── css
│ │ ├── img
│ │ └── js
│ └── WEB-INF
│ └── templates
└── child3
├── gradle
│ └── wrapper
└── src
└── main
├── java
│ └── yes
│ └── youcan
├── resources
└── webapp
├── resources
│ ├── css
│ ├── img
│ └── js
└── WEB-INF
└── templates
如果你们有任何解决这个问题的想法请告诉我谢谢
===== 21 年 9 月 23 日编辑 =====
我发现了一些不同之处!当多模块项目运行时,它会检查是否存在作为模板位置的资源,/WEB-INF/templates/
如下TemplateLocation.java
所示
public boolean exists(ResourcePatternResolver resolver) {
Assert.notNull(resolver, "Resolver must not be null");
if (resolver.getResource(this.path).exists()) {
return true;
}
try {
return anyExists(resolver);
}
catch (IOException ex) {
return false;
}
}
我在此检查处理时检查了根文件路径,另一方面,当我在单个模块项目上执行相同的工作时resolver.getResource('/').getFile()
,它返回了一些临时目录,它返回了实际的项目目录/AppData/.../tomcat-docbase...
D:\Java\...
我希望它可以成为解决问题的线索
解决方案
推荐阅读
- python - 使用 seaborn 联合图返回 hexbin 中的值数组
- linux - 在 Dante Socks5 Server ubuntu 中允许绑定连接
- python - 无法在 python 中读取地理空间数据(img、rrd、ige 文件)
- python - Python:更改 JSON 中的元素
- javascript - Puppeteer 中的 API 请求因 401 错误而被阻止
- python - python中1到N之间数字求和的问题
- reactjs - 空间未触发 onChange 事件
- watson-studio - 在 Watson Studio 中创建新项目时出现问题
- python - 如何使用密码保护 Google 表格中的敏感内容?
- r - 对于 df 中的每一行,提取具有最接近值的观察值