您的位置:首页 > 编程语言 > Java开发

Springboot+Kotlin+Jpa集成项目

2017-11-09 00:00 483 查看
项目集成

使用的工具:IDEA,MAMP,Navicat,Postman

1.创建项目





2.项目pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>

<groupId>com.socene</groupId>
<artifactId>kotlin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>kotlin-demo</name>
<description>Demo project for Spring Boot</description>

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

<properties>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<kotlin.version>1.1.51</kotlin.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--代替tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--kotlin-->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
<!--druid的配置-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.5</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.35</version>
</dependency>
<!--桥接器-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--swagger api 模板-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifac
7fe1
tId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
<jvmTarget>1.8</jvmTarget>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

</project>

3.application.yml

spring:
profiles:
active: dev
http:
encoding:  #解决乱码
enabled: true
force: true
charset: utf-8

4.application-dev.yml

spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
initial-size: 1
max-active: 20
filters: stat,wall,log4j
driver-class-name: com.mysql.jdbc.Driver
stat-view-servlet:  # http://localhost:port/path/druid/index.html 管理密码
login-username: root
login-password: root
jpa:
generate-ddl: true
hibernate:
ddl-auto: update
open-in-view: false
show-sql: true

swagger-enable: true #控制swagger api文档配置

5.jpa配置

package com.socene.kotlin.config

import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.transaction.annotation.EnableTransactionManagement

/* *
*Created by: Sorata 2017/11/9 0009 上午 9:55
*
*/
@Configuration
@EnableJpaRepositories(basePackages = arrayOf("com.socene.kotlin.dao")) //repository包
@EntityScan(basePackages = arrayOf("com.socene.kotlin.entity"))//实体包
@EnableTransactionManagement
class JpaConfig

6.转换器

package com.socene.kotlin.config

import com.alibaba.fastjson.serializer.SerializerFeature
import com.alibaba.fastjson.support.config.FastJsonConfig
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import java.nio.charset.Charset

/**
*Created by: Sorata 2017/9/9 下午4:18
*
*/
@Configuration
class WebConfig {

@Bean(name = arrayOf("fastJsonHttpMessageConverter4"))
fun fastJsonHttpMessageConverter4(): FastJsonHttpMessageConverter4 {
val converter = FastJsonHttpMessageConverter4()

converter.supportedMediaTypes = arrayListOf(
MediaType.APPLICATION_JSON_UTF8,
MediaType(MediaType.TEXT_HTML, Charset.forName("UTF-8")),
MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")),
MediaType(MediaType.APPLICATION_FORM_URLENCODED, Charset.forName("UTF-8")),
MediaType.MULTIPART_FORM_DATA
)

val config = FastJsonConfig()
config.charset = Charset.forName("UTF-8")
config.setSerializerFeatures(
SerializerFeature.PrettyFormat,
// SerializerFeature.WriteClassName,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.WriteNullNumberAsZero,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullStringAsEmpty
)
//   config.dateFormat = "yyyyMMddHHmmss"
converter.fastJsonConfig = config
return converter
}
}

7.MVCConfig.kt

package com.socene.kotlin.config

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter

/**
*Created by: Sorata 2017/9/9 下午4:10
*
*/
@Configuration
class WebMvcConfiguration @Autowired constructor(@Qualifier("fastJsonHttpMessageConverter4") val fastConverter: FastJsonHttpMessageConverter4) : WebMvcConfigurerAdapter() {

override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>?) {
converters?.add(fastConverter)
super.configureMessageConverters(converters)
}

override fun addResourceHandlers(registry: ResourceHandlerRegistry?) {
super.addResourceHandlers(registry)
registry?.addResourceHandler("/**")?.addResourceLocations("classpath:/static/")
registry?.addResourceHandler("swagger-ui.html")
?.addResourceLocations("classpath:/META-INF/resources/")
registry?.addResourceHandler("/webjars/**")
?.addResourceLocations("classpath:/META-INF/resources/webjars/")
}
}

8.swagger-ui文档配置

package com.socene.kotlin.config

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import springfox.documentation.builders.ApiInfoBuilder
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.service.ApiInfo
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.swagger2.annotations.EnableSwagger2

