From 0b5d9243e88bef143ae3324ab7e933da6848c277 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 19 Mar 2021 16:52:03 +0800 Subject: [PATCH 01/25] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gaea.app/build.gradle | 1 + .../app/component/aop/AnnotationHandler.kt | 7 ++ .../gaea/app/component/aop/AppAspect.kt | 68 +++++++++++++++++++ .../app/component/aop/annotation/Handler.kt | 5 ++ .../app/component/aop/annotation/SafeExec.kt | 10 +++ 5 files changed, 91 insertions(+) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index fce0f14..5ec0269 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -1,6 +1,7 @@ dependencies { compile project(":src:gaea") compile("org.springframework.boot:spring-boot-starter-web:$spring_version") + compile("org.springframework.boot:spring-boot-starter-aop:$spring_version") compile("org.springframework.boot:spring-boot-starter-mail:$spring_version") compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' compile group: 'org.apache.poi', name: 'poi', version: '4.1.2' diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt new file mode 100644 index 0000000..ca75515 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt @@ -0,0 +1,7 @@ +package com.synebula.gaea.app.component.aop + +import java.lang.Exception + +interface AnnotationHandler { + fun handle(clazz: Class, func: String, args: Array, exception: Exception?) +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt new file mode 100644 index 0000000..84e9901 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -0,0 +1,68 @@ +package com.synebula.gaea.app.component.aop + +import com.synebula.gaea.app.component.HttpMessage +import com.synebula.gaea.app.component.aop.annotation.SafeExec +import com.synebula.gaea.data.message.Status +import org.aspectj.lang.JoinPoint +import org.aspectj.lang.ProceedingJoinPoint +import org.aspectj.lang.annotation.* +import org.springframework.stereotype.Component +import org.springframework.web.context.request.RequestContextHolder +import org.springframework.web.context.request.ServletRequestAttributes +import java.util.* + + +@Aspect +@Component +class AppAspect { + @Pointcut("within(com.synebula..app.*)") + fun log() { + } + + //后置异常通知 + @AfterThrowing("log()") + fun throws(point: JoinPoint): Any { + val clazz = point.signature.declaringType + println("${clazz.name} - ${point.signature.name}异常:${point.signature.name}") + return "error" + } + + //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行 + @After("log()") + fun after(point: JoinPoint) { + println("方法最后执行.....") + } + + //环绕通知,环绕增强,相当于MethodInterceptor + @Around("log()") + fun around(point: ProceedingJoinPoint): Any? { + val clazz = point.signature.declaringType + val func = clazz.methods.find { + it.name == point.signature.name + }!! + val clazzAnnotations = clazz.annotations + val funcAnnotations = func.annotations ?: arrayOf() + + val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes + val request = attributes.request + // 记录下请求内容 + println("URL : " + request.requestURL.toString()) + println("HTTP_METHOD : " + request.method) + println("IP : " + request.remoteAddr) + println("CLASS_METHOD : " + clazz.name + "." + point.signature.name) + println("ARGS : " + Arrays.toString(point.args)) + + return try { + val res = point.proceed() + res + } catch (ex: Throwable) { + val msg = HttpMessage(Status.Success) + for (item in funcAnnotations) { + if (item.annotationClass == SafeExec::javaClass) { + } + } + println("方法${point.signature}异常: $msg - ${ex.message}") + return "error" + } + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt new file mode 100644 index 0000000..1a1d7ca --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt @@ -0,0 +1,5 @@ +package com.synebula.gaea.app.component.aop.annotation + +import kotlin.reflect.KClass + +annotation class Handler(val value: KClass) \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt new file mode 100644 index 0000000..b5b8434 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt @@ -0,0 +1,10 @@ +package com.synebula.gaea.app.component.aop.annotation + +/** + * 标记方法安全执行,由AOP负责try catch异常 + * + * @param errorMessage 异常消息 + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class SafeExec(val errorMessage: String) From af9a4a86a1819eb38546573c37ade612fb9187fa Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 22 Mar 2021 21:36:14 +0800 Subject: [PATCH 02/25] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BD=BF=E7=94=A8aop?= =?UTF-8?q?=E7=9A=84=E6=96=B9=E5=BC=8F=E8=AE=B0=E5=BD=95=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E6=97=A5=E5=BF=97-=E5=BC=95=E5=85=A5Spring=20AOP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/synebula/gaea/app/cmd/ICommandApp.kt | 24 +++--- .../gaea/app/component/EmailMessenger.kt | 28 ++++--- .../app/component/aop/AnnotationHandler.kt | 7 -- .../gaea/app/component/aop/AppAspect.kt | 80 ++++++++++++------- .../app/component/aop/annotation/AccessLog.kt | 8 ++ .../{SafeExec.kt => ExceptionMessage.kt} | 4 +- .../app/component/aop/annotation/Handler.kt | 5 +- .../component/aop/annotation/ModuleName.kt | 8 ++ .../component/aop/handler/AccessLogHandler.kt | 29 +++++++ .../aop/handler/AnnotationHandler.kt | 8 ++ .../kotlin/com/synebula/gaea/query/Params.kt | 16 ++-- 11 files changed, 144 insertions(+), 73 deletions(-) delete mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/AccessLog.kt rename src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/{SafeExec.kt => ExceptionMessage.kt} (69%) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ModuleName.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AccessLogHandler.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index d888115..8e8fa79 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -20,6 +20,18 @@ interface ICommandApp : IApplication { var service: IService? + @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 fun add(@RequestBody command: TCommand): HttpMessage { return this.safeExecute("添加${this.name}数据失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") { @@ -33,18 +45,6 @@ interface ICommandApp : IApplication { } } - @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 = "没有对应服务,无法执行该操作" - } - } - } - @PutMapping("/{id:.+}") fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage { return this.safeExecute("更新${this.name}失败 - ${if (jsonSerializer != null) jsonSerializer?.serialize(command) else ""}") { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EmailMessenger.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EmailMessenger.kt index 28a5dca..8bfbe91 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EmailMessenger.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EmailMessenger.kt @@ -11,24 +11,21 @@ import org.springframework.stereotype.Component import java.io.File @Component -class EmailMessenger : IEmailMessenger { +class EmailMessenger(var mailSender: JavaMailSender?) : IEmailMessenger { - @Autowired - private lateinit var mailSender: JavaMailSender - - @Value("\${spring.mail.host}") + @Value("\${spring.mail.host:}") var host = "" - @Value("\${spring.mail.port}") + @Value("\${spring.mail.port:}") var port = "" - @Value("\${spring.mail.sender}") + @Value("\${spring.mail.sender:}") var sender = "" - @Value("\${spring.mail.username}") + @Value("\${spring.mail.username:}") var username = "" - @Value("\${spring.mail.password}") + @Value("\${spring.mail.password:}") var password = "" @Autowired @@ -42,13 +39,20 @@ class EmailMessenger : IEmailMessenger { * @param receivers 邮件接受者 * @param files 附件 */ - override fun sendMessage(subject: String, content: String, receivers: List, files: Map): Map { + override fun sendMessage( + subject: String, + content: String, + receivers: List, + files: Map + ): Map { val result = mutableMapOf() this.check() receivers.forEach { receiver -> result[receiver] = true + if (this.mailSender == null) + throw Exception("没有配置JavaMailSender的实现实例,请重新配置") try { - val mail = mailSender.createMimeMessage() + val mail = this.mailSender!!.createMimeMessage() val mimeMessageHelper = MimeMessageHelper(mail, true, "utf-8") mimeMessageHelper.setFrom(sender) mimeMessageHelper.setTo(receiver) @@ -59,7 +63,7 @@ class EmailMessenger : IEmailMessenger { val file = FileSystemResource(File(path)) mimeMessageHelper.addAttachment(name, file) } - mailSender.send(mail) //发送 + this.mailSender!!.send(mail) //发送 } catch (e: Exception) { logger.error(e, "发送邮件[$subject]至地址[$receiver]失败") result[receiver] = false diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt deleted file mode 100644 index ca75515..0000000 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AnnotationHandler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.synebula.gaea.app.component.aop - -import java.lang.Exception - -interface AnnotationHandler { - fun handle(clazz: Class, func: String, args: Array, exception: Exception?) -} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 84e9901..9a89728 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -1,68 +1,86 @@ package com.synebula.gaea.app.component.aop import com.synebula.gaea.app.component.HttpMessage -import com.synebula.gaea.app.component.aop.annotation.SafeExec +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.ModuleName 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.springframework.web.context.request.RequestContextHolder -import org.springframework.web.context.request.ServletRequestAttributes -import java.util.* +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.ApplicationContext +import com.fasterxml.jackson.databind.ObjectMapper @Aspect @Component class AppAspect { + private val mapper = ObjectMapper() + + @Autowired + lateinit var logger: ILogger + + @Autowired + lateinit var applicationContext: ApplicationContext + @Pointcut("within(com.synebula..app.*)") fun log() { } - //后置异常通知 - @AfterThrowing("log()") - fun throws(point: JoinPoint): Any { + /** + * 后置异常通知 + */ + @AfterThrowing("log()", throwing = "ex") + fun throws(point: JoinPoint, ex: Throwable) { val clazz = point.signature.declaringType - println("${clazz.name} - ${point.signature.name}异常:${point.signature.name}") - return "error" + logger.error( + ex, + "${clazz.name}.${point.signature.name} exception:${ex.message}, args:${mapper.writeValueAsString(point.args)}" + ) } - //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行 - @After("log()") - fun after(point: JoinPoint) { - println("方法最后执行.....") - } - - //环绕通知,环绕增强,相当于MethodInterceptor + /** + * 环绕通知,环绕增强,相当于MethodInterceptor + */ @Around("log()") fun around(point: ProceedingJoinPoint): Any? { val clazz = point.signature.declaringType val func = clazz.methods.find { it.name == point.signature.name }!! - val clazzAnnotations = clazz.annotations val funcAnnotations = func.annotations ?: arrayOf() - val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes - val request = attributes.request - // 记录下请求内容 - println("URL : " + request.requestURL.toString()) - println("HTTP_METHOD : " + request.method) - println("IP : " + request.remoteAddr) - println("CLASS_METHOD : " + clazz.name + "." + point.signature.name) - println("ARGS : " + Arrays.toString(point.args)) + var exceptionMessage = func.name + //遍历方法注解 + for (funcAnnotation in funcAnnotations) { + val annotations = funcAnnotation.annotationClass.annotations + + //尝试寻找方法注解的处理类 + val handler = annotations.find { it is Handler } + if (handler != null && handler is Handler) { + val handleClazz = applicationContext.getBean(handler.value.java) + handleClazz.handle(clazz, func, point.args) + } + if (funcAnnotation is ExceptionMessage) + exceptionMessage = funcAnnotation.message + } return try { val res = point.proceed() res } catch (ex: Throwable) { - val msg = HttpMessage(Status.Success) - for (item in funcAnnotations) { - if (item.annotationClass == SafeExec::javaClass) { - } + //找到类的模块名称,否则使用类名 + var moduleName = clazz.name + val name = clazz.annotations.find { it is ModuleName } + if (name != null && name is ModuleName) { + moduleName = name.value } - println("方法${point.signature}异常: $msg - ${ex.message}") - return "error" + val message = "$moduleName - $exceptionMessage" + logger.error(ex, "$message, args: ${mapper.writeValueAsString(point.args)}") + return HttpMessage(Status.Error, message) } } } \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/AccessLog.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/AccessLog.kt new file mode 100644 index 0000000..28015c6 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/AccessLog.kt @@ -0,0 +1,8 @@ +package com.synebula.gaea.app.component.aop.annotation + +import com.synebula.gaea.app.component.aop.handler.AccessLogHandler + +@Target(AnnotationTarget.FUNCTION) +@Handler(AccessLogHandler::class) +@Retention(AnnotationRetention.RUNTIME) +annotation class AccessLog \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt similarity index 69% rename from src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt rename to src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt index b5b8434..89af71f 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/SafeExec.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt @@ -3,8 +3,8 @@ package com.synebula.gaea.app.component.aop.annotation /** * 标记方法安全执行,由AOP负责try catch异常 * - * @param errorMessage 异常消息 + * @param message 异常消息 */ @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) -annotation class SafeExec(val errorMessage: String) +annotation class ExceptionMessage(val message: String) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt index 1a1d7ca..73b5b47 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/Handler.kt @@ -1,5 +1,8 @@ package com.synebula.gaea.app.component.aop.annotation +import com.synebula.gaea.app.component.aop.handler.AnnotationHandler import kotlin.reflect.KClass -annotation class Handler(val value: KClass) \ No newline at end of file +@Target(AnnotationTarget.ANNOTATION_CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class Handler(val value: KClass) \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ModuleName.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ModuleName.kt new file mode 100644 index 0000000..3ab6e15 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ModuleName.kt @@ -0,0 +1,8 @@ +package com.synebula.gaea.app.component.aop.annotation + +/** + * 模块的业务名称 + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class ModuleName(val value: String) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AccessLogHandler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AccessLogHandler.kt new file mode 100644 index 0000000..1898eb3 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AccessLogHandler.kt @@ -0,0 +1,29 @@ +package com.synebula.gaea.app.component.aop.handler + +import com.fasterxml.jackson.databind.ObjectMapper +import com.synebula.gaea.log.ILogger +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component +import org.springframework.web.context.request.RequestContextHolder +import org.springframework.web.context.request.ServletRequestAttributes +import java.lang.reflect.Method + +@Component +class AccessLogHandler : AnnotationHandler { + private val mapper = ObjectMapper() + + @Autowired + lateinit var logger: ILogger + + override fun handle(clazz: Class, func: Method, args: Array, exception: Exception?) { + val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes + val request = attributes.request + logger.info( + "${request.method} ${request.requestURL} from ${request.remoteAddr}, call function ${clazz.name}.${func.name}, args: ${ + mapper.writeValueAsString( + args + ) + }" + ) + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt new file mode 100644 index 0000000..ea1c4aa --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt @@ -0,0 +1,8 @@ +package com.synebula.gaea.app.component.aop.handler + +import java.lang.Exception +import java.lang.reflect.Method + +interface AnnotationHandler { + fun handle(clazz: Class, func: Method, args: Array, exception: Exception? = null) +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt index a4c5090..0362126 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt @@ -11,8 +11,8 @@ import com.synebula.gaea.query.type.Order */ data class Params(var page: Int = 1, var size: Int = 10) { - private var _parameters = mutableMapOf() - private var _orders = mutableMapOf() + private var _parameters = linkedMapOf() + private var _orders = linkedMapOf() /** * 数据索引,从0开始。表示数据在总量的第几条。(index = (page - 1) * size) @@ -24,13 +24,13 @@ data class Params(var page: Int = 1, var size: Int = 10) { /** * 排序条件。 */ - var orders: Map + var orders: LinkedHashMap set(value) { - this._orders = value.toMutableMap() + this._orders = value } get() { if (this._parameters.keys.count { it.startsWith("@") } > 0) { - val params = mutableMapOf() + val params = linkedMapOf() this._parameters.forEach { if (it.key.startsWith("@")) { this._orders[it.key.removePrefix("@")] = Order.valueOf(it.value.toString()) @@ -45,13 +45,13 @@ data class Params(var page: Int = 1, var size: Int = 10) { /** * 查询条件。 */ - var parameters: Map + var parameters: LinkedHashMap set(value) { - this._parameters = value.toMutableMap() + this._parameters = value } get() { if (this._parameters.keys.count { it.startsWith("@") } > 0) { - val params = mutableMapOf() + val params = linkedMapOf() this._parameters.forEach { if (it.key.startsWith("@")) { this._orders[it.key.removePrefix("@")] = Order.valueOf(it.value.toString()) From 22d2228696c0e307084d4af434af4ed7dd3c5eaa Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 23 Mar 2021 16:35:04 +0800 Subject: [PATCH 03/25] =?UTF-8?q?0.7.0=20=E4=BF=AE=E6=94=B9=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E4=B8=BAAOP?= =?UTF-8?q?=E5=88=87=E9=9D=A2=E7=9A=84=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/synebula/gaea/app/IApplication.kt | 4 +- .../com/synebula/gaea/app/cmd/ICommandApp.kt | 57 ++++++++++--------- .../gaea/app/component/aop/AppAspect.kt | 52 ++++++++++------- .../aop/annotation/ExceptionMessage.kt | 3 + .../com/synebula/gaea/app/query/IQueryApp.kt | 27 +++++---- 6 files changed, 84 insertions(+), 61 deletions(-) diff --git a/build.gradle b/build.gradle index 8e5492c..fa4a7ee 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.6.1' + version '0.7.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt index 767ffa9..b5d3251 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt @@ -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") diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index 8e8fa79..8022e00 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -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 : IApplication { var service: IService? - @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 } } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 9a89728..45a02cd 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -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) } } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt index 89af71f..6d218a2 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt @@ -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) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt index 608d2aa..f3daa0e 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt @@ -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 : IApplication { var clazz: Class @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): 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 ): 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 : 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 } } \ No newline at end of file From d7912ee4bcfd7a0c6586379a2d0245f2d5cbc29c Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 31 Mar 2021 20:10:23 +0800 Subject: [PATCH 04/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fa4a7ee..9ec2799 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ subprojects { buildscript { repositories { mavenLocal() - maven { url 'http://maven.aliyuMongoRepositoryn.com/nexus/content/groups/public/' } + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } mavenCentral() } } From e0bf7df010af44012aca9f04fc854eae4ac6a081 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 31 Mar 2021 20:36:17 +0800 Subject: [PATCH 05/25] add message status --- .../kotlin/com/synebula/gaea/data/message/Status.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt index 179549e..c8baa33 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt @@ -6,11 +6,21 @@ object Status { */ const val Success = 200 + /** + * 重新授权 + */ + const val Reauthorize = 205 + /** * 失败 */ const val Failure = 400 + /** + * 未授权 + */ + const val Unauthorized = 401 + /** * 错误 */ From 0dd1d099162e34e4666718f0bf397558ebc8a94f Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 1 Apr 2021 20:20:33 +0800 Subject: [PATCH 06/25] =?UTF-8?q?=E5=BC=95=E5=85=A5GSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gaea.app/build.gradle | 1 + .../kotlin/com/synebula/gaea/app/component/HttpMessage.kt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index 5ec0269..0cd2a26 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -5,6 +5,7 @@ dependencies { compile("org.springframework.boot:spring-boot-starter-mail:$spring_version") compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' compile group: 'org.apache.poi', name: 'poi', version: '4.1.2' + compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' } publishing { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt index c463c1d..7b24bc6 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt @@ -1,5 +1,6 @@ package com.synebula.gaea.app.component +import com.google.gson.Gson import com.synebula.gaea.data.message.DataMessage class HttpMessage() : DataMessage() { @@ -22,4 +23,8 @@ class HttpMessage() : DataMessage() { this.message = msg.message this.data = msg.data } + + override fun toString(): String { + return Gson().toJson(this) + } } \ No newline at end of file From 0c33f6a919bacd9ec60874fee660a5e7e1ecbf73 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 1 Apr 2021 22:44:21 +0800 Subject: [PATCH 07/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9Message=E7=9A=84success?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E4=B8=BA=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/synebula/gaea/data/message/Message.kt | 4 +--- .../main/kotlin/com/synebula/gaea/domain/service/Service.kt | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt index c946c9e..c003dca 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt @@ -9,9 +9,7 @@ open class Message { /** * 获取状态是否成功 */ - val success: Boolean - get() = this.status == Status.Success - + fun success(): Boolean = this.status == Status.Success /** * 附带提示消息 diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt index 1c5f23f..5b4600b 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt @@ -68,8 +68,8 @@ open class Service, TKey>( var msg: Message for (func in functions) { msg = func(id) - if (!msg.success) { - throw java.lang.RuntimeException(msg.message) + if (!msg.success()) { + throw RuntimeException(msg.message) } } this.repository.remove(id, this.clazz) From c1d2359ef3e54ab5bea1c0d06b41d35e3c44f849 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 5 Apr 2021 23:00:08 +0800 Subject: [PATCH 08/25] =?UTF-8?q?=E5=A2=9E=E5=8A=A0eventbus=EF=BC=8C?= =?UTF-8?q?=E9=BB=98=E8=AE=A4guava=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- src/gaea.app/build.gradle | 2 + .../synebula/gaea/app/component/EventBus.kt | 42 +++++++++++++++++ .../component/EventBusSubscriberProcessor.kt | 45 +++++++++++++++++++ .../kotlin/com/synebula/gaea/event/IEvent.kt | 4 ++ .../com/synebula/gaea/event/IEventBus.kt | 28 ++++++++++++ 6 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBus.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBusSubscriberProcessor.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/event/IEvent.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/event/IEventBus.kt diff --git a/build.gradle b/build.gradle index 9ec2799..2076d88 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.7.0' + version '0.8.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index 0cd2a26..d748678 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -6,6 +6,8 @@ dependencies { compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' compile group: 'org.apache.poi', name: 'poi', version: '4.1.2' compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' + compile group: 'com.google.guava', name: 'guava', version: '30.1.1-jre' + } publishing { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBus.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBus.kt new file mode 100644 index 0000000..8448054 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBus.kt @@ -0,0 +1,42 @@ +package com.synebula.gaea.app.component + +import com.google.common.eventbus.AsyncEventBus +import com.google.common.eventbus.EventBus +import com.synebula.gaea.event.IEvent +import com.synebula.gaea.event.IEventBus +import org.springframework.stereotype.Component +import java.util.concurrent.Executors + +@Component +class EventBus : IEventBus { + + /** + * 同步事件总线 + */ + var eventBus = EventBus() + + /** + * 异步事件总线 + */ + var asyncEventBus = AsyncEventBus(Executors.newFixedThreadPool(2)) + + override fun register(obj: Any) { + eventBus.register(obj) + asyncEventBus.register(obj) + } + + override fun unregister(obj: Any) { + eventBus.unregister(obj) + asyncEventBus.unregister(obj) + } + + override fun publish(event: IEvent) { + eventBus.post(event) + } + + override fun publishAsync(event: IEvent) { + asyncEventBus.post(event) + } + +} + diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBusSubscriberProcessor.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBusSubscriberProcessor.kt new file mode 100644 index 0000000..98226c4 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/EventBusSubscriberProcessor.kt @@ -0,0 +1,45 @@ +package com.synebula.gaea.app.component + +import com.google.common.eventbus.Subscribe +import com.synebula.gaea.event.IEventBus +import org.springframework.beans.BeansException +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.BeanPostProcessor +import org.springframework.stereotype.Component +import java.lang.reflect.Method + + +@Component +class EventBusSubscriberProcessor : BeanPostProcessor { + + // 事件总线bean由Spring IoC容器负责创建,这里只需要通过@Autowired注解注入该bean即可使用事件总线 + @Autowired + var eventBus: IEventBus? = null + + @Throws(BeansException::class) + override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any { + return bean + } + + //对于每个容器执行了初始化的 bean,如果这个 bean 的某个方法注解了@Subscribe,则将该 bean 注册到事件总线 + @Throws(BeansException::class) + override fun postProcessAfterInitialization(bean: Any, beanName: String): Any { + // for each method in the bean + val methods: Array = bean.javaClass.methods + for (method in methods) { + // check the annotations on that method + val annotations: Array = method.getAnnotations() + for (annotation in annotations) { + // if it contains the Subscribe annotation + if (annotation.annotationClass == Subscribe::class) { + // 如果这是一个Guava @Subscribe注解的事件监听器方法,说明所在bean实例 + // 对应一个Guava事件监听器类,将该bean实例注册到Guava事件总线 + eventBus?.register(bean) + return bean + } + } + } + return bean + } + +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEvent.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEvent.kt new file mode 100644 index 0000000..59132cb --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEvent.kt @@ -0,0 +1,4 @@ +package com.synebula.gaea.event + +interface IEvent { +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEventBus.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEventBus.kt new file mode 100644 index 0000000..c0b6850 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/event/IEventBus.kt @@ -0,0 +1,28 @@ +package com.synebula.gaea.event + +interface IEventBus { + + /** + * 注册事件Listener + * @param obj Listener所在类 + */ + fun register(obj: Any) + + /** + * 取消注册事件Listener + * @param obj Listener所在类 + */ + fun unregister(obj: Any) + + /** + * 同步发布事件 + * @param event 事件 + */ + fun publish(event: IEvent) + + /** + * 异步发布事件 + * @param event 事件 + */ + fun publishAsync(event: IEvent) +} \ No newline at end of file From 3ea9b815b89a6f37ce6ebb7a173b745affa03420 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 6 Apr 2021 21:53:29 +0800 Subject: [PATCH 09/25] =?UTF-8?q?0.9.0=20=E5=A2=9E=E5=8A=A0JWT=E5=92=8CSpr?= =?UTF-8?q?ing=20Security=E4=BF=9D=E8=AF=81=E5=AE=89=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- src/gaea.app/build.gradle | 11 +- .../com/synebula/gaea/app/IApplication.kt | 23 ++- .../com/synebula/gaea/app/cmd/ICommandApp.kt | 2 +- .../gaea/app/component/aop/AppAspect.kt | 2 +- .../app/component/poi/{excel => }/Excel.kt | 12 +- .../app/component/security/TokenManager.kt | 131 ++++++++++++++++++ .../component/security/WebAuthorization.kt | 43 ++++++ .../app/component/security/WebSecurity.kt | 64 +++++++++ .../com/synebula/gaea/app/query/IQueryApp.kt | 2 +- .../poi/excel => struct}/ExcelData.kt | 2 +- .../app/{component => struct}/HttpMessage.kt | 2 +- .../exception/TokenCloseExpireException.kt | 5 + 13 files changed, 287 insertions(+), 14 deletions(-) rename src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/{excel => }/Excel.kt (91%) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/TokenManager.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebAuthorization.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt rename src/gaea.app/src/main/kotlin/com/synebula/gaea/app/{component/poi/excel => struct}/ExcelData.kt (75%) rename src/gaea.app/src/main/kotlin/com/synebula/gaea/app/{component => struct}/HttpMessage.kt (94%) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/exception/TokenCloseExpireException.kt diff --git a/build.gradle b/build.gradle index 2076d88..ed8f93f 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.8.0' + version '0.9.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index d748678..6c6bae8 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -1,13 +1,22 @@ +buildscript { + dependencies { + classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version") + } +} + +apply plugin: 'kotlin-spring' + dependencies { compile project(":src:gaea") compile("org.springframework.boot:spring-boot-starter-web:$spring_version") compile("org.springframework.boot:spring-boot-starter-aop:$spring_version") compile("org.springframework.boot:spring-boot-starter-mail:$spring_version") + compile("org.springframework.boot:spring-boot-starter-security:$spring_version") compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' compile group: 'org.apache.poi', name: 'poi', version: '4.1.2' compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' compile group: 'com.google.guava', name: 'guava', version: '30.1.1-jre' - + compile group: 'com.auth0', name: 'java-jwt', version: '3.14.0' } publishing { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt index b5d3251..56bf9fa 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt @@ -1,8 +1,10 @@ package com.synebula.gaea.app -import com.synebula.gaea.app.component.HttpMessage +import com.google.gson.Gson +import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.data.message.Status import com.synebula.gaea.log.ILogger +import org.springframework.security.core.context.SecurityContextHolder interface IApplication { @@ -47,4 +49,23 @@ interface IApplication { } return msg } + + /** + * 获取用户信息 + * @param clazz 用户信息结构类 + */ + fun sessionUser(clazz: Class): T? { + try { + val authentication = SecurityContextHolder.getContext().authentication.principal.toString() + try { + val gson = Gson() + return gson.fromJson(authentication, clazz) + } catch (ex: Exception) { + logger?.error(this, ex, "[$name]解析用户信息异常!用户信息:$authentication: ${ex.message}") + } + } catch (ex: Exception) { + logger?.error(this, ex, "[$name]获取用户信息异常!${ex.message}") + } + return null + } } \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index 8022e00..b17a444 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -1,7 +1,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.struct.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 diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 45a02cd..5876a28 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -2,7 +2,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.struct.HttpMessage 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.ModuleName diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/Excel.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt similarity index 91% rename from src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/Excel.kt rename to src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt index 3d0d179..76ab78d 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/Excel.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt @@ -1,5 +1,6 @@ -package com.synebula.gaea.app.component.poi.excel +package com.synebula.gaea.app.component.poi +import com.synebula.gaea.app.struct.ExcelData import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFCellStyle import org.apache.poi.hssf.usermodel.HSSFWorkbook @@ -9,7 +10,6 @@ import org.apache.poi.ss.usermodel.Sheet import org.apache.poi.ss.usermodel.VerticalAlignment import java.lang.Exception import java.lang.RuntimeException -import kotlin.math.ceil /** * Excel操作对象 @@ -35,7 +35,7 @@ object Excel { val titleFont = wb.createFont() titleFont.bold = true titleStyle.setFont(titleFont) - this.setBorderStyle(titleStyle, BorderStyle.THIN) + setBorderStyle(titleStyle, BorderStyle.THIN) //声明列对象 // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制 @@ -48,7 +48,7 @@ object Excel { cell = row.createCell(col) cell.setCellStyle(titleStyle) cell.setCellValue(data.columnNames[col]) - this.setColumnWidth(data.columnNames[col], col, sheet) + setColumnWidth(data.columnNames[col], col, sheet) } catch (ex: RuntimeException) { throw Exception("创建索引${col}列[${data.columnNames[col]}]时出现异常", ex) } @@ -57,7 +57,7 @@ object Excel { val contentStyle = wb.createCellStyle() contentStyle.alignment = HorizontalAlignment.LEFT// 创建一个修改居左格式 contentStyle.verticalAlignment = VerticalAlignment.CENTER - this.setBorderStyle(contentStyle, BorderStyle.THIN) + setBorderStyle(contentStyle, BorderStyle.THIN) //创建内容 var col = 0 @@ -70,7 +70,7 @@ object Excel { cell = row.createCell(col) cell.setCellStyle(contentStyle) cell.setCellValue(data.data[i][col]) - this.setColumnWidth(data.data[i][col], col, sheet) + setColumnWidth(data.data[i][col], col, sheet) col++ } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/TokenManager.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/TokenManager.kt new file mode 100644 index 0000000..a9a4c7d --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/TokenManager.kt @@ -0,0 +1,131 @@ +package com.synebula.gaea.app.component.security + +import com.auth0.jwt.JWT +import com.auth0.jwt.algorithms.Algorithm +import com.google.gson.Gson +import com.synebula.gaea.app.struct.exception.TokenCloseExpireException +import com.synebula.gaea.log.ILogger +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component +import java.util.* + +@Component +class TokenManager { + @Autowired + private lateinit var logger: ILogger + + @Autowired + private lateinit var gson: Gson + + @Value("\${jwt.secret:}") + val secret: String = "" + + /** + * 短期有效期, 默认一天。单位分钟 + */ + @Value("\${jwt.expire.normal:${24 * 60}}") + private val normalExpire = "" + + /** + * 长期有效期, 默认一年。单位分钟 + */ + @Value("\${jwt.expire.remember:${365 * 24 * 60}}") + private val rememberExpire = "" + + /** + * 放到header的名称 + */ + val header = "token" + + /** + * 业务载荷名称 + */ + val payload = "user" + + /** + * 生成签名,5min后过期 + * + * @param user 用户 + * @return 加密的token + */ + fun sign(user: Any, remember: Boolean = false): String { + return this.sign(gson.toJson(user), remember) + } + + /** + * 生成签名,5min后过期 + * + * @param userJson 用户 Json + * @return 加密的token + */ + fun sign(userJson: String, remember: Boolean = false): String { + val milli = this.expireMilliseconds(if (remember) rememberExpire.toLong() else normalExpire.toLong()) + val date = Date(System.currentTimeMillis() + milli) + val algorithm: Algorithm = Algorithm.HMAC256(secret) + // 附带username信息 + return JWT.create() + .withClaim(this.payload, userJson) + .withIssuedAt(Date()) + .withExpiresAt(date) + .sign(algorithm) + } + + /** + * 校验token是否正确 + * + * @param token 密钥 + * @return 是否正确 + */ + fun verify(token: String, clazz: Class): T? { + try { + val now = Date() + val algorithm = Algorithm.HMAC256(secret) + val jwt = JWT.decode(token) + val remain = jwt.expiresAt.time - now.time //剩余的时间 + val total = jwt.expiresAt.time - jwt.issuedAt.time //总时间 + if (remain > 0 && 1.0 * remain / total <= 0.3) //存活时间少于总时间的1/3重新下发 + throw TokenCloseExpireException("", JWT.decode(token).getClaim("user").asString()) + + val result = JWT.require(algorithm).build().verify(token) + val json = result.getClaim(this.payload).asString() + return gson.fromJson(json, clazz) + } catch (ex: Exception) { + this.logger.debug(this, ex, "解析token出错") + throw ex + } + } + + /** + * 校验token是否正确 + * + * @param token 密钥 + * @return 是否正确 + */ + fun verify(token: String): String { + try { + val now = Date() + val algorithm = Algorithm.HMAC256(secret) + val jwt = JWT.decode(token) + val remain = jwt.expiresAt.time - now.time //剩余的时间 + val total = jwt.expiresAt.time - jwt.issuedAt.time //总时间 + if (remain > 0 && 1.0 * remain / total <= 0.3) //存活时间少于总时间的1/3重新下发 + throw TokenCloseExpireException("", JWT.decode(token).getClaim("user").asString()) + + val result = JWT.require(algorithm).build().verify(token) + return result.getClaim(payload).asString() + } catch (ex: Exception) { + this.logger.debug(this, ex, "解析token出错") + throw ex + } + } + + /** + * 获取超时毫秒 + * @param minutes 分钟数 + */ + private fun expireMilliseconds(minutes: Long): Long { + return minutes * 60 * 1000 + } +} + diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebAuthorization.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebAuthorization.kt new file mode 100644 index 0000000..1d451d4 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebAuthorization.kt @@ -0,0 +1,43 @@ +package com.synebula.gaea.app.component.security + +import com.synebula.gaea.app.struct.HttpMessage +import com.synebula.gaea.app.struct.exception.TokenCloseExpireException +import com.synebula.gaea.data.message.Status +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter +import java.io.IOException +import javax.servlet.FilterChain +import javax.servlet.ServletException +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + + +/** + * 登录成功后 走此类进行鉴权操作 + */ +class WebAuthorization(authenticationManager: AuthenticationManager, var tokenManager: TokenManager) : + BasicAuthenticationFilter(authenticationManager) { + + /** + * 在过滤之前和之后执行的事件 + */ + @Throws(IOException::class, ServletException::class) + override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) { + val token = request.getHeader(tokenManager.header) + try { + val user = tokenManager.verify(token) + val authentication = + UsernamePasswordAuthenticationToken(user, null, null) + SecurityContextHolder.getContext().authentication = authentication + super.doFilterInternal(request, response, chain) + } catch (ex: TokenCloseExpireException) { + response.status = Status.Success + response.characterEncoding = "utf-8" + response.contentType = "text/javascript;charset=utf-8" + response.writer.print(HttpMessage(Status.Reauthorize, tokenManager.sign(ex.payload), "重新下发认证消息")) + response.flushBuffer() + } + } +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt new file mode 100644 index 0000000..c0a6a43 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt @@ -0,0 +1,64 @@ +package com.synebula.gaea.app.component.security + +import com.synebula.gaea.app.struct.HttpMessage +import com.synebula.gaea.data.message.Status +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.builders.WebSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter +import org.springframework.security.config.http.SessionCreationPolicy +import org.springframework.stereotype.Component +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource +import org.springframework.web.cors.UrlBasedCorsConfigurationSource + + +@Component +@EnableWebSecurity +class WebSecurity : WebSecurityConfigurerAdapter() { + @Autowired + lateinit var tokenManager: TokenManager + + /** + * 安全配置 + */ + @Throws(Exception::class) + override fun configure(http: HttpSecurity) { + // 跨域共享 + http.cors() + .and().csrf().disable() // 跨域伪造请求限制无效 + .authorizeRequests() + .anyRequest().authenticated()// 资源任何人都可访问 + .and() + .addFilter(WebAuthorization(authenticationManager(), tokenManager))// 添加JWT鉴权拦截器 + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 设置Session的创建策略为:Spring Security永不创建HttpSession 不使用HttpSession来获取SecurityContext + .and() + .exceptionHandling() + .authenticationEntryPoint { _, response, _ -> + response.status = Status.Success + response.characterEncoding = "utf-8" + response.contentType = "text/javascript;charset=utf-8" + response.writer.print(HttpMessage(Status.Unauthorized, "用户未登录,请重新登录后尝试!")) + } + } + + @Throws(Exception::class) + override fun configure(web: WebSecurity) { + web.ignoring().antMatchers("/sign/**") + } + + /** + * 跨域配置 + * @return 基于URL的跨域配置信息 + */ + @Bean + fun corsConfigurationSource(): CorsConfigurationSource { + val source = UrlBasedCorsConfigurationSource() + // 注册跨域配置 + source.registerCorsConfiguration("/**", CorsConfiguration().applyPermitDefaultValues()) + return source + } +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt index f3daa0e..1acc70a 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt @@ -1,7 +1,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.struct.HttpMessage import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage import com.synebula.gaea.data.message.Status import com.synebula.gaea.query.IQuery diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/ExcelData.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/ExcelData.kt similarity index 75% rename from src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/ExcelData.kt rename to src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/ExcelData.kt index e00e96f..ba4cf67 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/excel/ExcelData.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/ExcelData.kt @@ -1,4 +1,4 @@ -package com.synebula.gaea.app.component.poi.excel +package com.synebula.gaea.app.struct class ExcelData(var title: String = "", var columnNames: List = listOf(), diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/HttpMessage.kt similarity index 94% rename from src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt rename to src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/HttpMessage.kt index 7b24bc6..43e8236 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/HttpMessage.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/HttpMessage.kt @@ -1,4 +1,4 @@ -package com.synebula.gaea.app.component +package com.synebula.gaea.app.struct import com.google.gson.Gson import com.synebula.gaea.data.message.DataMessage diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/exception/TokenCloseExpireException.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/exception/TokenCloseExpireException.kt new file mode 100644 index 0000000..ffe8a26 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/struct/exception/TokenCloseExpireException.kt @@ -0,0 +1,5 @@ +package com.synebula.gaea.app.struct.exception + +import com.auth0.jwt.exceptions.TokenExpiredException + +class TokenCloseExpireException(msg: String, var payload: String) : TokenExpiredException(msg) From c047f7f5f8ea1e4213891dc026ab7d37d6b38c85 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 7 Apr 2021 11:05:30 +0800 Subject: [PATCH 10/25] =?UTF-8?q?0.9.1=20=E9=87=8D=E5=91=BD=E5=90=8DExcept?= =?UTF-8?q?ionMessage=E6=B3=A8=E8=A7=A3=E4=B8=BAMethodName?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt | 8 ++++---- .../com/synebula/gaea/app/component/aop/AppAspect.kt | 10 +++++----- .../annotation/{ExceptionMessage.kt => MethodName.kt} | 6 +++--- .../kotlin/com/synebula/gaea/app/query/IQueryApp.kt | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) rename src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/{ExceptionMessage.kt => MethodName.kt} (57%) diff --git a/build.gradle b/build.gradle index ed8f93f..6edd14c 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.9.0' + version '0.9.1' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index b17a444..5ad87eb 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -2,7 +2,7 @@ package com.synebula.gaea.app.cmd import com.synebula.gaea.app.IApplication import com.synebula.gaea.app.struct.HttpMessage -import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage +import com.synebula.gaea.app.component.aop.annotation.MethodName import com.synebula.gaea.data.message.Status import com.synebula.gaea.data.serialization.json.IJsonSerializer import com.synebula.gaea.domain.service.ICommand @@ -23,7 +23,7 @@ interface ICommandApp : IApplication { @PostMapping - @ExceptionMessage("添加异常") + @MethodName("添加") fun add(@RequestBody command: TCommand): HttpMessage { val msg = HttpMessage() if (this.service != null) { @@ -36,7 +36,7 @@ interface ICommandApp : IApplication { } @PutMapping("/{id:.+}") - @ExceptionMessage("更新异常") + @MethodName("更新") fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage { val msg = HttpMessage() if (this.service != null) @@ -50,7 +50,7 @@ interface ICommandApp : IApplication { @DeleteMapping("/{id:.+}") - @ExceptionMessage("删除异常") + @MethodName("删除") fun remove(@PathVariable id: TKey): HttpMessage { val msg = HttpMessage() if (this.service != null) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 5876a28..3a400bd 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -3,7 +3,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.struct.HttpMessage -import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage +import com.synebula.gaea.app.component.aop.annotation.MethodName import com.synebula.gaea.app.component.aop.annotation.Handler import com.synebula.gaea.app.component.aop.annotation.ModuleName import com.synebula.gaea.data.message.Status @@ -55,7 +55,7 @@ abstract class AppAspect { }!!//获取声明类型中的方法信息 val funcAnnotations = func.annotations ?: arrayOf() - var exceptionMessage = func.name + var funcName = func.name //遍历方法注解 for (funcAnnotation in funcAnnotations) { val annotations = funcAnnotation.annotationClass.annotations @@ -66,8 +66,8 @@ abstract class AppAspect { val handleClazz = applicationContext.getBean(handler.value.java) handleClazz.handle(clazz, func, point.args) } - if (funcAnnotation is ExceptionMessage) - exceptionMessage = funcAnnotation.message + if (funcAnnotation is MethodName) + funcName = funcAnnotation.name } return try { @@ -83,7 +83,7 @@ abstract class AppAspect { moduleName = name.value } } - val message = "$moduleName - $exceptionMessage" + val message = "$moduleName - $funcName 异常" logger.error( ex, "$message。Method args ${paramDiscover.getParameterNames(func)?.contentToString()} values is ${ diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/MethodName.kt similarity index 57% rename from src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt rename to src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/MethodName.kt index 6d218a2..3f09685 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/ExceptionMessage.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/annotation/MethodName.kt @@ -3,11 +3,11 @@ package com.synebula.gaea.app.component.aop.annotation import java.lang.annotation.Inherited /** - * 标记方法安全执行,由AOP负责try catch异常 + * 标记方法名称,由AOP负责记录异常时使用该名称 * - * @param message 异常消息 + * @param name 异常消息 */ @Inherited @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) -annotation class ExceptionMessage(val message: String) +annotation class MethodName(val name: String) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt index 1acc70a..c6e534a 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt @@ -2,7 +2,7 @@ package com.synebula.gaea.app.query import com.synebula.gaea.app.IApplication import com.synebula.gaea.app.struct.HttpMessage -import com.synebula.gaea.app.component.aop.annotation.ExceptionMessage +import com.synebula.gaea.app.component.aop.annotation.MethodName import com.synebula.gaea.data.message.Status import com.synebula.gaea.query.IQuery import com.synebula.gaea.query.Params @@ -21,24 +21,24 @@ interface IQueryApp : IApplication { */ var clazz: Class + @MethodName("获取数据") @GetMapping("/{id:.+}") - @ExceptionMessage("获取数据失败") fun get(@PathVariable id: TKey): HttpMessage { return this.doQuery { this.query!!.get(id, clazz) } } + @MethodName("获取列表数据") @GetMapping - @ExceptionMessage("获取列表数据失败") fun list(@RequestParam params: LinkedHashMap): HttpMessage { return this.doQuery { this.query!!.list(params, clazz) } } + @MethodName("获取分页数据") @GetMapping("/segments/{size}/pages/{page}") - @ExceptionMessage("获取分页数据失败") fun paging( @PathVariable size: Int, @PathVariable page: Int, From 6c5b84fe5d47844965d482a9d5ff81732cb9ab7f Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 8 Apr 2021 00:02:32 +0800 Subject: [PATCH 11/25] =?UTF-8?q?0.10.0=20=E5=A2=9E=E5=8A=A0repository?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=B7=BB=E5=8A=A0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/synebula/gaea/mongo/repository/MongoRepository.kt | 3 +++ .../com/synebula/gaea/domain/repository/IRepository.kt | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6edd14c..1996ab2 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.9.1' + version '0.10.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt index 93d035b..06c0fd7 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt +++ b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt @@ -35,6 +35,9 @@ open class MongoRepository(private var repo: MongoTemplate) : IRepository { this.repo.save(obj) } + override fun , TKey> add(obj: List, clazz: Class) { + this.repo.insert(obj, clazz) + } override fun count(params: Map?, clazz: Class): Int { val query = Query() diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt index 2d6e582..83dba92 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt @@ -15,6 +15,14 @@ interface IRepository { */ fun , TKey> add(obj: TAggregateRoot, clazz: Class) + /** + * 插入多个个对象。 + * + * @param obj 需要插入的对象。 + * @return 返回原对象,如果对象ID为自增,则补充自增ID。 + */ + fun , TKey> add(obj: List, clazz: Class) + /** * 更新对象。 * From 117ed25cee4e1b63e9bc933ee8aaaa6f2668716f Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 9 Apr 2021 00:21:07 +0800 Subject: [PATCH 12/25] =?UTF-8?q?=200.10.1=20=E6=B7=BB=E5=8A=A0=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E7=B1=BB=E5=9E=8B=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/synebula/gaea/data/date/DateTime.kt | 181 +++++++++++++++++- 2 files changed, 179 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 1996ab2..df48694 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.10.0' + version '0.10.1' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt index 8348d94..6163127 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt @@ -25,7 +25,15 @@ class DateTime : Comparable { /** * 列出时间的级别数组 */ - private val calendarLevel = intArrayOf(Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR) + private val calendarLevel = intArrayOf( + Calendar.MILLISECOND, + Calendar.SECOND, + Calendar.MINUTE, + Calendar.HOUR_OF_DAY, + Calendar.DAY_OF_MONTH, + Calendar.MONTH, + Calendar.YEAR + ) val date: Date get() = calendar.time @@ -43,35 +51,147 @@ class DateTime : Comparable { return instance.time } + /** + * 当前时间年 + */ var year: Int get() = calendar.get(Calendar.YEAR) set(value) = calendar.set(Calendar.YEAR, value) + /** + * 当前时间月 + */ var month: Int get() = calendar.get(Calendar.MONTH) set(value) = calendar.set(Calendar.MONTH, value) + /** + * 当前时间天 + */ var day: Int get() = calendar.get(Calendar.DAY_OF_MONTH) set(value) = calendar.set(Calendar.DAY_OF_MONTH, value) + /** + * 获取时间 + */ val time: Time get() = Time(calendar.time) - val firstDay: DateTime + /** + * 获取当月天数 + */ + val days: Int + get() { + return this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + } + + /** + * 当前月第一天 + */ + val firstDayOfMonth: DateTime get() { val instance = calendar.clone() as Calendar instance.set(Calendar.DAY_OF_MONTH, 1) return DateTime(instance) } - val lastDay: DateTime + /** + * 当前月最后一天 + */ + val lastDayOfMonth: DateTime get() { val instance = calendar.clone() as Calendar instance.set(Calendar.DAY_OF_MONTH, instance.getActualMaximum(Calendar.DAY_OF_MONTH)) return DateTime(instance) } + /** + * 当前周第一天 + */ + val firstDayOfWeek: DateTime + get() { + val instance = calendar.clone() as Calendar + instance.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY) + instance.set(Calendar.HOUR_OF_DAY, 0) + instance.set(Calendar.MINUTE, 0) + instance.set(Calendar.SECOND, 0) + instance.set(Calendar.MILLISECOND, 0) + return DateTime(instance) + } + + /** + * 当前周最后一天 + */ + val lastDayOfWeek: DateTime + get() { + val instance = this.firstDayOfWeek.calendar.clone() as Calendar + instance.add(Calendar.DAY_OF_WEEK, 6)//当前周第一天加6天 + instance.set(Calendar.HOUR_OF_DAY, 23) + instance.set(Calendar.MINUTE, 59) + instance.set(Calendar.SECOND, 59) + instance.set(Calendar.MILLISECOND, 0) + return DateTime(instance) + } + + /** + * 当前天最早时间 + */ + val earliestTime: DateTime + get() { + val instance = this.calendar.clone() as Calendar + instance.set(Calendar.HOUR_OF_DAY, 0) + instance.set(Calendar.MINUTE, 0) + instance.set(Calendar.SECOND, 0) + instance.set(Calendar.MILLISECOND, 0) + return DateTime(instance) + } + + /** + * 当前天最晚时间 + */ + val latestTime: DateTime + get() { + val instance = this.calendar.clone() as Calendar + instance.set(Calendar.HOUR_OF_DAY, 23) + instance.set(Calendar.MINUTE, 59) + instance.set(Calendar.SECOND, 59) + instance.set(Calendar.MILLISECOND, 0) + return DateTime(instance) + } + + /** + * 当前时间最上一月 + */ + val previousMonth: DateTime + get() { + return this.addMonth(-1) + } + + /** + * 当前时间下一月 + */ + val nextMonth: DateTime + get() { + return this.addMonth(1) + } + + /** + * 当前时间最上一天 + */ + val previousDay: DateTime + get() { + return this.addDay(-1) + } + + /** + * 当前时间下一天 + */ + val nextDay: DateTime + get() { + return this.addDay(1) + } + /** * 从Date格式转化 */ @@ -188,6 +308,61 @@ class DateTime : Comparable { } } + /** + * 判断当前时间是否在某时间后 + * + * @param other 另一时间 + */ + fun after(other: DateTime): Boolean { + return this.date.after(other.date) + } + + /** + * 判断当前时间是否在某时间前 + * + * @param other 另一时间 + */ + fun before(other: DateTime): Boolean { + return this.date.before(other.date) + } + + /** + * 加减月份。 + * + * @param month 月份。可以为负数,即为减。 + */ + fun addMonth(month: Int): DateTime { + val instance = calendar.clone() as Calendar + instance.add(Calendar.MONTH, month) + return DateTime(instance) + } + + /** + * 加减日期。 + * + * @param day 天数。可以为负数,即为减。 + */ + fun addDay(day: Int): DateTime { + val instance = calendar.clone() as Calendar + instance.add(Calendar.DAY_OF_MONTH, day) + return DateTime(instance) + } + + /** + * 当前天是否工作日 + */ + fun isWorkday(): Boolean { + return !this.isWeekend() + } + + /** + * 当前天是否周末 + */ + fun isWeekend(): Boolean { + val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) + return (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) + } + operator fun minus(other: DateTime): TimeSpan { return TimeSpan(this.milliseconds - other.milliseconds) } From 038ed84a1e027561ad022b6a21c9a665aaa1f2f0 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 11 Apr 2021 16:13:20 +0800 Subject: [PATCH 13/25] =?UTF-8?q?0.10.2=20=E4=BF=AE=E5=A4=8D=E8=B7=A8?= =?UTF-8?q?=E5=9F=9F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../app/component/security/WebSecurity.kt | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index df48694..41816a9 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.10.1' + version '0.10.2' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt index c0a6a43..3efed1f 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt @@ -13,6 +13,7 @@ import org.springframework.stereotype.Component import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import java.util.* @Component @@ -28,21 +29,21 @@ class WebSecurity : WebSecurityConfigurerAdapter() { override fun configure(http: HttpSecurity) { // 跨域共享 http.cors() - .and().csrf().disable() // 跨域伪造请求限制无效 - .authorizeRequests() - .anyRequest().authenticated()// 资源任何人都可访问 - .and() - .addFilter(WebAuthorization(authenticationManager(), tokenManager))// 添加JWT鉴权拦截器 - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 设置Session的创建策略为:Spring Security永不创建HttpSession 不使用HttpSession来获取SecurityContext - .and() - .exceptionHandling() - .authenticationEntryPoint { _, response, _ -> - response.status = Status.Success - response.characterEncoding = "utf-8" - response.contentType = "text/javascript;charset=utf-8" - response.writer.print(HttpMessage(Status.Unauthorized, "用户未登录,请重新登录后尝试!")) - } + .and().csrf().disable() // 跨域伪造请求限制无效 + .authorizeRequests() + .anyRequest().authenticated()// 资源任何人都可访问 + .and() + .addFilter(WebAuthorization(authenticationManager(), tokenManager))// 添加JWT鉴权拦截器 + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 设置Session的创建策略为:Spring Security永不创建HttpSession 不使用HttpSession来获取SecurityContext + .and() + .exceptionHandling() + .authenticationEntryPoint { _, response, _ -> + response.status = Status.Success + response.characterEncoding = "utf-8" + response.contentType = "text/javascript;charset=utf-8" + response.writer.print(HttpMessage(Status.Unauthorized, "用户未登录,请重新登录后尝试!")) + } } @Throws(Exception::class) @@ -56,9 +57,15 @@ class WebSecurity : WebSecurityConfigurerAdapter() { */ @Bean fun corsConfigurationSource(): CorsConfigurationSource { + val configuration = CorsConfiguration() + configuration.allowedOrigins = listOf("*") + configuration.allowedMethods = listOf("*") + configuration.allowedHeaders = listOf("*") + // 如果所有的属性不全部配置,一定要执行该方法 + configuration.applyPermitDefaultValues() val source = UrlBasedCorsConfigurationSource() // 注册跨域配置 - source.registerCorsConfiguration("/**", CorsConfiguration().applyPermitDefaultValues()) + source.registerCorsConfiguration("/**", configuration) return source } } From a8a13fd7f1c81fa30f121b6fc5ea2fbdfc705c5f Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 12 Apr 2021 22:38:41 +0800 Subject: [PATCH 14/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=9A=84=E6=8F=90=E7=A4=BA=E9=97=AE=E9=A2=98?= =?UTF-8?q?;=20=E4=BF=AE=E5=A4=8DInt=E7=B1=BB=E5=9E=8B=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt | 7 ++++++- .../src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt | 8 ++++++-- .../kotlin/com/synebula/gaea/domain/service/Service.kt | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 41816a9..1a019b2 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.10.2' + version '0.10.3' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index 5ad87eb..4a4bf4b 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -54,7 +54,12 @@ interface ICommandApp : IApplication { fun remove(@PathVariable id: TKey): HttpMessage { val msg = HttpMessage() if (this.service != null) - msg.data = this.service!!.remove(id) + try { + msg.data = this.service!!.remove(id) + } catch (ex: IllegalStateException) { + msg.status = Status.Error + msg.message = ex.message ?: "" + } else { msg.status = Status.Error msg.message = "没有对应服务,无法执行该操作" diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt index 4980f82..1c1349f 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt +++ b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt @@ -42,8 +42,12 @@ fun Query.where( //日期类型特殊处理为String类型 val fieldType = onFieldType(key) - if (fieldType != null && value.javaClass != fieldType && fieldType == Date::class.java) { - value = DateTime(value.toString(), "yyyy-MM-dd HH:mm:ss").date + if (fieldType != null && value.javaClass != fieldType) { + when (fieldType) { + Date::class.java -> value = DateTime(value.toString(), "yyyy-MM-ddTHH:mm:ss").date + Int::class.java -> value = value.toString().toInt() + Integer::class.java -> value = value.toString().toInt() + } } val where = onWhere(key) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt index 5b4600b..c68a1f1 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt @@ -69,7 +69,7 @@ open class Service, TKey>( for (func in functions) { msg = func(id) if (!msg.success()) { - throw RuntimeException(msg.message) + throw IllegalStateException(msg.message) } } this.repository.remove(id, this.clazz) From 274f8625157cf51a272c12be70e70ad63088b9c8 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 16 Apr 2021 09:37:43 +0800 Subject: [PATCH 15/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9DateTime=20between=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/synebula/gaea/data/date/DateTime.kt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt index 6163127..b227570 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt @@ -26,13 +26,13 @@ class DateTime : Comparable { * 列出时间的级别数组 */ private val calendarLevel = intArrayOf( - Calendar.MILLISECOND, - Calendar.SECOND, - Calendar.MINUTE, - Calendar.HOUR_OF_DAY, - Calendar.DAY_OF_MONTH, - Calendar.MONTH, - Calendar.YEAR + Calendar.MILLISECOND, + Calendar.SECOND, + Calendar.MINUTE, + Calendar.HOUR_OF_DAY, + Calendar.DAY_OF_MONTH, + Calendar.MONTH, + Calendar.YEAR ) val date: Date @@ -279,7 +279,8 @@ class DateTime : Comparable { * @return 是否。 */ fun between(start: DateTime, end: DateTime): Boolean { - return this in start..end + //return this in start..end + return start.dateNoTime.compareTo(this.dateNoTime) * this.dateNoTime.compareTo(end.dateNoTime) >= 0 } /** From 5fb26fc7e16624f4cfe7273fe06f7ece8775c896 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 13 May 2021 19:06:39 +0800 Subject: [PATCH 16/25] =?UTF-8?q?=200.11.0=20=E5=A2=9E=E5=8A=A0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9DateTime=E7=B1=BB=E5=9E=8B=E6=96=B9=E6=B3=95=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9Repo=20get=E6=96=B9=E6=B3=95=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../gaea/mongo/repository/MongoRepository.kt | 4 +- .../com/synebula/gaea/data/date/AlignTime.kt | 10 +- .../com/synebula/gaea/data/date/DateTime.kt | 196 +++++++++++++++--- .../gaea/domain/repository/IRepository.kt | 2 +- 5 files changed, 176 insertions(+), 38 deletions(-) diff --git a/build.gradle b/build.gradle index 1a019b2..8562eaa 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.10.3' + version '0.11.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt index 06c0fd7..75c7869 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt +++ b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongoRepository.kt @@ -20,8 +20,8 @@ open class MongoRepository(private var repo: MongoTemplate) : IRepository { override fun , TKey> get( id: TKey, clazz: Class - ): TAggregateRoot { - return this.repo.findOne(whereId(id), clazz) as TAggregateRoot + ): TAggregateRoot? { + return this.repo.findOne(whereId(id), clazz) } override fun , TKey> update( diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/AlignTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/AlignTime.kt index 0b10fe4..76b4a1f 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/AlignTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/AlignTime.kt @@ -1,6 +1,8 @@ package com.synebula.gaea.data.date import java.util.* +import kotlin.math.ceil +import kotlin.math.floor /** * 校准时间。 @@ -61,9 +63,9 @@ class AlignTime { */ fun ceilingTime(lastTime: DateTime, intervalSeconds: Int): DateTime { val span = lastTime - this.baseTime - val count = Math.ceil(span.totalSeconds / intervalSeconds).toInt() + val count = ceil(span.totalSeconds / intervalSeconds).toInt() val newTime = DateTime(this.baseTime.date) - newTime.addSeconds(count * intervalSeconds * 1L) + newTime.addSecond(count * intervalSeconds) return newTime } @@ -97,9 +99,9 @@ class AlignTime { */ fun floorTime(lastTime: DateTime, intervalSeconds: Int): DateTime { val span = lastTime - this.baseTime - val count = Math.floor(span.totalSeconds / intervalSeconds).toInt() + val count = floor(span.totalSeconds / intervalSeconds).toInt() val newTime = DateTime(this.baseTime.date) - newTime.addSeconds(count * intervalSeconds * 1L) + newTime.addSecond(count * intervalSeconds) return newTime } } \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt index b227570..03a0eab 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt @@ -7,7 +7,7 @@ import java.util.* /** * 时间格式,方便用于获取Date格式的多种形式 */ -class DateTime : Comparable { +class DateTime() : Comparable { // 内部存储日历格式方便操作 /** @@ -195,28 +195,25 @@ class DateTime : Comparable { /** * 从Date格式转化 */ - constructor(date: Date) { + constructor(date: Date) : this() { this.calendar.time = date - this.calendar.set(Calendar.MILLISECOND, 0) } /** * 从Calendar格式转化 */ - constructor(calendar: Calendar) { + constructor(calendar: Calendar) : this() { this.calendar = calendar - this.calendar.set(Calendar.MILLISECOND, 0) } /** * 从Date格式转化 */ - constructor(date: String, format: String) { + constructor(date: String, format: String = "yyyy-MM-dd HH:mm:ss") : this() { val formatter = SimpleDateFormat(format) try { val value = formatter.parse(date) this.calendar.time = value - this.calendar.set(Calendar.MILLISECOND, 0) } catch (e: ParseException) { throw RuntimeException("date string can't format to date", e) } @@ -225,9 +222,8 @@ class DateTime : Comparable { /** * 从Date格式转化。需要注意的是月0代表是一月,以此类推。 */ - constructor(year: Int, month: Int, day: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0) { + constructor(year: Int, month: Int, day: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0) : this() { this.calendar.set(year, month, day, hour, minute, second) - this.calendar.set(Calendar.MILLISECOND, 0) } /** @@ -294,25 +290,12 @@ class DateTime : Comparable { return this.compareTo(start, level) >= 0 && this.compareTo(end, level) <= 0 } - /** - * 增加秒 - */ - fun addSeconds(seconds: Long) { - if (seconds <= Int.MAX_VALUE) - this.calendar.add(Calendar.SECOND, seconds.toInt()) - else { - val span = TimeSpan(seconds * 1000) - this.calendar.add(Calendar.DAY_OF_MONTH, span.day) - this.calendar.add(Calendar.HOUR_OF_DAY, span.hour) - this.calendar.add(Calendar.MINUTE, span.minute) - this.calendar.add(Calendar.SECOND, span.second) - } - } /** * 判断当前时间是否在某时间后 * * @param other 另一时间 + * @return new DateTime object */ fun after(other: DateTime): Boolean { return this.date.after(other.date) @@ -322,31 +305,165 @@ class DateTime : Comparable { * 判断当前时间是否在某时间前 * * @param other 另一时间 + * @return new DateTime object */ fun before(other: DateTime): Boolean { return this.date.before(other.date) } + + /** + * 加减年。 + * + * @param year 月份。可以为负数,即为减。 + * @return this + */ + fun addYear(year: Int): DateTime { + this.calendar.add(Calendar.YEAR, year) + return this + } + /** * 加减月份。 * * @param month 月份。可以为负数,即为减。 + * @return this */ fun addMonth(month: Int): DateTime { - val instance = calendar.clone() as Calendar - instance.add(Calendar.MONTH, month) - return DateTime(instance) + this.calendar.add(Calendar.MONTH, month) + return this } + /** * 加减日期。 * * @param day 天数。可以为负数,即为减。 + * @return this */ fun addDay(day: Int): DateTime { - val instance = calendar.clone() as Calendar - instance.add(Calendar.DAY_OF_MONTH, day) - return DateTime(instance) + this.calendar.add(Calendar.DAY_OF_MONTH, day) + return this + } + + + /** + * 加减小时。 + * + * @param hour 小时。可以为负数,即为减。 + * @return this + */ + fun addHour(hour: Int): DateTime { + this.calendar.add(Calendar.HOUR_OF_DAY, hour) + return this + } + + /** + * 加减分钟。 + * + * @param minute 分钟。可以为负数,即为减。 + * @return this + */ + fun addMinute(minute: Int): DateTime { + this.calendar.add(Calendar.MINUTE, minute) + return this + } + + /** + * 加减秒 + * @param second 秒数。可以为负数,即为减。 + * @return this + */ + fun addSecond(second: Int): DateTime { + this.calendar.add(Calendar.SECOND, second) + return this + } + + /** + * 加减毫秒 + * @param millisecond 毫秒数。可以为负数,即为减。 + * @return this + */ + fun addMillisecond(millisecond: Int): DateTime { + this.calendar.add(Calendar.MILLISECOND, millisecond) + return this + } + + /** + * 设置年。 + * + * @param year 月份。 + * @return this + */ + fun setYear(year: Int): DateTime { + this.calendar.set(Calendar.YEAR, year) + return this + } + + /** + * 设置月份。 + * + * @param month 月份。 + * @return this + */ + fun setMonth(month: Int): DateTime { + this.calendar.set(Calendar.MONTH, month) + return this + } + + + /** + * 设置日期。 + * + * @param day 天数。 + * @return this + */ + fun setDay(day: Int): DateTime { + this.calendar.set(Calendar.DAY_OF_MONTH, day) + return this + } + + + /** + * 设置小时。 + * + * @param hour 小时。 + * @return this + */ + fun setHour(hour: Int): DateTime { + this.calendar.set(Calendar.HOUR_OF_DAY, hour) + return this + } + + /** + * 设置分钟。 + * + * @param minute 分钟。 + * @return this + */ + fun setMinute(minute: Int): DateTime { + this.calendar.set(Calendar.MINUTE, minute) + return this + } + + /** + * 设置秒 + * @param second 总秒数。 + * @return this + */ + fun setSecond(second: Int): DateTime { + this.calendar.set(Calendar.SECOND, second) + return this + } + + /** + * 设置毫秒。 + * @param millisecond 毫秒数。 + * @return this + */ + fun setMillisecond(millisecond: Int): DateTime { + this.calendar.set(Calendar.MILLISECOND, millisecond) + return this } /** @@ -360,10 +477,29 @@ class DateTime : Comparable { * 当前天是否周末 */ fun isWeekend(): Boolean { - val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) + val dayOfWeek = this.calendar.get(Calendar.DAY_OF_WEEK) return (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) } + /** + * 清空毫秒,避免误差 + */ + fun clearMillisecond() { + this.calendar.set(Calendar.MILLISECOND, 0) + } + + /** + * 克隆当前对象 + * + * @return 返回新的DateTime对象 + */ + fun clone(): DateTime { + return DateTime(this.calendar) + } + + /** + * 时间相见 + */ operator fun minus(other: DateTime): TimeSpan { return TimeSpan(this.milliseconds - other.milliseconds) } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt index 83dba92..8c653ef 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt @@ -46,7 +46,7 @@ interface IRepository { * @param clazz 操作数据的类型 * @return 聚合根 */ - fun , TKey> get(id: TKey, clazz: Class): TAggregateRoot + fun , TKey> get(id: TKey, clazz: Class): TAggregateRoot? /** From 387d4b813a1b2a33164157016c121dc1806924e0 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 19 May 2021 22:54:39 +0800 Subject: [PATCH 17/25] =?UTF-8?q?0.12.0=20=E5=A2=9E=E5=8A=A0excel=E7=9A=84?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=96=B9=E6=B3=95=EF=BC=9B=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8Daop=E8=AE=B0=E5=BD=95=E6=96=87=E4=BB=B6=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- src/gaea.app/build.gradle | 2 +- .../gaea/app/component/aop/AppAspect.kt | 19 +++-- .../synebula/gaea/app/component/poi/Excel.kt | 69 ++++++++++++++++++- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 8562eaa..16794ae 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.11.0' + version '0.12.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index 6c6bae8..9333a61 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -13,7 +13,7 @@ dependencies { compile("org.springframework.boot:spring-boot-starter-mail:$spring_version") compile("org.springframework.boot:spring-boot-starter-security:$spring_version") compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' - compile group: 'org.apache.poi', name: 'poi', version: '4.1.2' + compile group: 'org.apache.poi', name: 'poi-ooxml', version: '5.0.0' compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' compile group: 'com.google.guava', name: 'guava', version: '30.1.1-jre' compile group: 'com.auth0', name: 'java-jwt', version: '3.14.0' diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 3a400bd..bfc1329 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -1,6 +1,7 @@ package com.synebula.gaea.app.component.aop import com.fasterxml.jackson.databind.ObjectMapper +import com.google.gson.Gson import com.synebula.gaea.app.IApplication import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.app.component.aop.annotation.MethodName @@ -15,11 +16,12 @@ import org.aspectj.lang.annotation.Around import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext import org.springframework.core.DefaultParameterNameDiscoverer +import org.springframework.web.multipart.MultipartFile abstract class AppAspect { private var paramDiscover = DefaultParameterNameDiscoverer() - private val mapper = ObjectMapper() + private val gson = Gson() @Autowired lateinit var logger: ILogger @@ -39,8 +41,8 @@ abstract class AppAspect { fun throws(point: JoinPoint, ex: Throwable) { val clazz = point.signature.declaringType logger.error( - ex, - "${clazz.name}.${point.signature.name} exception:${ex.message}, args:${mapper.writeValueAsString(point.args)}" + ex, + "${clazz.name}.${point.signature.name} exception:${ex.message}, args:${gson.toJson(point.args)}" ) } @@ -84,13 +86,10 @@ abstract class AppAspect { } } val message = "$moduleName - $funcName 异常" - logger.error( - ex, - "$message。Method args ${paramDiscover.getParameterNames(func)?.contentToString()} values is ${ - mapper.writeValueAsString( - point.args - ) - }" + logger.error(ex, + "$message。Method args ${ + paramDiscover.getParameterNames(func)?.contentToString()} values is ${ + gson.toJson(point.args)}" ) return HttpMessage(Status.Error, message) } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt index 76ab78d..1ebf5a4 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt @@ -1,6 +1,7 @@ package com.synebula.gaea.app.component.poi import com.synebula.gaea.app.struct.ExcelData +import org.apache.poi.hpsf.Decimal import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFCellStyle import org.apache.poi.hssf.usermodel.HSSFWorkbook @@ -8,8 +9,9 @@ import org.apache.poi.ss.usermodel.BorderStyle import org.apache.poi.ss.usermodel.HorizontalAlignment import org.apache.poi.ss.usermodel.Sheet import org.apache.poi.ss.usermodel.VerticalAlignment -import java.lang.Exception -import java.lang.RuntimeException +import org.apache.poi.xssf.usermodel.XSSFWorkbook +import org.springframework.web.multipart.MultipartFile +import java.util.* /** * Excel操作对象 @@ -81,6 +83,69 @@ object Excel { writeTo(wb) } + /** + * 导入文件 + * + * @param file 上传文件流 + * @param columns 文件列名称、类型定义 + * @param startRow 数据起始行,默认0 + * @param startColumn 数据起始列,默认0 + * + * @return ExcelData + */ + fun import( + file: MultipartFile, + columns: List>, + startRow: Int = 0, + startColumn: Int = 0 + ): List> { + if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) + throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") + + val workbook = if (file.originalFilename?.endsWith(".xls") == true) + HSSFWorkbook(file.inputStream) + else + XSSFWorkbook(file.inputStream) + val sheet = workbook.getSheetAt(0) + + val data = mutableListOf>() + for (i in startRow..sheet.lastRowNum) { + val row = sheet.getRow(i) ?: continue + val rowData = mutableMapOf() + for (c in startColumn until columns.size + startColumn) { + try { + val column = columns[c] + val value: Any = when (column.second) { + Int::class.java.name, Double::class.java.name, + Float::class.java.name, Decimal::class.java.name -> try { + row.getCell(c).numericCellValue + } catch (ignored: Exception) { + row.getCell(c).stringCellValue + } + Boolean::class.java.name -> try { + row.getCell(c).booleanCellValue + } catch (ignored: Exception) { + row.getCell(c).stringCellValue + } + Date::class.java.name -> try { + row.getCell(c).dateCellValue + } catch (ignored: Exception) { + row.getCell(c).stringCellValue + } + else -> row.getCell(c).stringCellValue + } + rowData.put(columns[c].first, value) + } catch (ex: Exception) { + throw RuntimeException("解析EXCEL文件${file.originalFilename}第${i}行第${c}列出错", ex) + } + } + data.add(rowData) + } + workbook.close() + file.inputStream.close() + return data + } + /** * 设置列宽 * From a9078932aa7ce76bf5f2e326aabc0a480267adeb Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 20 May 2021 16:57:59 +0800 Subject: [PATCH 18/25] =?UTF-8?q?0.12.1=20=E8=B0=83=E6=95=B4excel=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=9B=E8=B0=83=E6=95=B4=E5=88=87=E9=9D=A2=E5=92=8C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/synebula/gaea/app/component/Logger.kt | 40 +++--- .../gaea/app/component/aop/AppAspect.kt | 11 -- .../synebula/gaea/app/component/poi/Excel.kt | 118 ++++++++++++++---- 3 files changed, 116 insertions(+), 53 deletions(-) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/Logger.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/Logger.kt index 24b042d..ec4150d 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/Logger.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/Logger.kt @@ -48,7 +48,7 @@ class Logger : ILogger { override fun trace(format: String, vararg args: Any) { if (this.logger.isTraceEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.trace(message) } } @@ -56,7 +56,7 @@ class Logger : ILogger { override fun trace(t: Throwable, format: String, vararg args: Any) { if (this.logger.isTraceEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.trace(message, t) } } @@ -64,7 +64,7 @@ class Logger : ILogger { override fun trace(obj: Any, format: String, vararg args: Any) { if (this.logger.isTraceEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.trace(message) } } @@ -72,7 +72,7 @@ class Logger : ILogger { override fun trace(obj: Any, t: Throwable?, format: String, vararg args: Any) { if (this.logger.isTraceEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.trace(message, t) } } @@ -95,7 +95,7 @@ class Logger : ILogger { override fun debug(format: String, vararg args: Any) { if (this.logger.isDebugEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.debug(message) } } @@ -103,7 +103,7 @@ class Logger : ILogger { override fun debug(t: Throwable, format: String, vararg args: Any) { if (this.logger.isDebugEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.debug(message, t) } } @@ -111,7 +111,7 @@ class Logger : ILogger { override fun debug(obj: Any, format: String, vararg args: Any) { if (this.logger.isDebugEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.debug(message) } } @@ -119,7 +119,7 @@ class Logger : ILogger { override fun debug(obj: Any, t: Throwable?, format: String, vararg args: Any) { if (this.logger.isDebugEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.debug(message, t) } } @@ -140,7 +140,7 @@ class Logger : ILogger { override fun info(format: String, vararg args: Any) { if (this.logger.isInfoEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.info(message) } } @@ -148,7 +148,7 @@ class Logger : ILogger { override fun info(t: Throwable, format: String, vararg args: Any) { if (this.logger.isInfoEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.info(message, t) } } @@ -156,7 +156,7 @@ class Logger : ILogger { override fun info(obj: Any, format: String, vararg args: Any) { if (this.logger.isInfoEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.info(message) } } @@ -164,7 +164,7 @@ class Logger : ILogger { override fun info(obj: Any, t: Throwable?, format: String, vararg args: Any) { if (this.logger.isInfoEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.info(message, t) } } @@ -185,7 +185,7 @@ class Logger : ILogger { override fun warn(format: String, vararg args: Any) { if (this.logger.isWarnEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.warn(message) } } @@ -193,7 +193,7 @@ class Logger : ILogger { override fun warn(t: Throwable, format: String, vararg args: Any) { if (this.logger.isWarnEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.warn(message, t) } } @@ -201,7 +201,7 @@ class Logger : ILogger { override fun warn(obj: Any, format: String, vararg args: Any) { if (this.logger.isWarnEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.warn(message) } } @@ -209,7 +209,7 @@ class Logger : ILogger { override fun warn(obj: Any, t: Throwable?, format: String, vararg args: Any) { if (this.logger.isWarnEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.warn(message, t) } } @@ -232,7 +232,7 @@ class Logger : ILogger { override fun error(format: String, vararg args: Any) { if (this.logger.isErrorEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.error(message) } } @@ -240,7 +240,7 @@ class Logger : ILogger { override fun error(t: Throwable, format: String, vararg args: Any) { if (this.logger.isErrorEnabled) { - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) this.logger.error(message, t) } } @@ -248,7 +248,7 @@ class Logger : ILogger { override fun error(obj: Any, format: String, vararg args: Any) { if (this.logger.isErrorEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.error(message) } } @@ -256,7 +256,7 @@ class Logger : ILogger { override fun error(obj: Any, t: Throwable?, format: String, vararg args: Any) { if (this.logger.isErrorEnabled) { val real = this.getLogger(obj) - val message = String.format(format, *args) + val message = if (args.isEmpty()) format else String.format(format, *args) real.error(message, t) } } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index bfc1329..b0272db 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -34,17 +34,6 @@ abstract class AppAspect { */ abstract fun func() - /** - * 后置异常通知 - */ - @AfterThrowing("func()", throwing = "ex") - fun throws(point: JoinPoint, ex: Throwable) { - val clazz = point.signature.declaringType - logger.error( - ex, - "${clazz.name}.${point.signature.name} exception:${ex.message}, args:${gson.toJson(point.args)}" - ) - } /** * 环绕通知,环绕增强,相当于MethodInterceptor diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt index 1ebf5a4..f22970d 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt @@ -4,15 +4,16 @@ import com.synebula.gaea.app.struct.ExcelData import org.apache.poi.hpsf.Decimal import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFCellStyle +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator import org.apache.poi.hssf.usermodel.HSSFWorkbook -import org.apache.poi.ss.usermodel.BorderStyle -import org.apache.poi.ss.usermodel.HorizontalAlignment -import org.apache.poi.ss.usermodel.Sheet -import org.apache.poi.ss.usermodel.VerticalAlignment +import org.apache.poi.ss.formula.BaseFormulaEvaluator +import org.apache.poi.ss.usermodel.* +import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.springframework.web.multipart.MultipartFile import java.util.* + /** * Excel操作对象 */ @@ -88,16 +89,16 @@ object Excel { * * @param file 上传文件流 * @param columns 文件列名称、类型定义 - * @param startRow 数据起始行,默认0 - * @param startColumn 数据起始列,默认0 + * @param rowStart 数据起始行,默认0 + * @param columnStart 数据起始列,默认0 * * @return ExcelData */ fun import( - file: MultipartFile, - columns: List>, - startRow: Int = 0, - startColumn: Int = 0 + file: MultipartFile, + columns: List>, + rowStart: Int = 0, + columnStart: Int = 0 ): List> { if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") @@ -109,34 +110,107 @@ object Excel { val sheet = workbook.getSheetAt(0) val data = mutableListOf>() - for (i in startRow..sheet.lastRowNum) { + for (i in rowStart..sheet.lastRowNum) { val row = sheet.getRow(i) ?: continue val rowData = mutableMapOf() - for (c in startColumn until columns.size + startColumn) { + for (r in columnStart until columns.size + columnStart) { try { - val column = columns[c] + val column = columns[r] val value: Any = when (column.second) { Int::class.java.name, Double::class.java.name, Float::class.java.name, Decimal::class.java.name -> try { - row.getCell(c).numericCellValue + row.getCell(r).numericCellValue } catch (ignored: Exception) { - row.getCell(c).stringCellValue + row.getCell(r).stringCellValue } Boolean::class.java.name -> try { - row.getCell(c).booleanCellValue + row.getCell(r).booleanCellValue } catch (ignored: Exception) { - row.getCell(c).stringCellValue + row.getCell(r).stringCellValue } Date::class.java.name -> try { - row.getCell(c).dateCellValue + row.getCell(r).dateCellValue } catch (ignored: Exception) { - row.getCell(c).stringCellValue + row.getCell(r).stringCellValue } - else -> row.getCell(c).stringCellValue + else -> row.getCell(r).stringCellValue } - rowData.put(columns[c].first, value) + rowData.put(columns[r].first, value) } catch (ex: Exception) { - throw RuntimeException("解析EXCEL文件${file.originalFilename}第${i}行第${c}列出错", ex) + throw RuntimeException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${r + 1}列出错", ex) + } + } + data.add(rowData) + } + workbook.close() + file.inputStream.close() + return data + } + + /** + * 导入文件 + * + * @param file 上传文件流 + * @param rowStartIndex 数据起始行,默认0 + * @param columnStartIndex 数据起始列,默认0 + * + * @return ExcelData + */ + fun import( + file: MultipartFile, + columnSize: Int = 0, + rowStartIndex: Int = 0, + columnStartIndex: Int = 0 + ): List> { + if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) + throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") + val eva: BaseFormulaEvaluator + val workbook = if (file.originalFilename?.endsWith(".xls") == true) { + val wb = HSSFWorkbook(file.inputStream) + eva = HSSFFormulaEvaluator(wb) + wb + } else { + val wb = XSSFWorkbook(file.inputStream) + eva = XSSFFormulaEvaluator(wb) + wb + } + val sheet = workbook.getSheetAt(0) + + val titles = mutableListOf() + val titleRow = sheet.getRow(rowStartIndex) + val size = if (columnSize != 0) columnSize else titleRow.physicalNumberOfCells //列数 + for (i in columnStartIndex until size) { + titles.add(titleRow.getCell(i).stringCellValue) + } + + val data = mutableListOf>() + for (r in (rowStartIndex + 1)..sheet.lastRowNum) { + val row = sheet.getRow(r) ?: continue + val rowData = mutableMapOf() + for (c in columnStartIndex until size + columnStartIndex) { + try { + val title = titles[c] + val cell = row.getCell(c) + val value = when (cell.cellType) { + CellType.BOOLEAN -> cell.booleanCellValue.toString() + CellType.ERROR -> cell.errorCellValue.toString() + CellType.NUMERIC -> { + val numericCellValue: Double = cell.numericCellValue + if (DateUtil.isCellDateFormatted(cell)) { + DateUtil.getLocalDateTime(numericCellValue).toString() + } else { + numericCellValue.toString() + } + } + CellType.STRING -> cell.richStringCellValue.string + CellType.BLANK -> "" + CellType.FORMULA -> eva.evaluate(cell).toString() + else -> throw Exception("匹配类型错误") + } + + rowData[title] = value + } catch (ex: Exception) { + throw RuntimeException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${c + 1}列出错", ex) } } data.add(rowData) From 162a6273153b1a0d6188858c56e5ac4478e0245e Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 21 May 2021 16:51:04 +0800 Subject: [PATCH 19/25] =?UTF-8?q?0.12.2=20=E5=A2=9E=E5=8A=A0excel=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=83=85=E5=86=B5=E7=9A=84=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../synebula/gaea/app/component/poi/Excel.kt | 157 ++++++++++++------ 2 files changed, 109 insertions(+), 50 deletions(-) diff --git a/build.gradle b/build.gradle index 16794ae..1f62688 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.12.0' + version '0.12.2' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt index f22970d..4714a41 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt @@ -1,6 +1,7 @@ package com.synebula.gaea.app.component.poi import com.synebula.gaea.app.struct.ExcelData +import com.synebula.gaea.data.date.DateTime import org.apache.poi.hpsf.Decimal import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFCellStyle @@ -98,46 +99,90 @@ object Excel { file: MultipartFile, columns: List>, rowStart: Int = 0, - columnStart: Int = 0 - ): List> { + columnStart: Int = 0, + emptyRowFilter: (row: Row) -> Boolean = + { row -> + row.getCell( + 0, + Row.MissingCellPolicy.RETURN_NULL_AND_BLANK + ) == null + } + ): List> { if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") - val workbook = if (file.originalFilename?.endsWith(".xls") == true) - HSSFWorkbook(file.inputStream) - else - XSSFWorkbook(file.inputStream) + val evaluator: BaseFormulaEvaluator + val workbook = if (file.originalFilename?.endsWith(".xls") == true) { + val wb = HSSFWorkbook(file.inputStream) + evaluator = HSSFFormulaEvaluator(wb) + wb + } else { + val wb = XSSFWorkbook(file.inputStream) + evaluator = XSSFFormulaEvaluator(wb) + wb + } + val sheet = workbook.getSheetAt(0) - val data = mutableListOf>() - for (i in rowStart..sheet.lastRowNum) { - val row = sheet.getRow(i) ?: continue - val rowData = mutableMapOf() - for (r in columnStart until columns.size + columnStart) { + val data = mutableListOf>() + for (r in rowStart..sheet.lastRowNum) { + val row = sheet.getRow(r) ?: continue + if (emptyRowFilter(row)) continue //空行不处理 + val rowData = mutableMapOf() + for (c in columnStart until columns.size + columnStart) { try { - val column = columns[r] - val value: Any = when (column.second) { - Int::class.java.name, Double::class.java.name, - Float::class.java.name, Decimal::class.java.name -> try { - row.getCell(r).numericCellValue - } catch (ignored: Exception) { - row.getCell(r).stringCellValue + val column = columns[c] + val cell = row.getCell(c, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL) + if (cell == null) { + rowData[columns[c].first] = "" + continue + } + val value: Any? = when (column.second) { + Int::class.java.name -> { + if (cell.cellType == CellType.NUMERIC) { + cell.numericCellValue.toInt() + } else { + this.getCellValue(cell, evaluator).toString().toIntOrNull() + } } - Boolean::class.java.name -> try { - row.getCell(r).booleanCellValue - } catch (ignored: Exception) { - row.getCell(r).stringCellValue + Double::class.java.name -> { + if (cell.cellType == CellType.NUMERIC) { + cell.numericCellValue + } else { + this.getCellValue(cell, evaluator).toString().toDoubleOrNull() + } + } + Float::class.java.name -> { + if (cell.cellType == CellType.NUMERIC) { + cell.numericCellValue.toFloat() + } else { + this.getCellValue(cell, evaluator).toString().toFloatOrNull() + } + } + Decimal::class.java.name -> { + if (cell.cellType == CellType.NUMERIC) { + cell.numericCellValue.toBigDecimal() + } else { + this.getCellValue(cell, evaluator).toString().toBigDecimalOrNull() + } + } + Boolean::class.java.name -> { + if (cell.cellType == CellType.BOOLEAN) { + cell.booleanCellValue + } else { + this.getCellValue(cell, evaluator).toString().toBoolean() + } } Date::class.java.name -> try { - row.getCell(r).dateCellValue + cell.dateCellValue } catch (ignored: Exception) { - row.getCell(r).stringCellValue + DateTime(cell.stringCellValue).date } - else -> row.getCell(r).stringCellValue + else -> cell.stringCellValue } - rowData.put(columns[r].first, value) + rowData[columns[c].first] = value } catch (ex: Exception) { - throw RuntimeException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${r + 1}列出错", ex) + throw RuntimeException("解析EXCEL文件${file.originalFilename}第${c + 1}行第${c + 1}列出错", ex) } } data.add(rowData) @@ -160,18 +205,24 @@ object Excel { file: MultipartFile, columnSize: Int = 0, rowStartIndex: Int = 0, - columnStartIndex: Int = 0 + columnStartIndex: Int = 0, + emptyRowFilter: (row: Row) -> Boolean = { row -> + row.getCell( + 0, + Row.MissingCellPolicy.RETURN_NULL_AND_BLANK + ) == null + } ): List> { if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") - val eva: BaseFormulaEvaluator + val evaluator: BaseFormulaEvaluator val workbook = if (file.originalFilename?.endsWith(".xls") == true) { val wb = HSSFWorkbook(file.inputStream) - eva = HSSFFormulaEvaluator(wb) + evaluator = HSSFFormulaEvaluator(wb) wb } else { val wb = XSSFWorkbook(file.inputStream) - eva = XSSFFormulaEvaluator(wb) + evaluator = XSSFFormulaEvaluator(wb) wb } val sheet = workbook.getSheetAt(0) @@ -186,29 +237,18 @@ object Excel { val data = mutableListOf>() for (r in (rowStartIndex + 1)..sheet.lastRowNum) { val row = sheet.getRow(r) ?: continue + if (emptyRowFilter(row)) continue //空行不处理 val rowData = mutableMapOf() for (c in columnStartIndex until size + columnStartIndex) { try { val title = titles[c] - val cell = row.getCell(c) - val value = when (cell.cellType) { - CellType.BOOLEAN -> cell.booleanCellValue.toString() - CellType.ERROR -> cell.errorCellValue.toString() - CellType.NUMERIC -> { - val numericCellValue: Double = cell.numericCellValue - if (DateUtil.isCellDateFormatted(cell)) { - DateUtil.getLocalDateTime(numericCellValue).toString() - } else { - numericCellValue.toString() - } - } - CellType.STRING -> cell.richStringCellValue.string - CellType.BLANK -> "" - CellType.FORMULA -> eva.evaluate(cell).toString() - else -> throw Exception("匹配类型错误") + val cell = row.getCell(c, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL) + if (cell == null) { + rowData[title] = "" + continue } - - rowData[title] = value + val value = getCellValue(cell, evaluator) + rowData[title] = value.toString() } catch (ex: Exception) { throw RuntimeException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${c + 1}列出错", ex) } @@ -243,4 +283,23 @@ object Excel { style.borderBottom = borderStyle style.borderLeft = borderStyle } + + private fun getCellValue(cell: Cell, evaluator: BaseFormulaEvaluator): Any { + return when (cell.cellType) { + CellType.BOOLEAN -> cell.booleanCellValue + CellType.ERROR -> cell.errorCellValue + CellType.NUMERIC -> { + val numericCellValue: Double = cell.numericCellValue + if (DateUtil.isCellDateFormatted(cell)) { + DateUtil.getLocalDateTime(numericCellValue) + } else { + numericCellValue + } + } + CellType.STRING -> cell.richStringCellValue.string + CellType.BLANK -> "" + CellType.FORMULA -> evaluator.evaluate(cell).toString() + else -> throw Exception("匹配类型错误") + } + } } \ No newline at end of file From dee7694cc40f4440e85521fe1130ef87f7664aa1 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 25 May 2021 15:27:39 +0800 Subject: [PATCH 20/25] =?UTF-8?q?0.13.0=20=E4=BF=AE=E6=94=B9service?= =?UTF-8?q?=E3=80=81query=E5=BC=95=E7=94=A8=E4=B8=8D=E5=8F=AF=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=EF=BC=9B=E6=B8=85=E7=90=86=E4=BB=A3=E7=A0=81import?= =?UTF-8?q?=EF=BC=9B=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=EF=BC=8C=E5=8F=AF=E5=AE=9A=E4=B9=89=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E7=BB=99=E7=94=A8=E6=88=B7=E7=9A=84=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/synebula/gaea/app/Application.kt | 4 +- .../com/synebula/gaea/app/cmd/CommandApp.kt | 7 ++-- .../com/synebula/gaea/app/cmd/ICommandApp.kt | 36 +++++----------- .../gaea/app/component/aop/AppAspect.kt | 28 ++++++++----- .../aop/handler/AnnotationHandler.kt | 1 - .../synebula/gaea/app/component/poi/Excel.kt | 5 ++- .../app/component/security/WebSecurity.kt | 1 - .../com/synebula/gaea/app/query/IQueryApp.kt | 41 +++++-------------- .../com/synebula/gaea/app/query/QueryApp.kt | 2 +- .../synebula/gaea/data/cache/CacheEntity.kt | 2 +- .../com/synebula/gaea/data/code/DateCode.kt | 2 +- .../gaea/data/code/FixedRandomCode.kt | 2 +- .../com/synebula/gaea/data/code/GUIDCode.kt | 2 +- .../com/synebula/gaea/data/date/Time.kt | 4 +- .../com/synebula/gaea/data/date/TimeSpan.kt | 3 -- .../synebula/gaea/domain/service/Command.kt | 2 - .../gaea/exception/NoticeUserException.kt | 6 +++ .../com/synebula/gaea/io/scan/ClassPath.kt | 3 +- .../com/synebula/gaea/io/scan/ClassScanner.kt | 4 +- 20 files changed, 62 insertions(+), 95 deletions(-) create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/exception/NoticeUserException.kt diff --git a/build.gradle b/build.gradle index 1f62688..e75f351 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.12.2' + version '0.13.0' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt index 329a7df..fdcbd6d 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt @@ -20,8 +20,8 @@ import javax.annotation.Resource open class Application( override var name: String, override var clazz: Class, - override var service: IService?, - override var query: IQuery?, + override var service: IService, + override var query: IQuery, override var logger: ILogger? ) : ICommandApp, IQueryApp { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/CommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/CommandApp.kt index 94c82c7..78860e9 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/CommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/CommandApp.kt @@ -14,9 +14,10 @@ import javax.annotation.Resource * @param logger 日志组件 */ open class CommandApp( - override var name: String, - override var service: IService?, - override var logger: ILogger?) : ICommandApp { + override var name: String, + override var service: IService, + override var logger: ILogger? +) : ICommandApp { @Resource override var jsonSerializer: IJsonSerializer? = null } \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index 4a4bf4b..e2ffca3 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -1,8 +1,8 @@ package com.synebula.gaea.app.cmd import com.synebula.gaea.app.IApplication -import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.app.component.aop.annotation.MethodName +import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.data.message.Status import com.synebula.gaea.data.serialization.json.IJsonSerializer import com.synebula.gaea.domain.service.ICommand @@ -19,33 +19,21 @@ import org.springframework.web.bind.annotation.* interface ICommandApp : IApplication { var jsonSerializer: IJsonSerializer? - var service: IService? + var service: IService @PostMapping @MethodName("添加") fun add(@RequestBody command: TCommand): HttpMessage { - val msg = HttpMessage() - if (this.service != null) { - msg.load(this.service!!.add(command)) - } else { - msg.status = Status.Error - msg.message = "没有对应服务,无法执行该操作" - } + val msg = HttpMessage(this.service.add(command)) return msg } @PutMapping("/{id:.+}") @MethodName("更新") fun update(@PathVariable id: TKey, @RequestBody command: TCommand): HttpMessage { - val msg = HttpMessage() - if (this.service != null) - this.service!!.update(id, command) - else { - msg.status = Status.Error - msg.message = "没有对应服务,无法执行该操作" - } - return msg + this.service.update(id, command) + return HttpMessage() } @@ -53,17 +41,13 @@ interface ICommandApp : IApplication { @MethodName("删除") fun remove(@PathVariable id: TKey): HttpMessage { val msg = HttpMessage() - if (this.service != null) - try { - msg.data = this.service!!.remove(id) - } catch (ex: IllegalStateException) { - msg.status = Status.Error - msg.message = ex.message ?: "" - } - else { + try { + msg.data = this.service.remove(id) + } catch (ex: IllegalStateException) { msg.status = Status.Error - msg.message = "没有对应服务,无法执行该操作" + msg.message = ex.message ?: "" } + return msg } } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index b0272db..0aa80b6 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -1,22 +1,19 @@ package com.synebula.gaea.app.component.aop -import com.fasterxml.jackson.databind.ObjectMapper import com.google.gson.Gson import com.synebula.gaea.app.IApplication -import com.synebula.gaea.app.struct.HttpMessage -import com.synebula.gaea.app.component.aop.annotation.MethodName import com.synebula.gaea.app.component.aop.annotation.Handler +import com.synebula.gaea.app.component.aop.annotation.MethodName import com.synebula.gaea.app.component.aop.annotation.ModuleName +import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.data.message.Status +import com.synebula.gaea.exception.NoticeUserException import com.synebula.gaea.log.ILogger -import org.aspectj.lang.JoinPoint import org.aspectj.lang.ProceedingJoinPoint -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 org.springframework.core.DefaultParameterNameDiscoverer -import org.springframework.web.multipart.MultipartFile abstract class AppAspect { private var paramDiscover = DefaultParameterNameDiscoverer() @@ -74,11 +71,20 @@ abstract class AppAspect { moduleName = name.value } } - val message = "$moduleName - $funcName 异常" - logger.error(ex, - "$message。Method args ${ - paramDiscover.getParameterNames(func)?.contentToString()} values is ${ - gson.toJson(point.args)}" + var message = "$moduleName - $funcName 异常" + if (ex is NoticeUserException) { + message = "$message: ${ex.message}" + } else { + message = "$message。如多次遇到,请联系开发人员。" + + } + logger.error( + ex, + "$message。Method args ${ + paramDiscover.getParameterNames(func)?.contentToString() + } values is ${ + gson.toJson(point.args) + }" ) return HttpMessage(Status.Error, message) } diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt index ea1c4aa..fbd2a37 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/handler/AnnotationHandler.kt @@ -1,6 +1,5 @@ package com.synebula.gaea.app.component.aop.handler -import java.lang.Exception import java.lang.reflect.Method interface AnnotationHandler { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt index 4714a41..b8e2626 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/poi/Excel.kt @@ -2,6 +2,7 @@ package com.synebula.gaea.app.component.poi import com.synebula.gaea.app.struct.ExcelData import com.synebula.gaea.data.date.DateTime +import com.synebula.gaea.exception.NoticeUserException import org.apache.poi.hpsf.Decimal import org.apache.poi.hssf.usermodel.HSSFCell import org.apache.poi.hssf.usermodel.HSSFCellStyle @@ -214,7 +215,7 @@ object Excel { } ): List> { if (file.originalFilename?.endsWith(".xls") != true && file.originalFilename?.endsWith(".xlsx") != true) - throw RuntimeException("无法识别的文件格式[${file.originalFilename}]") + throw NoticeUserException("无法识别的文件格式[${file.originalFilename}]") val evaluator: BaseFormulaEvaluator val workbook = if (file.originalFilename?.endsWith(".xls") == true) { val wb = HSSFWorkbook(file.inputStream) @@ -250,7 +251,7 @@ object Excel { val value = getCellValue(cell, evaluator) rowData[title] = value.toString() } catch (ex: Exception) { - throw RuntimeException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${c + 1}列出错", ex) + throw NoticeUserException("解析EXCEL文件${file.originalFilename}第${r + 1}行第${c + 1}列出错", ex) } } data.add(rowData) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt index 3efed1f..c0f6f3c 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/security/WebSecurity.kt @@ -13,7 +13,6 @@ import org.springframework.stereotype.Component import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource -import java.util.* @Component diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt index c6e534a..ff5ded0 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt @@ -1,9 +1,8 @@ package com.synebula.gaea.app.query import com.synebula.gaea.app.IApplication -import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.app.component.aop.annotation.MethodName -import com.synebula.gaea.data.message.Status +import com.synebula.gaea.app.struct.HttpMessage import com.synebula.gaea.query.IQuery import com.synebula.gaea.query.Params import org.springframework.web.bind.annotation.GetMapping @@ -14,7 +13,7 @@ interface IQueryApp : IApplication { /** * 查询服务 */ - var query: IQuery? + var query: IQuery /** * 查询的View类型 @@ -24,17 +23,17 @@ interface IQueryApp : IApplication { @MethodName("获取数据") @GetMapping("/{id:.+}") fun get(@PathVariable id: TKey): HttpMessage { - return this.doQuery { - this.query!!.get(id, clazz) - } + val data = this.query.get(id, clazz) + val msg = HttpMessage() + msg.data = data + return msg } @MethodName("获取列表数据") @GetMapping fun list(@RequestParam params: LinkedHashMap): HttpMessage { - return this.doQuery { - this.query!!.list(params, clazz) - } + val data = this.query.list(params, clazz) + return HttpMessage(data) } @MethodName("获取分页数据") @@ -44,26 +43,8 @@ interface IQueryApp : IApplication { @PathVariable page: Int, @RequestParam parameters: LinkedHashMap ): HttpMessage { - return this.doQuery { - val data = Params(page, size, parameters) - this.query!!.paging(data, clazz) - } - } - - - /** - * 抽取查询业务判断功能 - * - * @param biz 业务执行逻辑 - */ - fun doQuery(biz: (() -> Any?)): HttpMessage { - val msg = HttpMessage() - if (this.query != null) { - msg.data = biz() - } else { - msg.status = Status.Error - msg.message = "没有对应服务,无法执行该操作" - } - return msg + val params = Params(page, size, parameters) + val data = this.query.paging(params, clazz) + return HttpMessage(data) } } \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt index d8760fc..7b1a295 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt @@ -13,6 +13,6 @@ import com.synebula.gaea.query.IQuery open class QueryApp( override var name: String, override var clazz: Class, - override var query: IQuery?, + override var query: IQuery, override var logger: ILogger? ) : IQueryApp \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt index 7d30454..3272bbf 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/cache/CacheEntity.kt @@ -1,6 +1,6 @@ package com.synebula.gaea.data.cache -import java.util.Date +import java.util.* /** * diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/DateCode.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/DateCode.kt index 7d603a1..4afe5e4 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/DateCode.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/DateCode.kt @@ -1,7 +1,7 @@ package com.synebula.gaea.data.code import java.text.SimpleDateFormat -import java.util.Date +import java.util.* /** * @author alex diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/FixedRandomCode.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/FixedRandomCode.kt index 49a5562..001657b 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/FixedRandomCode.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/FixedRandomCode.kt @@ -1,6 +1,6 @@ package com.synebula.gaea.data.code -import java.util.Random +import java.util.* /** * 固定长度随机编号生成。 diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/GUIDCode.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/GUIDCode.kt index a24406f..9aad658 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/GUIDCode.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/code/GUIDCode.kt @@ -1,6 +1,6 @@ package com.synebula.gaea.data.code -import java.util.UUID +import java.util.* /** * 全球唯一编号生成。 diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt index 73a3543..5f676f7 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/Time.kt @@ -1,10 +1,8 @@ package com.synebula.gaea.data.date -import java.math.BigDecimal import java.text.ParseException import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Date +import java.util.* /** diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt index bc2c2fe..6d8505b 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/TimeSpan.kt @@ -6,9 +6,6 @@ */ package com.synebula.gaea.data.date -import java.math.BigDecimal -import java.util.* - /** * * @author whj diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt index b0f3e75..2c07161 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt @@ -1,7 +1,5 @@ package com.synebula.gaea.domain.service -import java.util.* - /** * 命令基础实现类,发给service的命令。 * diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/exception/NoticeUserException.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/exception/NoticeUserException.kt new file mode 100644 index 0000000..fff4d1a --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/exception/NoticeUserException.kt @@ -0,0 +1,6 @@ +package com.synebula.gaea.exception + +/** + * 需要通知给用户的异常 + */ +class NoticeUserException(message: String, cause: Exception? = null) : Exception(message, cause) \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt index a62caba..7aa60b5 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt @@ -2,8 +2,7 @@ package com.synebula.gaea.io.scan import java.io.IOException import java.net.URL -import java.util.Enumeration -import java.util.HashSet +import java.util.* /** * diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt index fb1b904..3b03ef0 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt @@ -5,9 +5,7 @@ import java.io.FileFilter import java.io.UnsupportedEncodingException import java.net.URLDecoder import java.nio.charset.Charset -import java.util.Collections -import java.util.HashSet -import java.util.LinkedList +import java.util.* import java.util.jar.JarFile /** From 98127c7dbfa0d63e3ba8d87d57d2490cdb690dc3 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 5 Jun 2021 22:30:21 +0800 Subject: [PATCH 21/25] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E6=8F=90=E7=A4=BA=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt index 0aa80b6..ed07e8b 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/component/aop/AppAspect.kt @@ -75,7 +75,7 @@ abstract class AppAspect { if (ex is NoticeUserException) { message = "$message: ${ex.message}" } else { - message = "$message。如多次遇到,请联系开发人员。" + message = "$message。" } logger.error( From e2731bbe2cda1cdaadf43f8ca7657731e2153bd0 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 10 Jun 2021 15:37:55 +0800 Subject: [PATCH 22/25] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=90=8C=E4=B8=80=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/synebula/gaea/data/date/DateTime.kt | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt index 03a0eab..9b8916f 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt @@ -272,9 +272,9 @@ class DateTime() : Comparable { * 比较当前时间是否在目标时间范围内。 * @param start 目标开始时间。 * @param end 目标结束时间。 - * @return 是否。 + * @return true or false */ - fun between(start: DateTime, end: DateTime): Boolean { + fun isBetween(start: DateTime, end: DateTime): Boolean { //return this in start..end return start.dateNoTime.compareTo(this.dateNoTime) * this.dateNoTime.compareTo(end.dateNoTime) >= 0 } @@ -284,9 +284,9 @@ class DateTime() : Comparable { * @param start 目标开始时间。 * @param end 目标结束时间。 * @param level 比较时间的最小级别。 - * @return 是否。 + * @return true or false */ - fun between(start: DateTime, end: DateTime, level: TimeUnit): Boolean { + fun isBetween(start: DateTime, end: DateTime, level: TimeUnit): Boolean { return this.compareTo(start, level) >= 0 && this.compareTo(end, level) <= 0 } @@ -295,9 +295,9 @@ class DateTime() : Comparable { * 判断当前时间是否在某时间后 * * @param other 另一时间 - * @return new DateTime object + * @return true or false */ - fun after(other: DateTime): Boolean { + fun isAfter(other: DateTime): Boolean { return this.date.after(other.date) } @@ -305,12 +305,24 @@ class DateTime() : Comparable { * 判断当前时间是否在某时间前 * * @param other 另一时间 - * @return new DateTime object + * @return true or false */ - fun before(other: DateTime): Boolean { + fun isBefore(other: DateTime): Boolean { return this.date.before(other.date) } + /** + * 判断当前时间是否同一天 + * + * @param other 另一时间 + * @return true or false + */ + fun isSameDay(other: DateTime): Boolean { + return this.calendar.get(Calendar.ERA) == other.calendar.get(Calendar.ERA) + && this.calendar.get(Calendar.YEAR) == other.calendar.get(Calendar.YEAR) + && this.calendar.get(Calendar.DAY_OF_YEAR) == other.calendar.get(Calendar.DAY_OF_YEAR) + } + /** * 加减年。 From 30b88714d2dc3e35f924f3b1e68f6c543b1a0e1d Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 11 Jun 2021 11:13:04 +0800 Subject: [PATCH 23/25] =?UTF-8?q?0.13.1=20=E4=BF=AE=E5=A4=8Ddatetime=20clo?= =?UTF-8?q?ne=E6=97=A0=E6=95=88=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e75f351..4355845 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { subprojects { ext { - version '0.13.0' + version '0.13.1' spring_version = "2.3.0.RELEASE" } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt index 9b8916f..053b4a9 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/date/DateTime.kt @@ -506,7 +506,7 @@ class DateTime() : Comparable { * @return 返回新的DateTime对象 */ fun clone(): DateTime { - return DateTime(this.calendar) + return DateTime(this.calendar.clone() as Calendar) } /** From 230648426ec557735ef3dbf01f68c98d8b4e5481 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 14 Mar 2022 10:18:07 +0800 Subject: [PATCH 24/25] fix grammar --- .../src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt index e2ffca3..9976caf 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ICommandApp.kt @@ -21,12 +21,10 @@ interface ICommandApp : IApplication { var service: IService - @PostMapping @MethodName("添加") fun add(@RequestBody command: TCommand): HttpMessage { - val msg = HttpMessage(this.service.add(command)) - return msg + return HttpMessage(service.add(command)) } @PutMapping("/{id:.+}") @@ -36,7 +34,6 @@ interface ICommandApp : IApplication { return HttpMessage() } - @DeleteMapping("/{id:.+}") @MethodName("删除") fun remove(@PathVariable id: TKey): HttpMessage { From 248d9a57d457550214276e9d384a93dc3e4e34a5 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 22 Mar 2022 09:57:44 +0800 Subject: [PATCH 25/25] add lazy app module --- .../com/synebula/gaea/app/LazyApplication.kt | 30 ++++++++ .../synebula/gaea/app/cmd/ILazyCommandApp.kt | 50 +++++++++++++ .../synebula/gaea/app/cmd/LazyCommandApp.kt | 25 +++++++ .../gaea/domain/service/ILazyService.kt | 39 ++++++++++ .../gaea/domain/service/LazyService.kt | 73 +++++++++++++++++++ 5 files changed, 217 insertions(+) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/LazyApplication.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ILazyCommandApp.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/LazyCommandApp.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ILazyService.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/LazyService.kt diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/LazyApplication.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/LazyApplication.kt new file mode 100644 index 0000000..628a9e9 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/LazyApplication.kt @@ -0,0 +1,30 @@ +package com.synebula.gaea.app + +import com.synebula.gaea.app.cmd.ILazyCommandApp +import com.synebula.gaea.app.query.IQueryApp +import com.synebula.gaea.data.serialization.json.IJsonSerializer +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.service.ILazyService +import com.synebula.gaea.log.ILogger +import com.synebula.gaea.query.IQuery +import javax.annotation.Resource + +/** + * 联合服务,同时实现了ILazyCommandApp和IQueryApp接口 + * + * @param name 业务名称 + * @param service 业务domain服务 + * @param query 业务查询服务 + * @param logger 日志组件 + */ +open class LazyApplication, TKey>( + override var name: String, + override var clazz: Class, //view class type + override var service: ILazyService, + override var query: IQuery, + override var logger: ILogger? +) : ILazyCommandApp, IQueryApp { + + @Resource + override var jsonSerializer: IJsonSerializer? = null +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ILazyCommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ILazyCommandApp.kt new file mode 100644 index 0000000..b3e1aec --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/ILazyCommandApp.kt @@ -0,0 +1,50 @@ +package com.synebula.gaea.app.cmd + +import com.synebula.gaea.app.IApplication +import com.synebula.gaea.app.component.aop.annotation.MethodName +import com.synebula.gaea.app.struct.HttpMessage +import com.synebula.gaea.data.message.Status +import com.synebula.gaea.data.serialization.json.IJsonSerializer +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.service.ILazyService +import org.springframework.web.bind.annotation.* + +/** + * 直接使用实体对象提供服务的api + * + * @author alex + * @version 0.1 + * @since 2020-05-15 + */ +interface ILazyCommandApp, TKey> : IApplication { + var jsonSerializer: IJsonSerializer? + + var service: ILazyService + + @PostMapping + @MethodName("添加") + fun add(@RequestBody entity: TRoot): HttpMessage { + return HttpMessage(service.add(entity)) + } + + @PutMapping("/{id:.+}") + @MethodName("更新") + fun update(@PathVariable id: TKey, @RequestBody entity: TRoot): HttpMessage { + this.service.update(id, entity) + return HttpMessage() + } + + @DeleteMapping("/{id:.+}") + @MethodName("删除") + fun remove(@PathVariable id: TKey): HttpMessage { + val msg = HttpMessage() + try { + msg.data = this.service.remove(id) + } catch (ex: IllegalStateException) { + msg.status = Status.Error + msg.message = ex.message ?: "" + } + + return msg + } +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/LazyCommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/LazyCommandApp.kt new file mode 100644 index 0000000..46abef3 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/cmd/LazyCommandApp.kt @@ -0,0 +1,25 @@ +package com.synebula.gaea.app.cmd + +import com.synebula.gaea.data.serialization.json.IJsonSerializer +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.service.ICommand +import com.synebula.gaea.domain.service.ILazyService +import com.synebula.gaea.domain.service.IService +import com.synebula.gaea.log.ILogger +import javax.annotation.Resource + +/** + * 指令服务,同时实现ICommandApp + * + * @param name 业务名称 + * @param service 业务domain服务 + * @param logger 日志组件 + */ +open class LazyCommandApp, TKey>( + override var name: String, + override var service: ILazyService, + override var logger: ILogger? +) : ILazyCommandApp { + @Resource + override var jsonSerializer: IJsonSerializer? = null +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ILazyService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ILazyService.kt new file mode 100644 index 0000000..2d2efec --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ILazyService.kt @@ -0,0 +1,39 @@ +package com.synebula.gaea.domain.service + +import com.synebula.gaea.data.message.DataMessage +import com.synebula.gaea.data.message.Message +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.log.ILogger + + +/** + * 继承该接口,表明对象为领域服务。 + * @author alex + * @version 0.0.1 + * @since 2016年9月18日 下午2:23:15 + */ +interface ILazyService, TKey> { + /** + * 日志组件。 + */ + var logger: ILogger + + fun add(root: TAggregateRoot): DataMessage + + fun update(id: TKey, root: TAggregateRoot) + + fun remove(id: TKey) + + /** + * 添加一个删除对象前执行监听器。 + * @param key 监听器标志。 + * @param func 监听方法。 + */ + fun addBeforeRemoveListener(key: String, func: (id: TKey) -> Message) + + /** + * 移除一个删除对象前执行监听器。 + * @param key 监听器标志。 + */ + fun removeBeforeRemoveListener(key: String) +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/LazyService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/LazyService.kt new file mode 100644 index 0000000..a0f6f4b --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/LazyService.kt @@ -0,0 +1,73 @@ +package com.synebula.gaea.domain.service + +import com.synebula.gaea.data.IObjectConverter +import com.synebula.gaea.data.message.DataMessage +import com.synebula.gaea.data.message.Message +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.repository.IRepository +import com.synebula.gaea.log.ILogger + + +/** + * 依赖了IRepository仓储借口的服务实现类 Service + * 该类依赖仓储接口 @see IRepository, 需要显式提供聚合根的class对象 + * + * @param repository 仓储对象 + * @param clazz 聚合根类对象 + * @param logger 日志组件 + * @author alex + * @version 0.1 + * @since 2020-05-17 + */ +open class LazyService, TKey>( + protected open var clazz: Class, + protected open var repository: IRepository, + override var logger: ILogger +) : ILazyService { + + /** + * 删除对象前执行监听器。 + */ + protected val beforeRemoveListeners = mutableMapOf Message>() + + /** + * 添加一个删除对象前执行监听器。 + * @param key 监听器标志。 + * @param func 监听方法。 + */ + override fun addBeforeRemoveListener(key: String, func: (id: TKey) -> Message) { + this.beforeRemoveListeners[key] = func + } + + /** + * 移除一个删除对象前执行监听器。 + * @param key 监听器标志。 + */ + override fun removeBeforeRemoveListener(key: String) { + this.beforeRemoveListeners.remove(key) + } + + override fun add(root: TAggregateRoot): DataMessage { + val msg = DataMessage() + this.repository.add(root, this.clazz) + msg.data = root.id + return msg + } + + override fun update(id: TKey, root: TAggregateRoot) { + root.id = id + this.repository.update(root, this.clazz) + } + + override fun remove(id: TKey) { + val functions = this.beforeRemoveListeners.values + var msg: Message + for (func in functions) { + msg = func(id) + if (!msg.success()) { + throw IllegalStateException(msg.message) + } + } + this.repository.remove(id, this.clazz) + } +}