refactor(core): 移除单例注解和优化异常处理
refactor(core): 优化QueryWrapperImpl类结构和缓存逻辑
This commit is contained in:
parent
c3cb7fae37
commit
098fa02ca6
@ -37,7 +37,7 @@ data class RespBean(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun failure(code: Int, message: String, data: Any? = null): RespBean {
|
fun failure(code: Int, message: String, data: Any? = null): RespBean {
|
||||||
return RespBean(HttpStatus.ERROR, message, data)
|
return RespBean(code, message, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class JwtAuthenticationHandler(
|
|||||||
tokenService.verifyToken(user)
|
tokenService.verifyToken(user)
|
||||||
event.setUser(user)
|
event.setUser(user)
|
||||||
event.next()
|
event.next()
|
||||||
} catch (e: Exception) {
|
} catch (e: Throwable) {
|
||||||
event.fail(401, Meta.unauthorized(e.message ?: "token"))
|
event.fail(401, Meta.unauthorized(e.message ?: "token"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class ResponseHandler: ResponseHandlerInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 业务异常处理
|
// 业务异常处理
|
||||||
override suspend fun exception(ctx: RoutingContext, e: Exception) {
|
override suspend fun exception(ctx: RoutingContext, e: Throwable) {
|
||||||
logger.error { "${ctx.request().uri()}: ${e.stackTraceToString()}" }
|
logger.error { "${ctx.request().uri()}: ${e.stackTraceToString()}" }
|
||||||
val resObj = when(e) {
|
val resObj = when(e) {
|
||||||
is Meta -> {
|
is Meta -> {
|
||||||
|
|||||||
@ -3,11 +3,9 @@ package app.domain.account
|
|||||||
import app.base.domain.auth.modle.AccountRoleDTO
|
import app.base.domain.auth.modle.AccountRoleDTO
|
||||||
import app.domain.account.modle.AccountRoleAccessDTO
|
import app.domain.account.modle.AccountRoleAccessDTO
|
||||||
import com.google.inject.Inject
|
import com.google.inject.Inject
|
||||||
import com.google.inject.Singleton
|
|
||||||
import io.vertx.sqlclient.SqlClient
|
import io.vertx.sqlclient.SqlClient
|
||||||
import org.aikrai.vertx.db.RepositoryImpl
|
import org.aikrai.vertx.db.RepositoryImpl
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class AccountRepositoryImpl @Inject constructor(
|
class AccountRepositoryImpl @Inject constructor(
|
||||||
sqlClient: SqlClient
|
sqlClient: SqlClient
|
||||||
) : RepositoryImpl<Long, Account>(sqlClient), AccountRepository {
|
) : RepositoryImpl<Long, Account>(sqlClient), AccountRepository {
|
||||||
|
|||||||
@ -64,9 +64,9 @@ class WebVerticle @Inject constructor(
|
|||||||
rootRouter.route("/api" + "*").subRouter(router)
|
rootRouter.route("/api" + "*").subRouter(router)
|
||||||
router.route()
|
router.route()
|
||||||
.handler(corsHandler)
|
.handler(corsHandler)
|
||||||
.failureHandler(errorHandler)
|
|
||||||
.handler(BodyHandler.create())
|
.handler(BodyHandler.create())
|
||||||
.handler(logHandler)
|
.handler(logHandler)
|
||||||
|
.failureHandler(errorHandler)
|
||||||
|
|
||||||
val authHandler = JwtAuthenticationHandler(coroutineScope, tokenService, context, snowflake)
|
val authHandler = JwtAuthenticationHandler(coroutineScope, tokenService, context, snowflake)
|
||||||
router.route("/*").handler(authHandler)
|
router.route("/*").handler(authHandler)
|
||||||
@ -92,13 +92,13 @@ class WebVerticle @Inject constructor(
|
|||||||
if (failure != null) {
|
if (failure != null) {
|
||||||
logger.error { "${ctx.request().uri()}: ${failure.stackTraceToString()}" }
|
logger.error { "${ctx.request().uri()}: ${failure.stackTraceToString()}" }
|
||||||
val resObj = when (failure) {
|
val resObj = when (failure) {
|
||||||
is Meta -> RespBean.failure("${failure.name}:${failure.message}", failure.data)
|
is Meta -> RespBean.failure(ctx.statusCode(),"${failure.name}:${failure.message}", failure.data)
|
||||||
else -> RespBean.failure("${failure.javaClass.simpleName}${if (failure.message != null) ":${failure.message}" else ""}")
|
else -> RespBean.failure("${failure.javaClass.simpleName}${if (failure.message != null) ":${failure.message}" else ""}")
|
||||||
}
|
}
|
||||||
val resStr = JsonUtil.toJsonStr(resObj)
|
val resStr = JsonUtil.toJsonStr(resObj)
|
||||||
ctx.put("responseData", resStr)
|
ctx.put("responseData", resStr)
|
||||||
ctx.response()
|
ctx.response()
|
||||||
.setStatusCode(if (ctx.statusCode() != 200) ctx.statusCode() else 500)
|
.setStatusCode(ctx.statusCode())
|
||||||
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8")
|
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8")
|
||||||
.end(resStr)
|
.end(resStr)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class DefaultResponseHandler: ResponseHandlerInterface {
|
|||||||
.end(resStr)
|
.end(resStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun exception(ctx: RoutingContext, e: Exception) {
|
override suspend fun exception(ctx: RoutingContext, e: Throwable) {
|
||||||
logger.error { "${ctx.request().uri()}: ${ctx.failure().stackTraceToString()}" }
|
logger.error { "${ctx.request().uri()}: ${ctx.failure().stackTraceToString()}" }
|
||||||
val failure = ctx.failure()
|
val failure = ctx.failure()
|
||||||
if (failure == null) {
|
if (failure == null) {
|
||||||
|
|||||||
@ -4,5 +4,5 @@ import io.vertx.ext.web.RoutingContext
|
|||||||
|
|
||||||
interface ResponseHandlerInterface {
|
interface ResponseHandlerInterface {
|
||||||
suspend fun normal(ctx: RoutingContext, responseData: Any?, customizeResponse: Boolean = false)
|
suspend fun normal(ctx: RoutingContext, responseData: Any?, customizeResponse: Boolean = false)
|
||||||
suspend fun exception(ctx: RoutingContext, e: Exception)
|
suspend fun exception(ctx: RoutingContext, e: Throwable)
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ class RouterBuilder(
|
|||||||
routeInfo.kFunction.call(instance, *params)
|
routeInfo.kFunction.call(instance, *params)
|
||||||
}
|
}
|
||||||
responseHandler.normal(ctx, resObj, routeInfo.customizeResp)
|
responseHandler.normal(ctx, resObj, routeInfo.customizeResp)
|
||||||
} catch (e: Exception) {
|
} catch (e: Throwable) {
|
||||||
responseHandler.exception(ctx, e)
|
responseHandler.exception(ctx, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,45 +1,27 @@
|
|||||||
package org.aikrai.vertx.db
|
package org.aikrai.vertx.db
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil
|
|
||||||
import io.vertx.kotlin.coroutines.coAwait
|
import io.vertx.kotlin.coroutines.coAwait
|
||||||
import io.vertx.sqlclient.Row
|
import io.vertx.sqlclient.Row
|
||||||
import io.vertx.sqlclient.SqlClient
|
import io.vertx.sqlclient.SqlClient
|
||||||
import io.vertx.sqlclient.templates.SqlTemplate
|
import io.vertx.sqlclient.templates.SqlTemplate
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import org.aikrai.vertx.db.annotation.TableField
|
|
||||||
import org.aikrai.vertx.db.annotation.TableName
|
|
||||||
import org.aikrai.vertx.jackson.JsonUtil
|
import org.aikrai.vertx.jackson.JsonUtil
|
||||||
import org.aikrai.vertx.utlis.Meta
|
import org.aikrai.vertx.utlis.Meta
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.lang.reflect.Modifier
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
class QueryWrapperImpl<T : Any>(
|
class QueryWrapperImpl<T : Any>(
|
||||||
private val clazz: Class<T>
|
private val clazz: Class<T>,
|
||||||
|
private val tableName: String,
|
||||||
|
private val fieldMappings: Map<String, String>,
|
||||||
) : QueryWrapper<T> {
|
) : QueryWrapper<T> {
|
||||||
var sqlClient: SqlClient? = null
|
var sqlClient: SqlClient? = null
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger { }
|
private val logger = KotlinLogging.logger { }
|
||||||
private val conditions = CopyOnWriteArrayList<QueryCondition>()
|
private val conditions = CopyOnWriteArrayList<QueryCondition>()
|
||||||
private val sqlMap = ConcurrentHashMap<String, String>()
|
private val sqlMap = ConcurrentHashMap<String, String>()
|
||||||
|
|
||||||
private val fields: List<Field> = clazz.declaredFields.filter {
|
|
||||||
!it.isAnnotationPresent(Transient::class.java) &&
|
|
||||||
!Modifier.isStatic(it.modifiers) &&
|
|
||||||
!it.isSynthetic
|
|
||||||
}.onEach { it.isAccessible = true }
|
|
||||||
|
|
||||||
private val fieldMappings: Map<String, String> = fields.associate { field ->
|
|
||||||
val fieldAnnotation = field.getAnnotation(TableField::class.java)
|
|
||||||
val fieldName = fieldAnnotation?.value?.takeIf { it.isNotBlank() }
|
|
||||||
?: StrUtil.toUnderlineCase(field.name)
|
|
||||||
field.name to fieldName
|
|
||||||
}
|
|
||||||
|
|
||||||
private val tableName: String = clazz.getAnnotation(TableName::class.java)?.value?.takeIf { it.isNotBlank() }
|
|
||||||
?: StrUtil.toUnderlineCase(clazz.simpleName)
|
|
||||||
|
|
||||||
override fun select(vararg columns: String): QueryWrapper<T> {
|
override fun select(vararg columns: String): QueryWrapper<T> {
|
||||||
conditions.add(
|
conditions.add(
|
||||||
QueryCondition(
|
QueryCondition(
|
||||||
|
|||||||
@ -28,35 +28,65 @@ import kotlin.reflect.KProperty1
|
|||||||
open class RepositoryImpl<TId, TEntity : Any>(
|
open class RepositoryImpl<TId, TEntity : Any>(
|
||||||
private val sqlClient: SqlClient
|
private val sqlClient: SqlClient
|
||||||
) : Repository<TId, TEntity> {
|
) : Repository<TId, TEntity> {
|
||||||
|
companion object {
|
||||||
|
// classInfoCache
|
||||||
|
private val fieldsCache = ConcurrentHashMap<String, List<Field>>()
|
||||||
|
private val fieldMappingCache = ConcurrentHashMap<String, Map<String, String>>()
|
||||||
|
private val idFieldCache = ConcurrentHashMap<String, Field>()
|
||||||
|
private val idFieldNameCache = ConcurrentHashMap<String, String>()
|
||||||
|
private val tableNameCache = ConcurrentHashMap<String, String>()
|
||||||
|
// sqlCache
|
||||||
|
private val baseSqlCache = ConcurrentHashMap<String, ConcurrentHashMap<String, String>>()
|
||||||
|
private val queryClientCache = ConcurrentHashMap<String, Any>()
|
||||||
|
}
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
private val clazz: Class<TEntity> = (this::class.java.genericSuperclass as ParameterizedType)
|
private val clazz: Class<TEntity> = (this::class.java.genericSuperclass as ParameterizedType)
|
||||||
.actualTypeArguments[1] as Class<TEntity>
|
.actualTypeArguments[1] as Class<TEntity>
|
||||||
private val sqlMap = ConcurrentHashMap<String, ConcurrentHashMap<String, String>>()
|
|
||||||
private val querySqlMap = ConcurrentHashMap<String, Any>()
|
|
||||||
|
|
||||||
// 缓存字段和映射
|
// 缓存字段和映射
|
||||||
private val fields: List<Field> = clazz.declaredFields.filter {
|
private val fields: List<Field> by lazy {
|
||||||
|
fieldsCache.getOrPut(clazz.simpleName) {
|
||||||
|
clazz.declaredFields.filter {
|
||||||
!Modifier.isStatic(it.modifiers) &&
|
!Modifier.isStatic(it.modifiers) &&
|
||||||
!it.isSynthetic &&
|
!it.isSynthetic &&
|
||||||
!it.isAnnotationPresent(Transient::class.java)
|
!it.isAnnotationPresent(Transient::class.java)
|
||||||
}.onEach { it.isAccessible = true }
|
}.onEach { it.isAccessible = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val fieldMappings: Map<String, String> = fields.associate { field ->
|
private val fieldMappings: Map<String, String> by lazy {
|
||||||
|
fieldMappingCache.getOrPut(clazz.simpleName) {
|
||||||
|
fields.associate { field ->
|
||||||
val fieldAnnotation = field.getAnnotation(TableField::class.java)
|
val fieldAnnotation = field.getAnnotation(TableField::class.java)
|
||||||
val fieldName = fieldAnnotation?.value?.takeIf { it.isNotBlank() }
|
val fieldName = fieldAnnotation?.value?.takeIf { it.isNotBlank() }
|
||||||
?: StrUtil.toUnderlineCase(field.name)
|
?: StrUtil.toUnderlineCase(field.name)
|
||||||
field.name to fieldName
|
field.name to fieldName
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val idField: Field =
|
private val idField: Field by lazy {
|
||||||
clazz.declaredFields.find { it.isAnnotationPresent(TableId::class.java) }?.also { it.isAccessible = true }
|
idFieldCache.getOrPut(clazz.simpleName) {
|
||||||
?: throw IllegalArgumentException("No @Id field found in ${clazz.simpleName}")
|
clazz.declaredFields.find { it.isAnnotationPresent(TableId::class.java) }
|
||||||
|
?.also { it.isAccessible = true }
|
||||||
|
?: throw IllegalArgumentException("No @Id field in ${clazz.simpleName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val idFieldName: String = idField.getAnnotation(TableField::class.java)?.value?.takeIf { it.isNotBlank() }
|
private val idFieldName: String by lazy {
|
||||||
|
idFieldNameCache.getOrPut(clazz.simpleName) {
|
||||||
|
idField.getAnnotation(TableField::class.java)?.value?.takeIf { it.isNotBlank() }
|
||||||
?: StrUtil.toUnderlineCase(idField.name)
|
?: StrUtil.toUnderlineCase(idField.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val tableName: String = clazz.getAnnotation(TableName::class.java)?.value?.takeIf { it.isNotBlank() }
|
private val tableName: String by lazy {
|
||||||
|
tableNameCache.getOrPut(clazz.simpleName) {
|
||||||
|
clazz.getAnnotation(TableName::class.java)?.value?.takeIf { it.isNotBlank() }
|
||||||
?: StrUtil.toUnderlineCase(clazz.simpleName)
|
?: StrUtil.toUnderlineCase(clazz.simpleName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun create(t: TEntity): Int {
|
override suspend fun create(t: TEntity): Int {
|
||||||
try {
|
try {
|
||||||
@ -287,8 +317,8 @@ open class RepositoryImpl<TId, TEntity : Any>(
|
|||||||
suspend fun queryBuilder(qClazz: Class<Any>? = null): QueryWrapper<TEntity> {
|
suspend fun queryBuilder(qClazz: Class<Any>? = null): QueryWrapper<TEntity> {
|
||||||
val qClass = qClazz ?: clazz
|
val qClass = qClazz ?: clazz
|
||||||
val connection = getConnection()
|
val connection = getConnection()
|
||||||
val queryWrapper = querySqlMap.getOrPut(qClass.simpleName) {
|
val queryWrapper = queryClientCache.getOrPut(qClass.simpleName) {
|
||||||
QueryWrapperImpl(qClass)
|
QueryWrapperImpl(qClass, tableName, fieldMappings)
|
||||||
} as QueryWrapperImpl<TEntity>
|
} as QueryWrapperImpl<TEntity>
|
||||||
queryWrapper.sqlClient = connection
|
queryWrapper.sqlClient = connection
|
||||||
return queryWrapper
|
return queryWrapper
|
||||||
@ -308,7 +338,7 @@ open class RepositoryImpl<TId, TEntity : Any>(
|
|||||||
|
|
||||||
// 通用获取或创建 SQL 模板的方法
|
// 通用获取或创建 SQL 模板的方法
|
||||||
private fun getOrCreateSql(tableName: String, key: String, sqlProvider: () -> String): String {
|
private fun getOrCreateSql(tableName: String, key: String, sqlProvider: () -> String): String {
|
||||||
val tableSqlMap = sqlMap.computeIfAbsent(tableName) { ConcurrentHashMap() }
|
val tableSqlMap = baseSqlCache.getOrPut(tableName) { ConcurrentHashMap() }
|
||||||
return tableSqlMap.getOrPut(key, sqlProvider)
|
return tableSqlMap.getOrPut(key, sqlProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user