/**
*Created by: Sorata 17/9/12 上午10:58
*
*/
@Configuration
@EnableSwagger2
@ConditionalOnProperty(value = "swagger-enable", havingValue = "true") //开发-上线 是否开启文档
class SwaggerConfiguration {

@Bean
fun createRestApi(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.socene.kotlin.controller"))//API//文档扫描的包
.paths(PathSelectors.any())
.build()
}

fun apiInfo(): ApiInfo {
return ApiInfoBuilder()
.title("API文档")
.description("项目文档描述")
.termsOfServiceUrl("www.baidu.com")
.contact("sorata")
.version("1.0")
.license("内部")
.build()
}

}

9.security配置

package com.socene.kotlin.config.security

import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import java.util.ArrayList

/**
*Created by: Sorata 17/9/12 上午9:33
*
*/

class SysUserDetails(name: String="admin", userId: String="1",pwd: String="admin",roles: Array<String> = arrayOf("")): SUser(name,userId,pwd,roles),UserDetails{

override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
val list = ArrayList<GrantedAuthority>()
if (this.roles.isNotEmpty()) {
this.roles.mapTo(list) { SimpleGrantedAuthority(it) }
} else {
list.add(SimpleGrantedAuthority("normal"))
}
return list

}

override fun isEnabled(): Boolean {
return true
}

override fun getUsername(): String {
return name
}

override fun isCredentialsNonExpired(): Boolean {
return true
}

override fun getPassword(): String {
return pwd
}

override fun isAccountNonExpired(): Boolean {
return true
}

override fun isAccountNonLocked(): Boolean {
return true
}
}

open class SUser(var name:String="admin",
var userId:String="admin",
var pwd:String="admin",
var roles:Array<String> = arrayOf(""))

这个是自定义的user,以下是配置文件

package com.socene.kotlin.config.security

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.security.SecurityProperties
import org.springframework.context.annotation.Bean
import org.springframework.core.annotation.Order
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException

/**
*Created by: Sorata 2017/9/9 下午6:25
*
*/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启注解
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
class WebAppSecurityConfig : WebSecurityConfigurerAdapter() {

/*添加拦截规则*/
override fun configure(http: HttpSecurity?) {
http?.headers()?.disable()?.
csrf()?.disable()?.
authorizeRequests()?.mvcMatchers("/admin/*")?.permitAll()?.
mvcMatchers("/web/*")?.authenticated()?.
mvcMatchers("/admin/login.html")?.authenticated()?.
anyRequest()?.permitAll()?.
and()?.
formLogin()?.loginPage("/admin/index.html")?.
successForwardUrl("/success")?.failureForwardUrl("/fail")
}

/*添加用户的服务的实现*/
override fun configure(auth: AuthenticationManagerBuilder?) {
auth?.userDetailsService(securityDetailsService)
}

@Autowired lateinit var securityDetailsService: WebSecurityUserDetailsService

@Bean
fun webSecurityUserDetailsService(): WebSecurityUserDetailsService {
return WebSecurityUserDetailsService()
}

}

/* 配置用户登录服务  这里需要与数据库进行交互*/
class WebSecurityUserDetailsService : UserDetailsService {

override fun loadUserByUsername(username: String?): UserDetails {

if (null == username) throw UsernameNotFoundException("Not Found User")
if (username == "admin") {
return SysUserDetails(username, "", "admin", arrayOf("admin", "user"))
}
throw UsernameNotFoundException("Not Found User")
}
}

以上全部配置完成,似乎有些配置没有啊?比如说数据源这东西?!当然 这里使用的是druid的springboot支持jar,所有只需要在application.yml文件里面配置相应的属性值就可以完成数据源的配置,并且支持监控。个人还是推荐使用undertow来替代tomcat 如果不喜欢这么做 那么可以自行调整。

项目测试

1.编写实体类、dao、service、controller

package com.socene.kotlin.entity

import java.util.*
import javax.persistence.*

