clyoudu/spring-boot-scala-demo
scala
?是Java
不好用还是不够难?可能仅仅是想装逼?scala
写spark
程序,所以有scala
和java
混合开发的需求,干脆研究一下纯scala
能不能搭建这样的开发环境。scala
的方式,因为scala
的环境下无法完美使用mybatis + druid
,当然也可以实现,但是映射、配置、事务等代码不是很优雅,mybatis-scala
在maven
仓库中只更新到scala 2.11
,github
上也不是很活跃,应该是需求量不大,说不定有很多坑,既然是java scala
混合使用,不妨用java
来实现ORM
相关代码。scala
一般使用java Persistence API
来实现数据库操作的。mybatis-scala
相关连接:github mybatis/scala;mvnrepository;mybatis-scala-core scala
实现ORM
,包括事务等。IDE
:IntelliJ IDEA 2017
JDK
:1.8
OS
:Win10
BT
:Maven
scala
:2.12.4
spring boot
:2.0.1.RELEASE
maven
:3
oracle
:11.2.0.4
可以直接从IDEA
创建,也可以从https://start.spring.io/创建一个基础的项目,这里使用IDEA
直接创建。
首先确保有Spring boot
插件:
然后创建一个简单的spring boot
项目:
这里根据自己的需求选择,也可以不选后面自己写。
如果已有maven
环境,可以删除mvn
相关的文件和文件夹。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.1.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Finchley.RC1spring-cloud.version>
<scala.version>2.12.4scala.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.3.1version>
dependency>
<dependency>
<groupId>org.scala-langgroupId>
<artifactId>scala-libraryartifactId>
<version>${scala.version}version>
dependency>
<dependency>
<groupId>com.oraclegroupId>
<artifactId>ojdbc6artifactId>
<version>11.2.0.4version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.9version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.47version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>4.1.3version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>net.alchim31.mavengroupId>
<artifactId>scala-maven-pluginartifactId>
<version>3.3.2version>
<executions>
<execution>
<id>compile-scalaid>
<phase>compilephase>
<goals>
<goal>add-sourcegoal>
<goal>compilegoal>
goals>
execution>
<execution>
<id>test-compile-scalaid>
<phase>test-compilephase>
<goals>
<goal>add-sourcegoal>
<goal>testCompilegoal>
goals>
execution>
executions>
<configuration>
<recompileMode>incrementalrecompileMode>
<scalaVersion>${scala.version}scalaVersion>
<args>
<arg>-deprecationarg>
args>
<jvmArgs>
<jvmArg>-Xms64mjvmArg>
<jvmArg>-Xmx1024mjvmArg>
jvmArgs>
configuration>
plugin>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.2version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/mybatis-generator-config.xml
configurationFile>
<overwrite>trueoverwrite>
<verbose>trueverbose>
configuration>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.42version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
dependencies>
plugin>
plugins>
build>
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@192.168.0.193:1521:single
spring.datasource.username=scott
spring.datasource.password=tiger
#连接池配置
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
#连接等待超时时间
spring.datasource.maxWait=60000
#配置隔多久进行一次检测(检测可以关闭的空闲连接)
spring.datasource.timeBetweenEvictionRunsMillis=60000
#配置连接在池中的最小生存时间
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
CREATE TABLE "SYSTEM"."USER" (
"ID" NVARCHAR2(36) NOT NULL ENABLE,
"USERNAME" NVARCHAR2(255) NOT NULL ENABLE,
"PASSWORD" NVARCHAR2(255) NOT NULL ENABLE,
"REGISTER_TIME" DATE NOT NULL ENABLE,
PRIMARY KEY ("ID")
) NOCOMPRESS;
CREATE TABLE "SYSTEM"."USER_OPERATION_HISTORY" (
"ID" NVARCHAR2(36) NOT NULL ENABLE,
"USER_ID" NVARCHAR2(36) NOT NULL ENABLE,
"USERNAME" NVARCHAR2(255) NOT NULL ENABLE,
"OPERATION_TYPE" NVARCHAR2(255) NOT NULL ENABLE,
"OPERATE_TIME" DATE NOT NULL ENABLE,
PRIMARY KEY ("ID")
) NOCOMPRESS;
<generatorConfiguration>
<classPathEntry location="C:/Users/vabsh/.m2/repository/com/oracle/ojdbc6/11.2.0.4/ojdbc6-11.2.0.4.jar" />
<context id="test">
<commentGenerator >
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="false" />
commentGenerator>
<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"
connectionURL="jdbc:oracle:thin:@192.168.0.193:1521:single"
userId="system"
password="single" />
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
javaTypeResolver>
<javaModelGenerator targetPackage="github.chenlei.springbootscalademo.entity"
targetProject="C:\github\spring-boot-scala-demo\src\main\java" >
<property name="enableSubPackages" value="false"/>
javaModelGenerator>
<sqlMapGenerator targetPackage="mapper"
targetProject="C:\github\spring-boot-scala-demo\src\main\resources" >
<property name="enableSubPackages" value="false" />
sqlMapGenerator>
<javaClientGenerator targetPackage="github.chenlei.springbootscalademo.dao"
targetProject="C:\github\spring-boot-scala-demo\src\main\java" type="XMLMAPPER" >
<property name="enableSubPackages" value="false" />
javaClientGenerator>
<table schema="SYSTEM"
tableName="USER_OPERATION_HISTORY"
enableCountByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
enableUpdateByExample="false"/>
<table schema="SYSTEM"
tableName="USER"
enableCountByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
enableUpdateByExample="false"/>
context>
generatorConfiguration>
执行mvn mybatis-generator:generate
或点击右侧工具栏Maven Projects > spring-boot-scala-demo > Plugins > mybatis-generator > mybatis-generator:generate
,mapper mapperxml entity
会自动创建在对应的包里。
后续的一些小改动:
因为USER
是oracle
保留字,需要在mapperxml
将USER
替换为"USER"
。
在XxxMapper
类上添加@Mapper
注解。
和spring boot
配置数据源类似,只不过用的scala
实现:
package github.chenlei.springbootscalademo.config
import java.sql.SQLException
import javax.sql.DataSource
import com.alibaba.druid.pool.DruidDataSource
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.context.annotation.{Bean, Configuration, Primary}
/**
* Create by IntelliJ IDEA
*
* @Author chenlei
* @DateTime 2018/5/7 10:59
* @Description DruidDataSource
*/
@Configuration
@Primary
class DruidDataSourceConfig extends DataSourceProperties {
private val LOGGER = LoggerFactory.getLogger(classOf[DruidDataSourceConfig])
@Value("${spring.datasource.url}")
private val dbUrl : String = null
@Value("${spring.datasource.username}")
private val username : String = null
@Value("${spring.datasource.password}")
private val password : String = null
@Value("${spring.datasource.driverClassName}")
private val driverClassName : String = null
@Value("${spring.datasource.initialSize}")
private val initialSize : Integer = 0
@Value("${spring.datasource.minIdle}")
private val minIdle : Integer = 0
@Value("${spring.datasource.maxActive}")
private val maxActive : Integer = 0
@Value("${spring.datasource.maxWait}")
private val maxWait : Long = 0
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private val timeBetweenEvictionRunsMillis : Long = 0
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private val minEvictableIdleTimeMillis = 0
@Value("${spring.datasource.validationQuery}")
private val validationQuery : String = null
@Value("${spring.datasource.testWhileIdle}")
private val testWhileIdle : Boolean = false
@Value("${spring.datasource.testOnBorrow}")
private val testOnBorrow : Boolean = false
@Value("${spring.datasource.testOnReturn}")
private val testOnReturn : Boolean = false
@Value("${spring.datasource.poolPreparedStatements}")
private val poolPreparedStatements : Boolean = false
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private val maxPoolPreparedStatementPerConnectionSize : Integer = 0
@Value("${spring.datasource.filters}")
private val filters : String = null
@Value("{spring.datasource.connectionProperties}")
private val connectionProperties : String = null
@Bean //声明其为Bean实例
def dataSource: DataSource = {
val datasource: DruidDataSource = new DruidDataSource
datasource.setUrl(this.dbUrl)
datasource.setUsername(username)
datasource.setPassword(password)
datasource.setDriverClassName(driverClassName)
//configuration
datasource.setInitialSize(initialSize)
datasource.setMinIdle(minIdle)
datasource.setMaxActive(maxActive)
datasource.setMaxWait(maxWait)
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis)
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis)
datasource.setValidationQuery(validationQuery)
datasource.setTestWhileIdle(testWhileIdle)
datasource.setTestOnBorrow(testOnBorrow)
datasource.setTestOnReturn(testOnReturn)
datasource.setPoolPreparedStatements(poolPreparedStatements)
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize)
try
datasource.setFilters(filters)
catch {
case e: SQLException =>
LOGGER.error("druid configuration initialization filter", e)
}
datasource.setConnectionProperties(connectionProperties)
datasource
}
}
package github.chenlei.springbootscalademo.config
import javax.servlet.{Filter, Servlet}
import com.alibaba.druid.support.http.{StatViewServlet, WebStatFilter}
import org.springframework.boot.web.servlet.{FilterRegistrationBean, ServletRegistrationBean}
import org.springframework.context.annotation.{Bean, Configuration}
/**
* Create by IntelliJ IDEA
*
* @Author chenlei
* @DateTime 2018/5/7 11:07
* @Description DruidMonitorConfig
*/
@Configuration
class DruidMonitorConfig {
/**
* 注册ServletRegistrationBean
*
* @return
*/
@Bean
def registrationBean: ServletRegistrationBean[StatViewServlet] = {
val bean : ServletRegistrationBean[StatViewServlet] = new ServletRegistrationBean(new StatViewServlet, "/druid/*")
/** 初始化参数配置,initParams **/
//白名单
bean.addInitParameter("allow", "127.0.0.1") //多个ip逗号隔开
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
//bean.addInitParameter("deny", "192.168.1.73");
//登录查看信息的账号密码.
bean.addInitParameter("loginUsername", "admin")
bean.addInitParameter("loginPassword", "123456")
//是否能够重置数据.
bean.addInitParameter("resetEnable", "false")
bean
}
/**
* 注册FilterRegistrationBean
*
* @return
*/
@Bean
def druidStatFilter: FilterRegistrationBean[_ <: Filter] = {
val bean = new FilterRegistrationBean(new WebStatFilter)
//添加过滤规则.
bean.addUrlPatterns("/*")
//添加不需要忽略的格式信息.
bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*")
bean
}
}
package github.chenlei.springbootscalademo.config
import java.util.Properties
import javax.sql.DataSource
import com.github.pagehelper.PageHelper
import org.apache.ibatis.plugin.Interceptor
import org.apache.ibatis.session.SqlSessionFactory
import org.mybatis.spring.{SqlSessionFactoryBean, SqlSessionTemplate}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.{Bean, Configuration}
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import org.springframework.jdbc.datasource.DataSourceTransactionManager
import org.springframework.transaction.annotation.TransactionManagementConfigurer
/**
* Create by IntelliJ IDEA
*
* @Author chenlei
* @DateTime 2018/5/7 11:14
* @Description MybatisConfig
*/
@Configuration
class MybatisConfig extends TransactionManagementConfigurer{
@Autowired
private val dataSource : DataSource = null
@Bean(name = Array("sqlSessionFactory"))
def sqlSessionFactoryBean: SqlSessionFactory = {
val bean = new SqlSessionFactoryBean
bean.setDataSource(dataSource)
bean.setTypeAliasesPackage("github.chenlei.springbootscalademo.entity")
//分页插件,插件无非是设置mybatis的拦截器
val pageHelper = new PageHelper
val properties = new Properties
properties.setProperty("offsetAsPageNum", "true")
properties.setProperty("rowBoundsWithCount", "true")
properties.setProperty("reasonable", "true")
pageHelper.setProperties(properties)
//添加插件
bean.setPlugins(Array[Interceptor](pageHelper))
//添加XML目录
val resolver = new PathMatchingResourcePatternResolver
try { //设置xml扫描路径
bean.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"))
bean.getObject
} catch {
case e: Exception =>
throw new RuntimeException("sqlSessionFactory init fail", e)
}
}
@Bean(name = Array("sqlSessionTemplate"))
def sqlSessionTemplate(sqlSessionFactory: SqlSessionFactory) = new SqlSessionTemplate(sqlSessionFactory)
@Bean(name = Array("transactionManager"))
override def annotationDrivenTransactionManager() = new DataSourceTransactionManager(dataSource)
}
很多方法可以在一个BaseService
里面定义和实现,因为scala
可以重写field
,所以结合泛型和字段重写能轻松实现模板方法,减少很多代码量,具体参考:github.chenlei.springbootscalademo.service
和spring boot
实现类似,依然改成scala
实现,具体参考:github.chenlei.springbootscalademo.controller
使用postman
访问创建用户接口:http://localhost:8080/user/create
访问druid monitor
:http://localhost:8080/druid
,admin/123456