零、版本说明:
springboot: 2.7.18
使用log4j2,不使用springboot自带的logback
scala版本:2.11
jackson版本:2.16.0
一、依赖:
buildscript {dependencies {// using spring-boot-maven-plugin as package toolclasspath("org.springframework.boot:spring-boot-maven-plugin:2.7.18")}
}
plugins {id 'idea'id 'scala'id 'org.springframework.boot' version '2.7.18'id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
// 指定java版本
sourceCompatibility = 1.8
targetCompatibility = 1.8
// 尽量使用2.16.0版本的jackson对scala支持更好。
ext {jackson_version = '2.16.0'
}dependencies {implementation("org.springframework.boot:spring-boot-starter-web") {exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'}implementation("org.springframework.boot:spring-boot-starter-log4j2")testImplementation("org.springframework.boot:spring-boot-starter-test") {exclude group: 'org.junit.jupiter'}testImplementation 'io.projectreactor:reactor-test:3.4.29'implementation("com.fasterxml.jackson.core:jackson-core:${jackson_version}")implementation("com.fasterxml.jackson.core:jackson-annotations:${jackson_version}")implementation("com.fasterxml.jackson.core:jackson-databind:${jackson_version}")implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson_version}")implementation("com.fasterxml.jackson.module:jackson-module-scala_2.11:${jackson_version}")testImplementation "com.fasterxml.jackson.core:jackson-core:${jackson_version}"testImplementation("com.fasterxml.jackson.core:jackson-annotations:${jackson_version}")testImplementation("com.fasterxml.jackson.core:jackson-databind:${jackson_version}")testImplementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson_version}")testImplementation("com.fasterxml.jackson.module:jackson-module-scala_2.11:${jackson_version}")
}
configurations {all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
主启动类
此处也可以继承scala的App
但需要注意要重新App
中的main方法。
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.{ SpringBootApplication}@SpringBootApplication
class AppServe
object AppServer {private val log = org.slf4j.LoggerFactory.getLogger(classOf[AppServer])def main(args: Array[String]): Unit = {log.info(s"${getClass.getName} get args: ${args.toList.toString()}")SpringApplication.run(classOf[AppServer], args: _*)}
}
scala常用获取jackson objectMapper参考:
// scaladef getMapper: ObjectMapper = {var mapper: ObjectMapper = JsonMapper.builder().addModule(DefaultScalaModule).build() :: ClassTagExtensionsmapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)mapper
springboot序列化使用的是jackson,而自带的jackson版本较低,且不支持scala。
import com.fasterxml.jackson.databind.Module
import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule}
import org.springframework.context.annotation.{Bean, Configuration}
import lombok.extern.slf4j.Slf4j/*** https://blog.csdn.net/beibaozhou1656/article/details/100966023*/
@Configuration
class JacksonConfiguration {@Beandef defaultScalaModule(): Module = {// 暂没有办法加:ClassTagExtensionsDefaultScalaModule}
}
controller类
注意:@Resource()
(@Autowire
)使用方法。
import org.springframework.web.bind.annotation.{PostMapping, PutMapping, RequestBody, RequestMapping, RestController}
import lombok.extern.slf4j.Slf4j@RestController
@RequestMapping(Array("/v1"))
class BatchController @Resource()(batchService: BatchSaveService) {@PostMapping(Array("/batch/save"))def batchSave(@RequestBody tbls: java.util.List[Element]): Unit = {batchService.batch(tbls.asScala)}
}
配置文件值获取
application.properties,application.yml,application.yaml文件
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import javax.annotation.PostConstruct@Component
class EnvConfiguration() {
// 注意:要去除value=s"${}"的`s`。@Value(value = "${udf.kafka.consumer.krb5-conf}") var krb5Conf: String = _@Value(value = "${udf.kafka.topic}") var topic: String = _@PostConstructdef init(): Unit = {// 使用在post construct之后可以使用krb5Conf变量System.setProperty( ... )}def getTopic():String={topic
}
}
import lombok.extern.slf4j.Slf4j
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.springframework.kafka.annotation.KafkaListener
import org.springframework.stereotype.{Component}
import javax.annotation.Resource/*** kerberos整合kafka、springboot* https://blog.csdn.net/weixin_40496191/article/details/124056953* SpringBoot集成Kafka详解* https://blog.csdn.net/qq_20865839/article/details/13394898*/
@Component
class KafkaTableService @Resource()(service: CommonServiceImpl) extends Logging {val mapper = JsonUtils.getMapper
// 可以使用#{}在注解中使用被@Component的的方法。@KafkaListener(topics = Array("#{EnvConfiguration.getTopic()}"))def onMessage(record: ConsumerRecord[String, String]) = {// do nothing}
}
注意:
1、springboot打包必须使用spring-boot-maven-plugin
,不能使用gradle的shadowJar
(com.github.johnrengelman.shadow
)
正确的jar应如下目录结构:
2、idea中debug
将所有application.yml等配置文件放在test/resources目录下,可以避免jar中含有配置文件,但测试时候会发现找不到配置文件。如果此时在点击object前的run或者debug,不是以test
方式run的不会触发gradle的test
,不会有如下test目录和不会触发gradle resource copy任务,当然即使触发了也没用,因为此处我们直接run main方法,不是test任务,classpath不会包含build/resources/test
目录,只会包含build/resources/main
。
解决办法:
在idea启动参数添加如下,注意下resources/
以结尾,/
告知spring此路径是个目录,不是文件。
另使用--spring.config.additional-location=
也是可以的。
--spring.config.location=D:/projects/my-project/my-moudel/src/test/resources/
从而实现打包没有配置文件,但run springboot可以加载到test/resources配置文件。
3、无需设置main-class,springboot的插件设置。
4、生产环境启动 nohub java -jar xxx.jar 2>&1 &
5、jackson版本最好高于2.16.0
jackson-module-scala 官方文档:
6、java语言动态参数如下,入参使用可以直接使用sum(1)
,即一个参数也可以使用。
但scala是不行的。需要明确指定类型是Array
如下:
7、@Slf4j
注解无法使用,此注解应该被idea lombok插件并在编译添加如下添加代码:
解决很简单,手动添加如下代码即可:
import org.slf4j.Logger
// class 适用
val LOG: Logger = org.slf4j.LoggerFactory.getLogger(this.getClass)
// object 适用
val LOG: Logger = org.slf4j.LoggerFactory.getLogger(classOf[类名称])
8、
参考文章:
Spring Boot 实践折腾记
Scala篇:整合springboot