专栏名称: 逸言
文学与软件,诗意地想念。
目录
相关文章推荐
OSC开源社区  ·  继V3之后,沐曦GPU再完成DeepSeek ... ·  昨天  
码农翻身  ·  漫画 | ... ·  昨天  
码农翻身  ·  为何 Linus ... ·  2 天前  
OSC开源社区  ·  DeepSeek-V3满血版在国产沐曦GPU ... ·  3 天前  
51好读  ›  专栏  ›  逸言

在Scala项目中使用Spring Cloud

逸言  · 公众号  · 程序员  · 2018-02-26 08:38

正文

标签 | Scala 微服务

作者 | 张逸


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

由于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语言库的依赖:

1
2
3
4
5
<dependency>
   <groupId>org.scala-langgroupId>
   <artifactId>scala-libraryartifactId>
   <version>2.11.11version>
dependency>

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

1
2
3
4
5
6
<dependency>
   <groupId>org.scalatestgroupId>
   <artifactId>scalatest_2.11artifactId>
   <version>3.0.4version>
   <scope>testscope>
dependency>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<build>
       <plugins>
           <plugin>
               <groupId>org.springframework.bootgroupId>
               <artifactId>spring-boot-maven-pluginartifactId>
           plugin>
           <plugin>
               <groupId>org.codehaus.mojogroupId>
               <artifactId>build-helper-maven-pluginartifactId>
               <version>1.10version>
               <executions>
                   <execution>
                       <id>add-sourceid>
                       <phase>generate-sourcesphase>
                       <goals>
                           <goal>add-sourcegoal>
                       goals>
                       <configuration>
                           <sources>
                               <source>src/main/scalasource>
                           sources>
                       configuration>
                   execution>
                   <execution>
                       <id>add-test-sourceid>
                       <phase>generate-test-sourcesphase>
                       <goals>
                           <goal>add-test-sourcegoal>
                       goals>
                       <configuration>
                           <sources>
                               <source>src/test/scalasource>
                           sources>
                       configuration>
                   execution>
               executions>
           plugin>
           <plugin >
               <groupId>net.alchim31.mavengroupId>
               <artifactId>scala-maven-pluginartifactId>
               <version>3.2.2version>
               <executions>
                   <execution>
                       <goals>
                           <goal>compilegoal>
                           <goal>testCompilegoal>
                       goals>
                   execution>
               executions>
           plugin>
       plugins>
   build>

Spring的语法

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

1
2
3
4
5
6
7
@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 类型,例如:

1
2
3
4
5
6
7
8
9
@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的支持模块:

1
2
3
4
5
<dependency>
   <groupId>com.fasterxml.jackson.modulegroupId>
   <artifactId>jackson-module-scala_2.11artifactId>
   <version>2.8.7version>
dependency>

添加WebConfig

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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,如下图所示:

在Scala中的定义如下所示:

1
2
3
4
5
6
7
8
9
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], dataType: String) extends ConditionExpression

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

1
2
3
4
5
6
7
8
9
10
11
@JsonTypeInfo(
 use = JsonTypeInfo.Id.NAME,
 include = JsonTypeInfo.As.PROPERTY,
 property = "type")






请到「今天看啥」查看全文