在Scala项目中使用Spring Cloud

简介: 在Scala项目中使用Spring Cloud

特别说明:本文包含大量代码片段,若要获得更好阅读观感,请点击文末“阅读原文”或访问我的博客。

由于Scala本身属于JVM下的语言,因此它能够较好地与Java项目融合在一起。在Scala中调用Java库,基本上与在Java中调用Java库的方式是相同的(反过来则未必,必将Java没有Scala中独有的语法糖)。因此,在Scala中可以非常方便地调用Spring Cloud,使其支持Spring Cloud提供的微服务基础设施,例如Eureka、Feign以及Spring Boot等。

不过仍然有几点需要注意,这些方面包括:

  • Maven依赖
  • Spring的语法
  • Json的序列化

Maven依赖


在Scala项目中,如果仍然使用Maven管理依赖,则它与在Java项目中添加Spring Boot依赖几乎完全相同,不同在于项目要支持Scala,需要添加对Scala语言库的依赖:

<dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-library</artifactId>
    <version>2.11.11</version>
</dependency>

要支持用ScalaTest编写单元测试,则还需要添加:

<dependency>
    <groupId>org.scalatest</groupId>
    <artifactId>scalatest_2.11</artifactId>
    <version>3.0.4</version>
    <scope>test</scope>
</dependency>

同时,添加对编译Scala代码的插件依赖:

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/main/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                    <execution>
                        <id>add-test-source</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>add-test-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/test/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


Spring的语法


Scala语言中照样可以使用Java的Annotation,因此scala项目的Application,可以这样实现:

@SpringBootApplication
@EnableDiscoveryClient
class SqlEngineApplication
object SqlEngineApplication extends App {
  SpringApplication.run(classOf[SqlEngineApplication], args: _*)
}

注意,Spring Cloud以及Spring Boot提供的annotation是运用在类上面的,而Scala可以运用的Application则可以直接定义为与类同名的object。

而对于Spring Boot的Controller,在语法上有少许差异,即在值中要使用Scala的Array类型,例如:

@RestController
@RequestMapping(Array("/"))
class SqlStatementController extends SqlGenerator {
  @RequestMapping(value = Array("/sql"), method = Array(GET))
  def getSql:String = ???
  @RequestMapping(value = Array("/sql"), method = Array(POST))
  def generateSql(@RequestBody request: GenerateSqlRequest): String = ???
}


Json的序列化


添加依赖


Spring Boot使用Jackson作为Json的序列化支持,若要在Scala项目也要使用Jackson,则需要添加jackson对scala的支持模块:

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-scala_2.11</artifactId>
    <version>2.8.7</version>
</dependency>


添加WebConfig


同时还需要添加WebConfig,告诉Spring Boot选择Scala Module对对象进行映射:

@Configuration
class WebConfig extends WebMvcConfigurerAdapter {
  override def configureMessageConverters(converters: java.util.List[HttpMessageConverter[_]]): Unit =
  converters.add(jackson2HttpMessageConverter())
  @Bean
  def jackson2HttpMessageConverter(): MappingJackson2HttpMessageConverter =
    new MappingJackson2HttpMessageConverter(objectMapper())
  @Bean
  def objectMapper(): ObjectMapper =
    new ObjectMapper() {
      setVisibility(PropertyAccessor.FIELD, Visibility.ANY)
      registerModule(DefaultScalaModule)
    }
}


对多态的支持


客户端发过来的Request中,包含了一棵表达式树。这棵树的节点分为两种类型:

  • Condition Group
  • Condition

Condition Group作为根节点,可以递归嵌套Condition Group和Condition,如下图所示:

image.png

在Scala中的定义如下所示:

