Springboot+Kotlin+Jpa集成项目

项目集成

    使用的工具: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</artifactId>
			<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

转载于:https://my.oschina.net/swiftloop/blog/1570506

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值