介绍下scala如何配合spring boot框架进行项目开发,由于scala和java一样都是运行在jvm中的,所以和java一样,scala配合spring boot使用几乎和java一样,由于java和scala各有各的特性,处理的场景不同(比如scala天生适合集合的处理),所以有的时候还是需要用java来处理较为方便,所以该骨架中将java和scala一起进行混编,最终打成jar包提供部署。
- 软件版本
- jdk
1.7.0_79 - scala
2.10.5(使用该版本是为了配合公司spark环境的版本) - maven
3.3.9(使用gradle一样可以管理依赖和打包)
- jdk
- pom文件
由于使用java和scala进行混编,所以需要在pom中同时加入打包java和scala的插件,具体如下:
<build> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>3.2.2</version> <executions> <execution> <id>compile-scala</id> <phase>compile</phase> <goals> <goal>add-source</goal> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile-scala</id> <phase>test-compile</phase> <goals> <goal>add-source</goal> <goal>testCompile</goal> </goals> </execution> </executions> <configuration> <recompileMode>incremental</recompileMode> <scalaVersion>${scala.version}</scalaVersion> <args> <arg>-deprecation</arg> </args> <jvmArgs> <jvmArgs>-Xmx8192m</jvmArgs> <jvmArgs>-Xms1024m</jvmArgs> </jvmArgs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.0-SNAPSHOT</version> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
其中是shade plugin是用来打包java的,scala-maven-plugin是用来打包scala的。 - 配置文件读取
由于scala‘隐藏’了getter和setter方法,导致无法使用prefix的方法注入(只能使用@Value注解,但是这个注解不是很方便),所以我们这边还是使用java来读取配置文件,代码如下:package com.jthink.teemo.properties; import org.springframework.boot.context.properties.ConfigurationProperties; /** * jthink company * * @author jthink * @version 0.0.1 * @desc 任务相关的task * @date 2017-01-11 16:17:27 */ @ConfigurationProperties(prefix = "spring.spark.task") public class TaskProperties { // spark job名字 private String name; // hdfs路径 private String srcPath; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSrcPath() { return srcPath; } public void setSrcPath(String srcPath) { this.srcPath = srcPath; } }
启动类:
package com.jthink.teemo.launcher import com.jthink.teemo.properties.TaskProperties import org.slf4j.{Logger, LoggerFactory} import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.ConfigurableApplicationContext import org.springframework.context.annotation.{ComponentScan, PropertySource} /** * jthink company * * 项目启动器 * * @author jthink * @version 0.0.1 */ @SpringBootApplication @ComponentScan(basePackages = Array("com.jthink.teemo")) //@PropertySource(Array("file:/the/file/location/teemo/teemo.properties")) @PropertySource(Array("classpath:properties/teemo.properties")) @EnableConfigurationProperties(Array(classOf[TaskProperties])) class Launcher { } object Launcher { private val LOGGER: Logger = LoggerFactory.getLogger(classOf[Launcher]) def main(args: Array[String]): Unit = { val context: ConfigurableApplicationContext = new SpringApplicationBuilder(classOf[Launcher]).run(args: _*) LOGGER.info("teemo start successfully") } }
如果这个时候run,或者打包启动,会发现会报错,报错原因为@Repeatable不存在,查原因该注解在jdk1.8才会出现,spring-boot是基于jdk1.8进行打包,解决方法是更换jdk为1.8,但是这边提供一个不需要修改版本的方法,由于@Repeatable在@PropertySource会出现,所以将PropertySource.java覆写,具体如下:
package org.springframework.context.annotation; import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PropertySource { String name() default ""; String[] value(); boolean ignoreResourceNotFound() default false; }
启动正常。 - 如何使用spring data jpa 或者 hbase、mongo等java api
在scala中新建类,在class上打annotation,和java相同,不再赘述 - scala java+spring boot编写spark代码骨架
见github:https://github.com/JThink/teemo