/* *
*Created by: Sorata 2017/11/9 0009 上午 10:32
*
*/
@Entity
@Table(name = "table_user")
data class User(
@Id
@GeneratedValue
var id: Int = 0,
@Column(nullable = true,unique = true)
var username: String = "",
@Column(length = 36)
var password: String = "",
var enable: Boolean = true,
var createTime: Date = Date()
)

package com.socene.kotlin.dao

import com.socene.kotlin.entity.User
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param

/* *
*Created by: Sorata 2017/11/9 0009 上午 10:38
*
*/
interface UserRepository : JpaRepository<User, Int> {

fun findByUsername(name: String): User?

fun findByPassword(password: String, pageable: Pageable): Page<User>

@Query("select u from User u where username = :name  and password = :password")
fun selectUser(@Param("name")name: String, @Param("password") password: String): User?

}

package com.socene.kotlin.bean

import org.springframework.data.domain.Example
import org.springframework.data.jpa.repository.JpaRepository
import java.io.Serializable

/* *
*Created by: Sorata 2017/11/9 0009 上午 10:40
*
*/
abstract class BaseService<T, ID : Serializable> {

abstract val repository: JpaRepository<T, ID>

fun save(entity: T) = repository.save(entity)

fun save(entitys: Iterable<T>): MutableList<T> = repository.save(entitys)

fun saveAndFlush(entity: T) = repository.saveAndFlush(entity)

fun del(entity: T) = repository.delete(entity)

fun del(id: ID) = repository.delete(id)

fun del(ens: Iterable<T>) = repository.delete(ens)

fun findOne(id: ID): T? = repository.findOne(id)

fun findOne(example: Example<T>) = repository.findOne(example)

fun exists(id: ID) = repository.exists(id)

fun flush() = repository.flush()

}

package com.socene.kotlin.service

import com.socene.kotlin.bean.BaseService
import com.socene.kotlin.dao.UserRepository
import com.socene.kotlin.entity.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Service

/* *
*Created by: Sorata 2017/11/9 0009 上午 10:48
*
*/
@Service
class UserService : BaseService<User, Int>() {

@Autowired lateinit var userRepository: UserRepository

override val repository: JpaRepository<User, Int>
get() = userRepository

fun findByUsername(name: String) = userRepository.findByUsername(name)

fun findUserPage(password: String,page:Int,limit:Int):Page<User>{
val pageable = PageRequest(page,limit,Sort.Direction.DESC,"createTime")
return userRepository.findByPassword(password, pageable)
}

fun findUser(name: String,password:String) = userRepository.selectUser(name,password)
}

package com.socene.kotlin.controller

import com.socene.kotlin.entity.User
import com.socene.kotlin.service.UserService
import io.swagger.annotations.Api
import io.swagger.annotations.ApiImplicitParam
import io.swagger.annotations.ApiImplicitParams
import io.swagger.annotations.ApiOperation
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.*

/* *
*Created by: Sorata 2017/11/9 0009 上午 11:13
*
*/
@Api("用户接口")
@RestController
@RequestMapping("/api")
class UserController {

private val logger: Logger = LoggerFactory.getLogger(javaClass)

@Autowired lateinit var userService: UserService

@ApiOperation("根据名字查询一个用户")
@ApiImplicitParams(
ApiImplicitParam(value = "名字", name = "name", required = true, dataType = "string", paramType = "path")
)
@GetMapping("/user/find/one/{name}")
fun findOne(@PathVariable name: String) = userService.findByUsername(name) ?: "未找到数据"

@ApiOperation("根据用户名密码查询")
@ApiImplicitParams(
ApiImplicitParam(value = "名字", name = "name", required = true, dataType = "string", paramType = "query"),
ApiImplicitParam(value = "密码", name = "password", required = true, dataType = "string", paramType = "query")
)
@GetMapping("user/find/one/query")
fun findOne(@RequestParam name: String, @RequestParam password: String) =
userService.findUser(name, password) ?: "未找到数据"

@GetMapping("user/find/page")
fun findPage(@RequestParam name: String, @RequestParam(required = false, defaultValue = "0")
page: Int, @RequestParam(required = false, defaultValue = "15") limit: Int) = userService.findUserPage(name, page, limit)

}

附:https://gitee.com/lencer93/springboot-kotlin
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  springboot kotlin jpa