0.7.0 修改异常日志记录为AOP切面的方式

This commit is contained in:
2021-03-23 16:35:04 +08:00
parent af9a4a86a1
commit 22d2228696
6 changed files with 84 additions and 61 deletions

View File

@@ -21,7 +21,7 @@ allprojects {
subprojects { subprojects {
ext { ext {
version '0.6.1' version '0.7.0'
spring_version = "2.3.0.RELEASE" spring_version = "2.3.0.RELEASE"
} }

View File

@@ -21,7 +21,7 @@ interface IApplication {
* 安全执行 * 安全执行
*/ */
fun safeExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage { fun safeExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage {
val msg = HttpMessage(Status.Success) val msg = HttpMessage()
try { try {
process(msg) process(msg)
logger?.debug(this, "$name business execute success") logger?.debug(this, "$name business execute success")
@@ -37,7 +37,7 @@ interface IApplication {
* 可抛出自定义异常信息的安全controller实现了异常捕获和消息组成。 * 可抛出自定义异常信息的安全controller实现了异常捕获和消息组成。
*/ */
fun throwExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage { fun throwExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage {
val msg = HttpMessage(Status.Success) val msg = HttpMessage()
try { try {
process(msg) process(msg)
logger?.debug(this, "$name business execute success") logger?.debug(this, "$name business execute success")

View File

@@ -2,6 +2,7 @@ package com.synebula.gaea.app.cmd
import com.synebula.gaea.app.IApplication import com.synebula.gaea.app.IApplication
import com.synebula.gaea.app.component.HttpMessage import com.synebula.gaea.app.component.HttpMessage
import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage
import com.synebula.gaea.data.message.Status import com.synebula.gaea.data.message.Status
import com.synebula.gaea.data.serialization.json.IJsonSerializer import com.synebula.gaea.data.serialization.json.IJsonSerializer
import com.synebula.gaea.domain.service.ICommand import com.synebula.gaea.domain.service.ICommand
@@ -20,40 +21,44 @@ interface ICommandApp<TCommand : ICommand, TKey> : IApplication {
var service: IService<TKey>? var service: IService<TKey>?
@DeleteMapping("/{id:.+}")
fun remove(@PathVariable id: TKey): HttpMessage {
return this.safeExecute("删除${this.name}[id: $id]失败") {
if (this.service != null)
it.data = this.service!!.remove(id)
else {
it.status = Status.Error
it.message = "没有对应服务,无法执行该操作"
}
}
}
@PostMapping @PostMapping
@ExceptionMessage("添加异常")
fun add(@RequestBody command: TCommand): HttpMessage { fun add(@RequestBody command: TCommand): HttpMessage {
return this.safeExecute("添加${this.name}数据失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") { val msg = HttpMessage()
if (this.service != null) { if (this.service != null) {
val msg = this.service!!.add(command) msg.load(this.service!!.add(command))
it.load(msg) } else {
} else { msg.status = Status.Error
it.status = Status.Error msg.message = "没有对应服务,无法执行该操作"
it.message = "没有对应服务,无法执行该操作"
}
} }
return msg
} }
@PutMapping("/{id:.+}") @PutMapping("/{id:.+}")
@ExceptionMessage("更新异常")
fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage { fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage {
return this.safeExecute("更新${this.name}失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") { val msg = HttpMessage()
if (this.service != null) if (this.service != null)
this.service!!.update(id, command) this.service!!.update(id, command)
else { else {
it.status = Status.Error msg.status = Status.Error
it.message = "没有对应服务,无法执行该操作" msg.message = "没有对应服务,无法执行该操作"
}
} }
return msg
}
@DeleteMapping("/{id:.+}")
@ExceptionMessage("删除异常")
fun remove(@PathVariable id: TKey): HttpMessage {
val msg = HttpMessage()
if (this.service != null)
msg.data = this.service!!.remove(id)
else {
msg.status = Status.Error
msg.message = "没有对应服务,无法执行该操作"
}
return msg
} }
} }

View File

@@ -1,5 +1,7 @@
package com.synebula.gaea.app.component.aop package com.synebula.gaea.app.component.aop
import com.fasterxml.jackson.databind.ObjectMapper
import com.synebula.gaea.app.IApplication
import com.synebula.gaea.app.component.HttpMessage import com.synebula.gaea.app.component.HttpMessage
import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage
import com.synebula.gaea.app.component.aop.annotation.Handler import com.synebula.gaea.app.component.aop.annotation.Handler
@@ -8,16 +10,15 @@ import com.synebula.gaea.data.message.Status
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
import org.aspectj.lang.JoinPoint import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.* import org.aspectj.lang.annotation.AfterThrowing
import org.springframework.stereotype.Component import org.aspectj.lang.annotation.Around
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContext
import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.core.DefaultParameterNameDiscoverer
abstract class AppAspect {
private var paramDiscover = DefaultParameterNameDiscoverer()
@Aspect
@Component
class AppAspect {
private val mapper = ObjectMapper() private val mapper = ObjectMapper()
@Autowired @Autowired
@@ -26,14 +27,15 @@ class AppAspect {
@Autowired @Autowired
lateinit var applicationContext: ApplicationContext lateinit var applicationContext: ApplicationContext
@Pointcut("within(com.synebula..app.*)") /**
fun log() { * 定义切面的方法
} */
abstract fun func()
/** /**
* 后置异常通知 * 后置异常通知
*/ */
@AfterThrowing("log()", throwing = "ex") @AfterThrowing("func()", throwing = "ex")
fun throws(point: JoinPoint, ex: Throwable) { fun throws(point: JoinPoint, ex: Throwable) {
val clazz = point.signature.declaringType val clazz = point.signature.declaringType
logger.error( logger.error(
@@ -45,12 +47,12 @@ class AppAspect {
/** /**
* 环绕通知,环绕增强相当于MethodInterceptor * 环绕通知,环绕增强相当于MethodInterceptor
*/ */
@Around("log()") @Around("func()")
fun around(point: ProceedingJoinPoint): Any? { fun around(point: ProceedingJoinPoint): Any? {
val clazz = point.signature.declaringType val clazz = point.`this`.javaClass //获取实际对象的类型避免获取到父类
val func = clazz.methods.find { val func = point.signature.declaringType.methods.find {
it.name == point.signature.name it.name == point.signature.name
}!! }!!//获取声明类型中的方法信息
val funcAnnotations = func.annotations ?: arrayOf() val funcAnnotations = func.annotations ?: arrayOf()
var exceptionMessage = func.name var exceptionMessage = func.name
@@ -69,17 +71,27 @@ class AppAspect {
} }
return try { return try {
val res = point.proceed() point.proceed()
res
} catch (ex: Throwable) { } catch (ex: Throwable) {
//找到类的模块名称,否则使用类名 //找到类的模块名称,否则使用类名
var moduleName = clazz.name var moduleName = clazz.name
val name = clazz.annotations.find { it is ModuleName } if (IApplication::class.java.isAssignableFrom(clazz)) {
if (name != null && name is ModuleName) { moduleName = (point.`this` as IApplication).name
moduleName = name.value } else {
val name = clazz.annotations.find { it is ModuleName }
if (name != null && name is ModuleName) {
moduleName = name.value
}
} }
val message = "$moduleName - $exceptionMessage" val message = "$moduleName - $exceptionMessage"
logger.error(ex, "$message, args: ${mapper.writeValueAsString(point.args)}") logger.error(
ex,
"$message。Method args ${paramDiscover.getParameterNames(func)?.contentToString()} values is ${
mapper.writeValueAsString(
point.args
)
}"
)
return HttpMessage(Status.Error, message) return HttpMessage(Status.Error, message)
} }
} }

View File

@@ -1,10 +1,13 @@
package com.synebula.gaea.app.component.aop.annotation package com.synebula.gaea.app.component.aop.annotation
import java.lang.annotation.Inherited
/** /**
* 标记方法安全执行由AOP负责try catch异常 * 标记方法安全执行由AOP负责try catch异常
* *
* @param message 异常消息 * @param message 异常消息
*/ */
@Inherited
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
annotation class ExceptionMessage(val message: String) annotation class ExceptionMessage(val message: String)

View File

@@ -2,6 +2,7 @@ package com.synebula.gaea.app.query
import com.synebula.gaea.app.IApplication import com.synebula.gaea.app.IApplication
import com.synebula.gaea.app.component.HttpMessage import com.synebula.gaea.app.component.HttpMessage
import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage
import com.synebula.gaea.data.message.Status import com.synebula.gaea.data.message.Status
import com.synebula.gaea.query.IQuery import com.synebula.gaea.query.IQuery
import com.synebula.gaea.query.Params import com.synebula.gaea.query.Params
@@ -21,26 +22,29 @@ interface IQueryApp<TView, TKey> : IApplication {
var clazz: Class<TView> var clazz: Class<TView>
@GetMapping("/{id:.+}") @GetMapping("/{id:.+}")
@ExceptionMessage("获取数据失败")
fun get(@PathVariable id: TKey): HttpMessage { fun get(@PathVariable id: TKey): HttpMessage {
return this.doQuery("获取${this.name}数据失败") { return this.doQuery {
this.query!!.get(id, clazz) this.query!!.get(id, clazz)
} }
} }
@GetMapping @GetMapping
@ExceptionMessage("获取列表数据失败")
fun list(@RequestParam params: LinkedHashMap<String, Any>): HttpMessage { fun list(@RequestParam params: LinkedHashMap<String, Any>): HttpMessage {
return this.doQuery("获取${this.name}列表数据失败") { return this.doQuery {
this.query!!.list(params, clazz) this.query!!.list(params, clazz)
} }
} }
@GetMapping("/segments/{size}/pages/{page}") @GetMapping("/segments/{size}/pages/{page}")
@ExceptionMessage("获取分页数据失败")
fun paging( fun paging(
@PathVariable size: Int, @PathVariable size: Int,
@PathVariable page: Int, @PathVariable page: Int,
@RequestParam parameters: LinkedHashMap<String, Any> @RequestParam parameters: LinkedHashMap<String, Any>
): HttpMessage { ): HttpMessage {
return this.doQuery("获取${this.name}分页数据[条数:$size,页码:$page]失败") { return this.doQuery {
val data = Params(page, size, parameters) val data = Params(page, size, parameters)
this.query!!.paging(data, clazz) this.query!!.paging(data, clazz)
} }
@@ -50,17 +54,16 @@ interface IQueryApp<TView, TKey> : IApplication {
/** /**
* 抽取查询业务判断功能 * 抽取查询业务判断功能
* *
* @param error 错误消息
* @param biz 业务执行逻辑 * @param biz 业务执行逻辑
*/ */
fun doQuery(error: String, biz: (() -> Any?)): HttpMessage { fun doQuery(biz: (() -> Any?)): HttpMessage {
return this.safeExecute(error) { val msg = HttpMessage()
if (this.query != null) { if (this.query != null) {
it.data = biz() msg.data = biz()
} else { } else {
it.status = Status.Error msg.status = Status.Error
it.message = "没有对应服务,无法执行该操作" msg.message = "没有对应服务,无法执行该操作"
}
} }
return msg
} }
} }