当前位置: 首页 > news >正文

【scala】使用gradle和scala构建springboot程序

零、版本说明:

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的shadowJarcom.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

相关文章:

  • 数字乡村战略实施:科技引领农村经济社会全面发展
  • ThreadPoolExecutor经典面试题
  • javaWeb项目-火车票订票信息系统功能介绍
  • 在Debian 11上安装GCC
  • 深度学习 - PyTorch基本流程 (代码)
  • 没学数模电可以玩单片机吗?
  • 【flutter】flutter基础总结1
  • 蓝桥杯备考随手记: practise01
  • iOS - Runtime-isa详解(位域、union(共用体)、位运算)
  • 【嵌入式开发 Linux 常用命令系列 1.4 -- grep -Ev 反向搜索】
  • golang 使用redis
  • Sentinel入门
  • Linux文件IO(2):使用标准IO进行文件的打开、关闭、读写、流定位等相关操作
  • 基于Java在线考试系统系统设计与实现(源码+部署文档)
  • 算法---动态规划练习-6(地下城游戏)
  • [iOS]Core Data浅析一 -- 启用Core Data
  • [数据结构]链表的实现在PHP中
  • 【391天】每日项目总结系列128(2018.03.03)
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Apache Spark Streaming 使用实例
  • CSS中外联样式表代表的含义
  • FineReport中如何实现自动滚屏效果
  • interface和setter,getter
  • 给github项目添加CI badge
  • 基于web的全景—— Pannellum小试
  • 检测对象或数组
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 聚类分析——Kmeans
  • 删除表内多余的重复数据
  • 数据仓库的几种建模方法
  • 算法系列——算法入门之递归分而治之思想的实现
  • 我建了一个叫Hello World的项目
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #13 yum、编译安装与sed命令的使用
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #微信小程序(布局、渲染层基础知识)
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (pytorch进阶之路)扩散概率模型
  • (二)WCF的Binding模型
  • (二十三)Flask之高频面试点
  • (七)c52学习之旅-中断
  • (七)理解angular中的module和injector,即依赖注入
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)原始图像数据和PDF中的图像数据
  • .naturalWidth 和naturalHeight属性,
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .net core控制台应用程序初识
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET6 命令行启动及发布单个Exe文件
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @font-face 用字体画图标
  • @JoinTable会自动删除关联表的数据