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 {
ext {
version '0.6.1'
version '0.7.0'
spring_version = "2.3.0.RELEASE"
}

View File

@@ -21,7 +21,7 @@ interface IApplication {
* 安全执行
*/
fun safeExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage {
val msg = HttpMessage(Status.Success)
val msg = HttpMessage()
try {
process(msg)
logger?.debug(this, "$name business execute success")
@@ -37,7 +37,7 @@ interface IApplication {
* 可抛出自定义异常信息的安全controller实现了异常捕获和消息组成。
*/
fun throwExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage {
val msg = HttpMessage(Status.Success)
val msg = HttpMessage()
try {
process(msg)
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.component.HttpMessage
import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage
import com.synebula.gaea.data.message.Status
import com.synebula.gaea.data.serialization.json.IJsonSerializer
import com.synebula.gaea.domain.service.ICommand
@@ -20,40 +21,44 @@ interface ICommandApp<TCommand : ICommand, TKey> : IApplication {
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
@ExceptionMessage("添加异常")
fun add(@RequestBody command: TCommand): HttpMessage {
return this.safeExecute("添加${this.name}数据失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") {
if (this.service != null) {
val msg = this.service!!.add(command)
it.load(msg)
} else {
it.status = Status.Error
it.message = "没有对应服务,无法执行该操作"
}
val msg = HttpMessage()
if (this.service != null) {
msg.load(this.service!!.add(command))
} else {
msg.status = Status.Error
msg.message = "没有对应服务,无法执行该操作"
}
return msg
}
@PutMapping("/{id:.+}")
@ExceptionMessage("更新异常")
fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage {
return this.safeExecute("更新${this.name}失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") {
if (this.service != null)
this.service!!.update(id, command)
else {
it.status = Status.Error
it.message = "没有对应服务,无法执行该操作"
}
val msg = HttpMessage()
if (this.service != null)
this.service!!.update(id, command)
else {
msg.status = Status.Error
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
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.aop.annotation.ExceptionMessage
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 org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.*
import org.springframework.stereotype.Component
import org.aspectj.lang.annotation.AfterThrowing
import org.aspectj.lang.annotation.Around
import org.springframework.beans.factory.annotation.Autowired
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()
@Autowired
@@ -26,14 +27,15 @@ class AppAspect {
@Autowired
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) {
val clazz = point.signature.declaringType
logger.error(
@@ -45,12 +47,12 @@ class AppAspect {
/**
* 环绕通知,环绕增强相当于MethodInterceptor
*/
@Around("log()")
@Around("func()")
fun around(point: ProceedingJoinPoint): Any? {
val clazz = point.signature.declaringType
val func = clazz.methods.find {
val clazz = point.`this`.javaClass //获取实际对象的类型避免获取到父类
val func = point.signature.declaringType.methods.find {
it.name == point.signature.name
}!!
}!!//获取声明类型中的方法信息
val funcAnnotations = func.annotations ?: arrayOf()
var exceptionMessage = func.name
@@ -69,17 +71,27 @@ class AppAspect {
}
return try {
val res = point.proceed()
res
point.proceed()
} catch (ex: Throwable) {
//找到类的模块名称,否则使用类名
var moduleName = clazz.name
val name = clazz.annotations.find { it is ModuleName }
if (name != null && name is ModuleName) {
moduleName = name.value
if (IApplication::class.java.isAssignableFrom(clazz)) {
moduleName = (point.`this` as IApplication).name
} else {
val name = clazz.annotations.find { it is ModuleName }
if (name != null && name is ModuleName) {
moduleName = name.value
}
}
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)
}
}

View File

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