IDEA + maven + spring boot + scala + oracle + mybatis + druid scala java混合开发环境搭建

IDEA + maven + spring boot + scala + oracle + mybatis + druid scala java混合开发环境搭建

demo地址

clyoudu/spring-boot-scala-demo

为什么要用scala

  • 为什么要用scala?是Java不好用还是不够难?可能仅仅是想装逼?
  • 其实是项目中要用scalaspark程序,所以有scalajava混合开发的需求,干脆研究一下纯scala能不能搭建这样的开发环境。
  • 最后放弃了完全使用scala的方式,因为scala的环境下无法完美使用mybatis + druid,当然也可以实现,但是映射、配置、事务等代码不是很优雅,mybatis-scalamaven仓库中只更新到scala 2.11github上也不是很活跃,应该是需求量不大,说不定有很多坑,既然是java scala混合使用,不妨用java来实现ORM相关代码。
  • scala一般使用java Persistence API来实现数据库操作的。
  • mybatis-scala相关连接:github mybatis/scalamvnrepositorymybatis-scala-core
    ,这里有很多示例代码,看了基本能用scala实现ORM,包括事务等。

环境

  • IDEIntelliJ IDEA 2017
  • JDK1.8
  • OSWin10
  • BTMaven
  • scala2.12.4
  • spring boot2.0.1.RELEASE
  • maven3
  • oracle11.2.0.4

初始化spring boot项目

可以直接从IDEA创建,也可以从https://start.spring.io/创建一个基础的项目,这里使用IDEA直接创建。

首先确保有Spring boot插件:
这里写图片描述

然后创建一个简单的spring boot项目:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述
这里根据自己的需求选择,也可以不选后面自己写。

这里写图片描述

这里写图片描述

如果已有maven环境,可以删除mvn相关的文件和文件夹。

添加依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Finchley.RC1</spring-cloud.version>
    <scala.version>2.12.4</scala.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- spring boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!-- scala -->
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>
    </dependency>

    <!-- database -->
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>11.2.0.4</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.9</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>4.1.3</version>
    </dependency>

    <!-- log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

添加插件

<build>
    <plugins>
        <!-- spring boot -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <!-- scala compiler -->
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.3.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>
                    <jvmArg>-Xms64m</jvmArg>
                    <jvmArg>-Xmx1024m</jvmArg>
                </jvmArgs>
            </configuration>
        </plugin>

        <!-- mybatis generator -->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.2</version>
            <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/mybatis-generator-config.xml
                </configurationFile>
                <overwrite>true</overwrite>
                <verbose>true</verbose>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.42</version>
                </dependency>
                <dependency>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                    <version>3.4.5</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

application.properties

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;

配置/resources/generator/mybatis-generator-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>

    <!-- 指定数据连接驱动jar地址 -->
    <classPathEntry location="C:/Users/vabsh/.m2/repository/com/oracle/ojdbc6/11.2.0.4/ojdbc6-11.2.0.4.jar" />

    <!-- 一个数据库一个context -->
    <context id="test">
        <!-- 注释 -->
        <commentGenerator >
            <property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
            <property name="suppressDate" value="false" /> <!-- 是否生成注释代时间戳-->
        </commentGenerator>

        <!-- jdbc连接 -->
        <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"
                        connectionURL="jdbc:oracle:thin:@192.168.0.193:1521:single"
                        userId="system"
                        password="single" />

        <!-- 类型转换 -->
        <javaTypeResolver>
            <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 生成实体类地址 -->
        <javaModelGenerator targetPackage="github.chenlei.springbootscalademo.entity"
                            targetProject="C:\github\spring-boot-scala-demo\src\main\java" >
            <!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否针对string类型的字段在set的时候进行trim调用 -->
            <!-- <property name="trimStrings" value="true"/>   -->
        </javaModelGenerator>

        <!-- 生成mapxml文件 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="C:\github\spring-boot-scala-demo\src\main\resources" >
            <!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!-- 生成mapxml对应client,也就是接口dao -->
        <javaClientGenerator targetPackage="github.chenlei.springbootscalademo.dao"
                             targetProject="C:\github\spring-boot-scala-demo\src\main\java" type="XMLMAPPER" >
            <!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <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:generatemapper mapperxml entity会自动创建在对应的包里。

后续的一些小改动:
因为USERoracle保留字,需要在mapperxmlUSER替换为"USER"
XxxMapper类上添加@Mapper注解。

DataSource和Mybatis配置

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)
}

Service

很多方法可以在一个BaseService里面定义和实现,因为scala可以重写field,所以结合泛型和字段重写能轻松实现模板方法,减少很多代码量,具体参考:github.chenlei.springbootscalademo.service

Controller

spring boot实现类似,依然改成scala实现,具体参考:github.chenlei.springbootscalademo.controller

启动并测试

使用postman访问创建用户接口:http://localhost:8080/user/create
这里写图片描述
这里写图片描述
这里写图片描述

访问druid monitorhttp://localhost:8080/druidadmin/123456
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/cl_yd/article/details/80204237