自动路由处理器添加异常处理功能

This commit is contained in:
tursom 2020-03-09 18:08:38 +08:00
parent 38f3655ed2
commit 28233132c3
3 changed files with 57 additions and 31 deletions

View File

@ -256,4 +256,7 @@ inline fun loop(`continue`: () -> Boolean = { true }, action: () -> Unit) {
while (`continue`()) action() while (`continue`()) action()
} }
inline fun <reified T> getClazz() = T::class.java inline fun <reified T> getClazz() = T::class.java
@Suppress("NOTHING_TO_INLINE")
inline fun <R, T : Function<R>> lambda(lambda: T) = lambda

View File

@ -1,6 +1,8 @@
package cn.tursom.web.router package cn.tursom.web.router
import cn.tursom.core.buffer.ByteBuffer import cn.tursom.core.buffer.ByteBuffer
import cn.tursom.core.cast
import cn.tursom.core.lambda
import cn.tursom.core.regex.regex import cn.tursom.core.regex.regex
import cn.tursom.json.JsonWorkerImpl import cn.tursom.json.JsonWorkerImpl
import cn.tursom.web.ExceptionContent import cn.tursom.web.ExceptionContent
@ -11,9 +13,9 @@ import cn.tursom.web.mapping.*
import cn.tursom.web.result.* import cn.tursom.web.result.*
import cn.tursom.web.router.impl.SimpleRouter import cn.tursom.web.router.impl.SimpleRouter
import cn.tursom.web.utils.Chunked import cn.tursom.web.utils.Chunked
import cn.tursom.web.utils.ContextTypeEnum
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.*
import java.io.RandomAccessFile
import java.lang.reflect.Method import java.lang.reflect.Method
import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadFactory import java.util.concurrent.ThreadFactory
@ -40,7 +42,7 @@ open class RoutedHttpHandler(
Runtime.getRuntime().availableProcessors() * 4, Runtime.getRuntime().availableProcessors() * 4,
Runtime.getRuntime().availableProcessors() * 4, Runtime.getRuntime().availableProcessors() * 4,
0L, TimeUnit.MILLISECONDS, 0L, TimeUnit.MILLISECONDS,
LinkedBlockingQueue<Runnable>(), LinkedBlockingQueue(),
ThreadFactory { ThreadFactory {
Thread(it, "TreeDiagramWorker-${threadNumber.incrementAndGet()}") Thread(it, "TreeDiagramWorker-${threadNumber.incrementAndGet()}")
} }
@ -61,7 +63,16 @@ open class RoutedHttpHandler(
open fun handle(content: HttpContent, handler: ((HttpContent) -> Any?)?) { open fun handle(content: HttpContent, handler: ((HttpContent) -> Any?)?) {
if (handler != null) { if (handler != null) {
handler(content) try {
handler(content)
} catch (e: Throwable) {
val bos = ByteArrayOutputStream()
bos.write("处理时发生异常:\n".toByteArray())
e.printStackTrace(PrintStream(bos))
content.setContextType(ContextTypeEnum.txt.value)
content.write(bos.toByteArray())
content.finish(502)
}
} else { } else {
notFound(content) notFound(content)
} }
@ -128,44 +139,43 @@ open class RoutedHttpHandler(
} }
} }
@Suppress("UNREACHABLE_CODE")
fun addRouter(obj: Any, method: Method, route: String, router: Router<Pair<Any?, (HttpContent) -> Any?>>) { fun addRouter(obj: Any, method: Method, route: String, router: Router<Pair<Any?, (HttpContent) -> Any?>>) {
val doLog = method.doLog val doLog = method.doLog
router[safeRoute(route)] = obj to (if (method.parameterTypes.isEmpty()) { router[safeRoute(route)] = obj to (if (method.parameterTypes.isNotEmpty()) when (method.returnType) {
when { Void::class.java -> lambda { content: HttpContent -> method(obj, content) }
method.getAnnotation(Html::class.java) != null -> { content -> Void.TYPE -> lambda { content: HttpContent -> method(obj, content) }
method(obj)?.let { result -> finishHtml(result, content, doLog) } Unit::class.java -> lambda { content: HttpContent -> method(obj, content) }
}
method.getAnnotation(Text::class.java) != null -> { content ->
method(obj)?.let { result -> finishText(result, content, doLog) }
}
method.getAnnotation(Json::class.java) != null -> { content ->
method(obj)?.let { result -> finishJson(result, content, doLog) }
}
else -> { content ->
method(obj)?.let { result -> autoReturn(method, result, content, doLog) }
}
}
} else when (method.returnType) {
Void::class.java -> { content -> method(obj, content) }
Void.TYPE -> { content -> method(obj, content) }
Unit::class.java -> { content -> method(obj, content) }
else -> when { else -> when {
method.getAnnotation(Html::class.java) != null -> { content -> method.getAnnotation(Html::class.java) != null -> lambda { content: HttpContent ->
method(obj, content)?.let { result -> finishHtml(result, content, doLog) } method(obj, content)?.let { result -> finishHtml(result, content, doLog) }
} }
method.getAnnotation(Text::class.java) != null -> { content -> method.getAnnotation(Text::class.java) != null -> lambda { content: HttpContent ->
method(obj, content)?.let { result -> finishText(result, content, doLog) } method(obj, content)?.let { result -> finishText(result, content, doLog) }
} }
method.getAnnotation(Json::class.java) != null -> { content -> method.getAnnotation(Json::class.java) != null -> lambda { content: HttpContent ->
method(obj, content)?.let { result -> finishJson(result, content, doLog) } method(obj, content)?.let { result -> finishJson(result, content, doLog) }
} }
else -> { content: HttpContent -> else -> lambda { content: HttpContent ->
method(obj, content)?.let { result -> autoReturn(method, result, content, doLog) } method(obj, content)?.let { result -> autoReturn(method, result, content, doLog) }
} }
} }
} else when {
method.getAnnotation(Html::class.java) != null -> lambda { content: HttpContent ->
method(obj)?.let { result -> finishHtml(result, content, doLog) }
}
method.getAnnotation(Text::class.java) != null -> lambda { content: HttpContent ->
method(obj)?.let { result -> finishText(result, content, doLog) }
}
method.getAnnotation(Json::class.java) != null -> lambda { content: HttpContent ->
method(obj)?.let { result -> finishJson(result, content, doLog) }
}
else -> lambda { content: HttpContent ->
method(obj)?.let { result -> autoReturn(method, result, content, doLog) }
}
}).let { }).let {
if (method.getAnnotation(BlockHandler::class.java) != null) { content -> if (method.getAnnotation(BlockHandler::class.java) != null) lambda { content ->
workerThread.execute { it(content) } workerThread.execute { handle(content, it) }
} else } else
it it
} }

View File

@ -5,9 +5,12 @@ import cn.tursom.web.MutableHttpContent
import cn.tursom.web.mapping.* import cn.tursom.web.mapping.*
import cn.tursom.web.result.* import cn.tursom.web.result.*
import cn.tursom.web.router.impl.SimpleRouter import cn.tursom.web.router.impl.SimpleRouter
import cn.tursom.web.utils.ContextTypeEnum
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import kotlin.reflect.KCallable import kotlin.reflect.KCallable
import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.jvmErasure import kotlin.reflect.jvm.jvmErasure
@ -41,7 +44,17 @@ open class AsyncRoutedHttpHandler(
open suspend fun handle(content: HttpContent, handler: (suspend (HttpContent) -> Unit)?) { open suspend fun handle(content: HttpContent, handler: (suspend (HttpContent) -> Unit)?) {
if (handler != null) { if (handler != null) {
handler(content) try {
handler(content)
} catch (e: Throwable) {
val bos = ByteArrayOutputStream()
@Suppress("BlockingMethodInNonBlockingContext")
bos.write("处理时发生异常:\n".toByteArray())
e.printStackTrace(PrintStream(bos))
content.setContextType(ContextTypeEnum.txt.value)
content.write(bos.toByteArray())
content.finish(502)
}
} else { } else {
notFound(content) notFound(content)
} }