import org.springframework.boot.springapplication
import org.springframework.boot.autoconfigure.springbootapplication
/**
* created by tony on 2018/11/13.
*/
@springbootapplication
open class springkotlinapplication
fun main(args: array<string>) {
springapplication.run(springkotlinapplication::class.java, *args)
}
需要注意open的使用,如果不加open会报如下的错误:
org.springframework.beans.factory.parsing.beandefinitionparsingexception: configuration problem: @configuration class 'springkotlinapplication' may not be final. remove the final modifier to continue.
import com.alibaba.fastjson.json
import com.alibaba.fastjson.serializer.serializerfeature
import org.springframework.data.redis.serializer.redisserializer
import org.springframework.data.redis.serializer.serializationexception
import java.nio.charset.charset
/**
* created by tony on 2018/11/13.
*/
class fastjsonredisserializer<t>(private val clazz: class<t>) : redisserializer<t> {
@throws(serializationexception::class)
override fun serialize(t: t?) = if (null == t) {
bytearray(0)
} else json.tojsonstring(t, serializerfeature.writeclassname).tobytearray(default_charset)
@throws(serializationexception::class)
override fun deserialize(bytes: bytearray?): t? {
if (null == bytes || bytes.size <= 0) {
return null
}
val str = string(bytes, default_charset)
return json.parseobject(str, clazz) as t
}
companion object {
private val default_charset = charset.forname("utf-8")
}
}
创建 redisconfig
import org.springframework.data.redis.core.redistemplate
import org.springframework.data.redis.connection.redisconnectionfactory
import org.springframework.context.annotation.bean
import org.springframework.data.redis.cache.rediscachemanager
import org.springframework.cache.cachemanager
import org.springframework.cache.annotation.cachingconfigurersupport
import org.springframework.cache.annotation.enablecaching
import org.springframework.context.annotation.configuration
import org.springframework.data.redis.serializer.stringredisserializer
import org.springframework.boot.autoconfigure.condition.conditionalonmissingbean
import org.springframework.boot.context.properties.enableconfigurationproperties
import org.springframework.data.redis.core.redisoperations
import org.springframework.boot.autoconfigure.condition.conditionalonclass
import org.springframework.boot.autoconfigure.data.redis.redisproperties
/**
* created by tony on 2018/11/13.
*/
@enablecaching
@configuration
@conditionalonclass(redisoperations::class)
@enableconfigurationproperties(redisproperties::class)
open class redisconfig : cachingconfigurersupport() {
@bean(name = arrayof("redistemplate"))
@conditionalonmissingbean(name = arrayof("redistemplate"))
open fun redistemplate(redisconnectionfactory: redisconnectionfactory): redistemplate<any, any> {
val template = redistemplate<any, any>()
val fastjsonredisserializer = fastjsonredisserializer(any::class.java)
template.valueserializer = fastjsonredisserializer
template.hashvalueserializer = fastjsonredisserializer
template.keyserializer = stringredisserializer()
template.hashkeyserializer = stringredisserializer()
template.connectionfactory = redisconnectionfactory
return template
}
//缓存管理器
@bean
open fun cachemanager(redisconnectionfactory: redisconnectionfactory): cachemanager {
val builder = rediscachemanager
.rediscachemanagerbuilder
.fromconnectionfactory(redisconnectionfactory)
return builder.build()
}
}
这里也都需要使用open,理由同上。 1.4 创建 service
创建一个 user 对象,使用 datat class 类型。
data class user(var username:string,var password:string):serializable
创建操作 user 的service接口
import com.kotlin.tutorial.user.user
/**
* created by tony on 2018/11/13.
*/
interface iuserservice {
fun getuser(username: string): user
fun createuser(username: string,password: string)
}
创建 service 的实现类:
import com.kotlin.tutorial.user.user
import com.kotlin.tutorial.user.service.iuserservice
import org.springframework.beans.factory.annotation.autowired
import org.springframework.data.redis.core.redistemplate
import org.springframework.stereotype.service
/**
* created by tony on 2018/11/13.
*/
@service
class userserviceimpl : iuserservice {
@autowired
lateinit var redistemplate: redistemplate<any, any>
override fun getuser(username: string): user {
var user = redistemplate.opsforvalue().get("user_${username}")
if (user == null) {
user = user("default","000000")
}
return user as user
}
override fun createuser(username: string, password: string) {
redistemplate.opsforvalue().set("user_${username}", user(username, password))
}
}
/**
* created by tony on 2018/11/13.
*/
interface itask {
fun execute()
}
再创建一个模拟的任务,其中delayinseconds用来模拟任务所花费的时间,单位是秒。
import java.util.concurrent.timeunit
import com.kotlin.tutorial.task.itask
/**
* created by tony on 2018/11/13.
*/
class mocktask(private val delayinseconds: int) : itask {
/**
* stores information if task was started.
*/
var started: boolean = false
/**
* stores information if task was successfully finished.
*/
var finishedsuccessfully: boolean = false
/**
* stores information if the task was interrupted.
* it can happen if the thread that is running this task was killed.
*/
var interrupted: boolean = false
/**
* stores the thread identifier in which the task was executed.
*/
var threadid: long = 0
override fun execute() {
try {
this.threadid = thread.currentthread().id
this.started = true
timeunit.seconds.sleep(delayinseconds.tolong())
this.finishedsuccessfully = true
} catch (e: interruptedexception) {
this.interrupted = true
}
}
}
import com.kotlin.tutorial.task.itask
import io.reactivex.completable
import io.reactivex.schedulers.schedulers
import org.slf4j.loggerfactory
import org.springframework.util.collectionutils
import java.util.*
import java.util.concurrent.executors
import java.util.stream.collectors
/**
* created by tony on 2018/11/13.
*/
class concurrenttasksexecutor(private val numberofconcurrentthreads: int, private val tasks: collection<itask>?) : itask {
val log = loggerfactory.getlogger(this.javaclass)
constructor(numberofconcurrentthreads: int, vararg tasks: itask) : this(numberofconcurrentthreads, if (tasks == null) null else arrays.aslist<itask>(*tasks)) {}
init {
if (numberofconcurrentthreads < 0) {
throw runtimeexception("amount of threads must be higher than zero.")
}
}
/**
* converts collection of tasks (except null tasks) to collection of completable actions.
* each action will be executed in thread according to the scheduler created with [.createscheduler] method.
*
* @return list of completable actions
*/
private val asconcurrenttasks: list<completable>
get() {
if (tasks!=null) {
val scheduler = createscheduler()
return tasks.stream()
.filter { task -> task != null }
.map { task ->
completable
.fromaction {
task.execute()
}
.subscribeon(scheduler)
}
.collect(collectors.tolist())
} else {
return arraylist<completable>()
}
}
/**
* checks whether tasks collection is empty.
*
* @return true if tasks collection is null or empty, false otherwise
*/
private val istaskscollectionempty: boolean
get() = collectionutils.isempty(tasks)
/**
* executes all tasks concurrent way only if collection of tasks is not empty.
* method completes when all of the tasks complete (or one of them fails).
* if one of the tasks failed the the exception will be rethrown so that it can be handled by mechanism that calls this method.
*/
override fun execute() {
if (istaskscollectionempty) {
log.warn("there are no tasks to be executed.")
return
}
log.debug("executing #{} tasks concurrent way.", tasks?.size)
completable.merge(asconcurrenttasks).blockingawait()
}
/**
* creates a scheduler that will be used for executing tasks concurrent way.
* scheduler will use number of threads defined in [.numberofconcurrentthreads]
*
* @return scheduler
*/
private fun createscheduler() = schedulers.from(executors.newfixedthreadpool(numberofconcurrentthreads))
}