mirror of
https://github.com/tursom/TursomServer.git
synced 2025-02-03 16:20:16 +08:00
AsyncRoutedHttpHandler 添加对协程的支持
This commit is contained in:
parent
024dd8c7cf
commit
597b94f12d
@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.RandomAccessFile
|
import java.io.RandomAccessFile
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
import kotlin.reflect.KCallable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动添加路径映射的处理器
|
* 自动添加路径映射的处理器
|
||||||
@ -97,44 +98,54 @@ open class RoutedHttpHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun insertMapping(obj: Any, method: Method) {
|
protected fun insertMapping(obj: Any, method: Method) {
|
||||||
|
val mapping = obj::class.java.getAnnotation(Mapping::class.java)?.route ?: arrayOf("")
|
||||||
method.annotations.forEach { annotation ->
|
method.annotations.forEach { annotation ->
|
||||||
log?.info("method route {} annotation {}", method, annotation)
|
log?.info("method route {} annotation {}", method, annotation)
|
||||||
val (routes, router) = getRoutes(annotation) ?: return@forEach
|
val (routes, router) = getRoutes(annotation) ?: return@forEach
|
||||||
log?.info("method route {} mapped to {}", method, routes)
|
log?.info("method route {} mapped to {}", method, routes)
|
||||||
routes.forEach { route ->
|
routes.forEach { route ->
|
||||||
router[safeRoute(route)] = if (method.parameterTypes.isEmpty()) {
|
if (mapping.isEmpty()) {
|
||||||
obj to when {
|
addRouter(obj, method, route, router)
|
||||||
method.getAnnotation(Html::class.java) != null -> { content ->
|
} else mapping.forEach {
|
||||||
method(obj)?.let { result -> finishHtml(result, content) }
|
val base = safeRoute(it)
|
||||||
}
|
addRouter(obj, method, base + route, router)
|
||||||
method.getAnnotation(Text::class.java) != null -> { content ->
|
}
|
||||||
method(obj)?.let { result -> finishText(result, content) }
|
}
|
||||||
}
|
}
|
||||||
method.getAnnotation(Json::class.java) != null -> { content ->
|
}
|
||||||
method(obj)?.let { result -> finishJson(result, content) }
|
|
||||||
}
|
fun addRouter(obj: Any, method: Method, route: String, router: Router<Pair<Any?, (HttpContent) -> Unit>>) {
|
||||||
else -> { content ->
|
router[safeRoute(route)] = if (method.parameterTypes.isEmpty()) {
|
||||||
method(obj)?.let { result -> autoReturn(result, content) }
|
obj to when {
|
||||||
}
|
method.getAnnotation(Html::class.java) != null -> { content ->
|
||||||
}
|
method(obj)?.let { result -> finishHtml(result, content) }
|
||||||
} else obj to when (method.returnType) {
|
}
|
||||||
Void::class.java -> { content -> method(obj, content) }
|
method.getAnnotation(Text::class.java) != null -> { content ->
|
||||||
Void.TYPE -> { content -> method(obj, content) }
|
method(obj)?.let { result -> finishText(result, content) }
|
||||||
Unit::class.java -> { content -> method(obj, content) }
|
}
|
||||||
else -> when {
|
method.getAnnotation(Json::class.java) != null -> { content ->
|
||||||
method.getAnnotation(Html::class.java) != null -> { content ->
|
method(obj)?.let { result -> finishJson(result, content) }
|
||||||
method(obj, content)?.let { result -> finishHtml(result, content) }
|
}
|
||||||
}
|
else -> { content ->
|
||||||
method.getAnnotation(Text::class.java) != null -> { content ->
|
method(obj)?.let { result -> autoReturn(result, content) }
|
||||||
method(obj, content)?.let { result -> finishText(result, content) }
|
}
|
||||||
}
|
}
|
||||||
method.getAnnotation(Json::class.java) != null -> { content ->
|
} else obj to when (method.returnType) {
|
||||||
method(obj, content)?.let { result -> finishJson(result, content) }
|
Void::class.java -> { content -> method(obj, content) }
|
||||||
}
|
Void.TYPE -> { content -> method(obj, content) }
|
||||||
else -> { content ->
|
Unit::class.java -> { content -> method(obj, content) }
|
||||||
method(obj, content)?.let { result -> autoReturn(result, content) }
|
else -> when {
|
||||||
}
|
method.getAnnotation(Html::class.java) != null -> { content ->
|
||||||
}
|
method(obj, content)?.let { result -> finishHtml(result, content) }
|
||||||
|
}
|
||||||
|
method.getAnnotation(Text::class.java) != null -> { content ->
|
||||||
|
method(obj, content)?.let { result -> finishText(result, content) }
|
||||||
|
}
|
||||||
|
method.getAnnotation(Json::class.java) != null -> { content ->
|
||||||
|
method(obj, content)?.let { result -> finishJson(result, content) }
|
||||||
|
}
|
||||||
|
else -> { content ->
|
||||||
|
method(obj, content)?.let { result -> autoReturn(result, content) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,15 +242,25 @@ open class RoutedHttpHandler(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> T.repeatUntil(state: (T) -> Boolean, block: (T) -> T): T {
|
||||||
|
var result = this
|
||||||
|
while (state(result)) {
|
||||||
|
result = block(result)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
fun safeRoute(route: String) = (
|
fun safeRoute(route: String) = (
|
||||||
if (route.startsWith('/')) route else "/$route").let {
|
if (route.startsWith('/')) route else "/$route").let {
|
||||||
if (it.endsWith('/')) it.dropLast(1) else it
|
if (it.endsWith('/')) it.dropLast(1) else it
|
||||||
}
|
}.repeatUntil({ it.contains("//") }) { it.replace("//", "/") }
|
||||||
|
|
||||||
fun autoReturn(result: Any, content: HttpContent) {
|
fun autoReturn(result: Any, content: HttpContent) {
|
||||||
log?.debug("{}: autoReturn: {}", content.clientIp, result)
|
log?.debug("{}: autoReturn: {}", content.clientIp, result)
|
||||||
when (result) {
|
when (result) {
|
||||||
is String -> content.finishText(result.toByteArray())
|
is String -> content.finishText(result.toByteArray())
|
||||||
|
is StringBuilder -> content.finishText(result.toString().toByteArray())
|
||||||
|
is StringBuffer -> content.finishText(result.toString().toByteArray())
|
||||||
is ByteArray -> content.finishText(result)
|
is ByteArray -> content.finishText(result)
|
||||||
is File -> {
|
is File -> {
|
||||||
content.autoContextType(result.name)
|
content.autoContextType(result.name)
|
||||||
|
7
web/web-coroutine/build.gradle
Normal file
7
web/web-coroutine/build.gradle
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
dependencies {
|
||||||
|
implementation project(":web")
|
||||||
|
api project(":json")
|
||||||
|
api group: 'org.slf4j', name: 'slf4j-api', version: '1.7.29'
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
|
||||||
|
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.3.61'
|
||||||
|
}
|
@ -80,51 +80,62 @@ open class AsyncRoutedHttpHandler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
protected fun insertMapping(obj: Any, method: KCallable<*>) {
|
protected fun insertMapping(obj: Any, method: KCallable<*>) {
|
||||||
|
val mapping = obj::class.java.getAnnotation(Mapping::class.java)?.route ?: arrayOf("")
|
||||||
method.annotations.forEach { annotation ->
|
method.annotations.forEach { annotation ->
|
||||||
log?.info("method route {} annotation {}", method, annotation)
|
log?.info("method route {} annotation {}", method, annotation)
|
||||||
val (routes, router) = getAsyncRoutes(annotation) ?: return@forEach
|
val (routes, router) = getAsyncRoutes(annotation) ?: return@forEach
|
||||||
log?.info("method route {} mapped to {}", method, routes)
|
log?.info("method route {} mapped to {}", method, routes)
|
||||||
routes.forEach { route ->
|
routes.forEach { route ->
|
||||||
router[safeRoute(route)] = if (method.parameters.size == 1) {
|
if (mapping.isEmpty()) {
|
||||||
obj to when {
|
addRouter(obj, method, route, router)
|
||||||
method.findAnnotation<Html>() != null -> { content ->
|
} else mapping.forEach {
|
||||||
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishHtml(result, content) }
|
val base = safeRoute(it)
|
||||||
}
|
addRouter(obj, method, base + route, router)
|
||||||
method.findAnnotation<Text>() != null -> { content ->
|
|
||||||
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishText(result, content) }
|
|
||||||
}
|
|
||||||
method.findAnnotation<Json>() != null -> { content ->
|
|
||||||
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishJson(result, content) }
|
|
||||||
}
|
|
||||||
else -> { content ->
|
|
||||||
(method as suspend Any.() -> Any?)(obj)?.let { result -> autoReturn(result, content) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else obj to when (method.returnType) {
|
|
||||||
Void::class.java -> method as suspend (HttpContent) -> Unit
|
|
||||||
Void.TYPE -> method as suspend (HttpContent) -> Unit
|
|
||||||
Unit::class.java -> method as suspend (HttpContent) -> Unit
|
|
||||||
else -> when {
|
|
||||||
method.findAnnotation<Html>() != null -> { content ->
|
|
||||||
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishHtml(result, content) }
|
|
||||||
}
|
|
||||||
method.findAnnotation<Text>() != null -> { content ->
|
|
||||||
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishText(result, content) }
|
|
||||||
}
|
|
||||||
method.findAnnotation<Json>() != null -> { content ->
|
|
||||||
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishJson(result, content) }
|
|
||||||
}
|
|
||||||
else -> { content ->
|
|
||||||
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> autoReturn(result, content) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun addRouter(obj: Any, method: KCallable<*>, route: String, router: Router<Pair<Any?, suspend (HttpContent) -> Unit>>) {
|
||||||
|
router[safeRoute(route)] = if (method.parameters.size == 1) {
|
||||||
|
obj to when {
|
||||||
|
method.findAnnotation<Html>() != null -> { content ->
|
||||||
|
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishHtml(result, content) }
|
||||||
|
}
|
||||||
|
method.findAnnotation<Text>() != null -> { content ->
|
||||||
|
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishText(result, content) }
|
||||||
|
}
|
||||||
|
method.findAnnotation<Json>() != null -> { content ->
|
||||||
|
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishJson(result, content) }
|
||||||
|
}
|
||||||
|
else -> { content ->
|
||||||
|
(method as suspend Any.() -> Any?)(obj)?.let { result -> autoReturn(result, content) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else obj to when (method.returnType) {
|
||||||
|
Void::class.java -> method as suspend (HttpContent) -> Unit
|
||||||
|
Void.TYPE -> method as suspend (HttpContent) -> Unit
|
||||||
|
Unit::class.java -> method as suspend (HttpContent) -> Unit
|
||||||
|
else -> when {
|
||||||
|
method.findAnnotation<Html>() != null -> { content ->
|
||||||
|
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishHtml(result, content) }
|
||||||
|
}
|
||||||
|
method.findAnnotation<Text>() != null -> { content ->
|
||||||
|
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishText(result, content) }
|
||||||
|
}
|
||||||
|
method.findAnnotation<Json>() != null -> { content ->
|
||||||
|
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishJson(result, content) }
|
||||||
|
}
|
||||||
|
else -> { content ->
|
||||||
|
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> autoReturn(result, content) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected fun getAsyncRoutes(annotation: Annotation) = when (annotation) {
|
protected fun getAsyncRoutes(annotation: Annotation) = when (annotation) {
|
||||||
is Mapping -> {
|
is Mapping -> {
|
||||||
annotation.route to getAsyncRouter(annotation.method)
|
annotation.route to getAsyncRouter(annotation.method)
|
||||||
|
Loading…
Reference in New Issue
Block a user