case class GenerateSqlRequest(sqlTemplateName: String, criteria: Option[ConditionGroup] = None, groupBy: List[GroupByField] = Nil)
abstract class ConditionExpression {
  def evaluate: String
}
case class ConditionGroup(logicOperator: String, conditions: List[ConditionExpression]) extends ConditionExpression 
case class Condition(fieldName: String, operator: String, values: List[String

GenerateSqlRequest中包含的criteria属性的类型就是前面提及的表达式树,它对应的Json结构需要支持Json类型的多态,即前面代码所示的ConditionExpression抽象类型,子类ConditionGroupCondition拥有不同的属性定义。要支持这种Json的多态,则必须在抽象类型ConditionExpression上添加如下annotation:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "type")
@JsonSubTypes(Array(
  new Type(value = classOf[Condition], name = "condition"),
  new Type(value = classOf[ConditionGroup], name = "group")
))
abstract class ConditionExpression {
  def evaluate: String
}

即使ConditionGroupCondition子类没有定义type属性,在对应的Json结构中也需要添加type,并给出符合上述代码定义的值:

{
    "sqlTemplateName": "name1",
    "criteria": {
        "type": "group",
        "logicOperator": "and",
        "conditions": [
          {
             "type": "condition",
            "fieldName": "sales",
            "operator": "between",
            "values": ["3", "100"],
            "dataType": "Integer"
          },
          {
            "type": "group",
            "logicOperator": "or",
            "conditions": [
              {
                      "type": "condition",
                  "fieldName": "brand",
                  "operator": "=",
                  "values": ["apple"],
                  "dataType": "String"
              },
              {
                      "type": "condition",
                  "fieldName": "location",
                  "operator": "in",
                  "values": ["Sichuan", "Shanghai"],
                  "dataType": "String"
              }
            ]
          }
      ]
    },
    "groupBy": [
      {
        "fieldName": "location"
      },
      {
        "fieldName": "brand"
      }
    ]
}

注意,这种对多态的支持不仅仅是针对Scala,同样支持Java:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Condition.class, name = "condition"),
    @JsonSubTypes.Type(value = ConditionGroup.class, name = "group") }
)
public abstract class ConditionExpression {}

一旦在Scala项目中使用了Spring Boot以及Spring Cloud,在编译打包后,使用方式和普通Java项目结合Spring Boot与Spring Cloud是完全一样的,毕竟scala编译后生成的就是一个不同的Jar包。

相关文章
|
5天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
16 2
|
1月前
|
设计模式 前端开发 Java
Spring MVC——项目创建和建立请求连接
MVC是一种软件架构设计模式,将应用分为模型、视图和控制器三部分。Spring MVC是基于MVC模式的Web框架,通过`@RequestMapping`等注解实现URL路由映射,支持GET和POST请求,并可传递参数。创建Spring MVC项目与Spring Boot类似,使用`@RestController`注解标记控制器类。
34 1
Spring MVC——项目创建和建立请求连接
|
1月前
|
Java 关系型数据库 MySQL
Maven——创建 Spring Boot项目
Maven 是一个项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,简化了项目的构建和管理过程。其核心功能包括项目构建和依赖管理,支持创建、编译、测试、打包和发布项目。Maven 仓库分为本地仓库和远程仓库,远程仓库包括中央仓库、私服和其他公共库。此外,文档还介绍了如何创建第一个 SpringBoot 项目并实现简单的 HTTP 请求响应。
115 1
Maven——创建 Spring Boot项目
|
1月前
|
Java 关系型数据库 MySQL
如何使用 maven 创建一个 Spring Boot项目
Maven 是一个强大的项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,提高开发效率。其核心功能包括项目构建和依赖管理。项目构建支持编译、测试、打包和发布等流程,而依赖管理则通过中央仓库、本地仓库和私有服务器获取和管理项目依赖。示例中展示了如何创建第一个 SpringBoot 项目并实现简单接口。
24 1
如何使用 maven 创建一个 Spring Boot项目
|
1月前
|
JSON SpringCloudAlibaba Java
Springcloud Alibaba + jdk17+nacos 项目实践
本文基于 `Springcloud Alibaba + JDK17 + Nacos2.x` 介绍了一个微服务项目的搭建过程,包括项目依赖、配置文件、开发实践中的新特性(如文本块、NPE增强、模式匹配)以及常见的问题和解决方案。通过本文,读者可以了解如何高效地搭建和开发微服务项目,并解决一些常见的开发难题。项目代码已上传至 Gitee,欢迎交流学习。
125 1
Springcloud Alibaba + jdk17+nacos 项目实践
|
1月前
|
Java 应用服务中间件 Android开发
Eclipse创建Spring项目
本文介绍了在Eclipse中创建Spring项目的步骤,包括如何配置Tomcat服务器、创建项目、部署项目到Tomcat以及添加Spring框架所需的JAR包。
53 1
Eclipse创建Spring项目
|
1月前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?
|
1月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
53 2
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
167 2
|
1月前
|
前端开发 安全 Java
【Spring】Spring Boot项目创建和目录介绍
【Spring】Spring Boot项目创建和目录介绍
84 2