GithubHelp home page GithubHelp logo

cloudoptlab / cloudopt-next Goto Github PK

View Code? Open in Web Editor NEW
337.0 13.0 49.0 1.06 MB

A simple and modern Java and Kotlin vert.x web framework

Home Page: https://www.yuque.com/cloudopt/next/hp3mc1

License: Apache License 2.0

Kotlin 98.91% CSS 0.01% FreeMarker 0.03% HTML 0.98% Handlebars 0.03% Python 0.04%
kotlin java vertx vert java-web java-library java-8 java-9 springboot cloudopt next web framework jfinal resty restful-api

cloudopt-next's Introduction

Cloudopt Next

image.png image.png

Cloudopt Next is a very lightweight and modern, JVM-based, full stack kotlin framework designed for building modular, easily testable JVM applications with support for Java, Kotlin language, crafted from the best of breed Java libraries and standards.

Cloudopt Next has the following features:

Simple Minimalist design, almost no configuration, no dependence on tomcat, jetty and other web containers.

Asyn Based on vertx, it is easy to achieve high-performance asynchronous services.

Plugin Supports various components of the vertx system, and also supports the extension of functions through plug-ins. The official also provides a large number of useful plug-ins.

Chinese All Chinese documents, Chinese community to help Chinese developers get started quickly

Started

You can view the document by visiting the official website of Cloudopt Next, or you can go to example to see a simple example.

Route

Let's take a look at a simple route based on Cloudopt Next:

@API("/")
class IndexController : Resource() {
    @GET
    fun get(){
        renderHtml(view = "index")
    }
}
@API(value = "/")
public class IndexController extends Resource {
    @GET
    public void get(){
        View v = new View();
        v.setView("index");
        renderHtml(view);
    }
}

Run

fun main(args: Array<String>) {
    CloudoptServer.run()
}
public static void main(String args[]) {
    CloudoptServer.run();
}

SockJS

@SocketJS("/socket/api/*")
class SocketController : SocketJSResource {
    override fun handler(socket: SockJSSocket) {
        println(socket)
        socket.handler {message->
            println(message)
            socket.write("Hello world!")
        }
    }
}

Plugin

fun main(args: Array<String>) {
    CloudoptServer.addPlugin(TestPlugin())
    CloudoptServer.addPlugin(EventPlugin())
    CloudoptServer.run()
}

Getting help

Having trouble with Cloudopt Next? We’d like to help!

  • Follow our twitter to get the latest information.
  • Check the reference documentation carefully for specific code cases or common problems.
  • If you have a problem with the upgrade, check the upgrade instructions in the Wiki.
  • Send mail to [email protected].
  • Send issue to your question on GitHub, we will answer it as soon as possible.
  • If you are in China, you can also join the QQ group: 557692142.

Reporting Issues

Cloudopt Next uses GitHub’s integrated issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:

  • Before you log a bug, please search the issue tracker to see if someone has already reported the problem.
  • Please provide as much information as possible with the issue report, we like to know the version of Cloudopt Next that you are using, as well as your Operating System and JVM version.

License

Cloudopt Next is Open Source software released under the Apache 2.0 license.

cloudopt-next's People

Contributors

ccixyj avatar kiyoupio avatar mayangzz avatar t-baby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cloudopt-next's Issues

getBodyJson 方法不能转换为目标类型对象

fun getBodyJson(clazz: Class<*>): Any? { return Jsoner.toJsonObject(Jsoner.toJsonString(context.bodyAsJson), clazz) }

初步怀疑:context.bodyAsJson获取的是JSONObject类型的对象,所以JSONObject结构并不能转换为clazz类型。

bug:如果application.json文件不存在,无法正常启动

类初始化问题,NextServer init先执行检测包名,包名空则抛异常了,导致NextServer.run(App.class)无法正常执行。
public static void main(String[] args) {
NextServer.run(App.class);
}

报错:
Caused by: java.lang.RuntimeException: Package name must not be null!
at net.cloudopt.next.web.NextServer.scan(NextServer.kt:109)
at net.cloudopt.next.web.NextServer.(NextServer.kt:78)
... 1 more

为什么Kafka会重复消费?

默认情况下cloudopt-next-kafka的autoCommit是关闭的,需要手动提交。

您只需要打开配置文件中设置autoCommit为true即可。

当然您还可以手动提交,默认会自动将最后一个消费的提交:

KafkaManager.consumer.commit({ ar ->

  if (ar.succeeded()) {
    println("Last read message offset committed")
  }
})

功能建议: 自动编译加载、Swagger、GraphQL、WebSocket

  1. 在开发模式下支持热加载,src目录内容修改后自动编译、重新加载。可以参考KtorActFramework
  2. 通过注解、decorator生成swagger.json,SwaggerUI加载显示。Spring Boot JFinal支持此项功能
  3. 集成graphQLgraphiQL
  4. 增加WebSocket相关接口

在一个方法上添加两个自定义annotation,这两个自定义annotation都用@Before修饰,而只有一个Before的invokeBy类中的方法被调用。

//第一个annotation
@retention(AnnotationRetention.RUNTIME)
@target(AnnotationTarget.FUNCTION)
@MustBeDocumented

@before(invokeBy = [RoleCheck::class])
annotation class PreRole(
val value: String,
)
//第二个annotation
@retention(AnnotationRetention.RUNTIME)
@target(AnnotationTarget.FUNCTION)
@MustBeDocumented

@before(invokeBy = [PermissionCheck::class])
annotation class PreAuthorize(
val value: String,
)

//
@API("/api/log")
class LogController : Resource() {

@GET("/list")
@PreRole("admin")
@PreAuthorize("log:list")
suspend fun list() {
  //......
}

}

跟踪代码发现:
问题在NextServer.kt 第169行,beforeRouteHandlersTable[resourceUrl]?.get(httpMethod)?.plus(annotation)

handler 层支持 suspend

目前 handler 层不支持 suspend,如果将 render 改为 suspend 的话,需要将 handler 同步支持 suspend。

Handle建议

Handle是否可以修改为类似springmvc的 preHandle,postHandle,afterCompletion,以便做性能统计,方法耗时之类的
另外相同路径的Interceptor有多个的话,似乎后面的会覆盖前面的

前后端分离本地调试,前端vue请求后端服务接口失败,报CORS error

配置文件未配置属性cors,查看源码默认开启跨域访问的。
但,仍报跨域错误。
而用原生vertx代码,却是可以的。
router.route().handler(CorsHandler.create(".")
.allowCredentials(true)
.allowedMethods(setOf(HttpMethod.OPTIONS, HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE))
.allowedHeader("
")
.maxAgeSeconds(3600)
)

连接池优化

image

当用户配置了连接池类时,不要初始化默认的连接池

建议请求参数校验器直接返回参数错误信息

3.0 版本开始,添加了错误拦截的特性:
https://www.yuque.com/cloudopt/next/fwebaf

而请求参数校验,会直接返回 400 且不会抛出异常:
图片

如果不写错误拦截器,返回 400 时就不会显示具体参数错误,而会返回以下内容:

{"errorMessage":"Something is wrong, but no exception messages are caught.","error":"400"}

希望可以支持 2.x 版本那种做法,不添加错误拦截器也能在参数校验不通过时直接返回 400 和具体的校验错误信息,例如用户定义的:

{"error":1001,"errorMessage":"签名校验失败"}

依赖cloudopt-next-eventbus时,也必须同时依赖lettuce-core,否则启动打印类找不到。

net.cloudopt.next cloudopt-next-eventbus ${nextVersion}

java.lang.NoClassDefFoundError: io/lettuce/core/pubsub/RedisPubSubAdapter
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at net.cloudopt.next.core.Classer.loadClass(Classer.kt:169)
at net.cloudopt.next.core.Classer.fillClass(Classer.kt:365)
at net.cloudopt.next.core.Classer.processJarFile(Classer.kt:340)
at net.cloudopt.next.core.Classer.fillClasses(Classer.kt:235)
at net.cloudopt.next.core.Classer.scanPackage(Classer.kt:127)
at net.cloudopt.next.core.Classer.scanPackageByAnnotation(Classer.kt:83)
at net.cloudopt.next.web.NextServer.scan(NextServer.kt:208)
at net.cloudopt.next.web.NextServer.run(NextServer.kt:277)

java.lang.ClassNotFoundException: org.beetl.core.Configuration

pom.xml 引入依赖

<parent>
        <artifactId>cloudopt-next-parent</artifactId>
        <groupId>net.cloudopt.next</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
<dependency>
            <groupId>net.cloudopt.next</groupId>
            <artifactId>cloudopt-next-web</artifactId>
        </dependency>

App启动类

public class WikiApp {

    public static void main(String[] args) {
        CloudoptServer.run();
    }

}

IndexController 定义

@API("/")
public class IndexController extends Resource {

    @GET("index")
    public void index() {
        renderText("Cloudopt-next");
    }

}

main方法启动以后,浏览器地址栏访问http://localhost:8888/index

控制台报错:
java.lang.ClassNotFoundException:org.beetl.core.Configuration

pom.xml文件加入beetl依赖,访问就没没问题了
想知道,这个beetl依赖为什么没有引入

启动报出Thread blocked

2022-07-05 11:55:26.675 [vertx-blocked-thread-checker] WARN io.vertx.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2813 ms, time limit is 2000 ms
2022-07-05 11:55:27.681 [vertx-blocked-thread-checker] WARN io.vertx.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3820 ms, time limit is 2000 ms
2022-07-05 11:55:28.722 [vertx-blocked-thread-checker] WARN io.vertx.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 4861 ms, time limit is 2000 ms
2022-07-05 11:55:29.731 [vertx-blocked-thread-checker] WARN io.vertx.core.impl.BlockedThreadChecker - Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 5866 ms, time limit is 2000 ms
io.vertx.core.VertxException: Thread blocked
at [email protected]/java.io.WinNTFileSystem.getBooleanAttributes(Native Method)
at [email protected]/java.io.File.exists(File.java:820)
at [email protected]/java.io.WinNTFileSystem.lambda$listRoots$1(WinNTFileSystem.java:600)
at [email protected]/java.io.WinNTFileSystem$$Lambda$247/0x00000008004c3440.test(Unknown Source)
at [email protected]/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
at [email protected]/java.util.stream.IntPipeline$1$1.accept(IntPipeline.java:180)
at [email protected]/java.util.BitSet$1BitSetSpliterator.forEachRemaining(BitSet.java:1302)
at [email protected]/java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:699)
at [email protected]/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at [email protected]/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at [email protected]/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at [email protected]/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at [email protected]/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at [email protected]/java.io.WinNTFileSystem.listRoots(WinNTFileSystem.java:601)
at [email protected]/java.io.File.listRoots(File.java:1791)
at app//io.vertx.ext.web.handler.impl.StaticHandlerImpl.setRoot(StaticHandlerImpl.java:590)
at app//io.vertx.ext.web.handler.impl.StaticHandlerImpl.setWebRoot(StaticHandlerImpl.java:453)
at app//net.cloudopt.next.web.NextServerVerticle.start(NextServerVerticle.kt:220)
at app//io.vertx.kotlin.coroutines.CoroutineVerticle$start$1.invokeSuspend(CoroutineVerticle.kt:50)
at app//kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at app//kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at app//io.vertx.kotlin.coroutines.VertxCoroutineExecutor.execute(VertxCoroutine.kt:229)
at app//kotlinx.coroutines.ExecutorCoroutineDispatcherBase.dispatch(Executors.kt:94)
at app//kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:332)
at app//kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at app//kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at app//kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at app//kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at app//kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at app//kotlinx.coroutines.BuildersKt.launch(Unknown Source)
at app//kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at app//kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
at app//io.vertx.kotlin.coroutines.CoroutineVerticle.start(CoroutineVerticle.kt:48)
at app//io.vertx.core.impl.DeploymentManager.lambda$doDeploy$5(DeploymentManager.java:196)
at app//io.vertx.core.impl.DeploymentManager$$Lambda$234/0x00000008004c7c40.handle(Unknown Source)
at app//io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
at app//io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:59)
at app//io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:37)
at app//io.vertx.core.impl.EventLoopContext$$Lambda$116/0x000000080037e840.run(Unknown Source)
at app//io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:164)
at app//io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
at app//io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at app//io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at app//io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at app//io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at app//io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at [email protected]/java.lang.Thread.run(Thread.java:834)

部署到腾讯云 centos7 ,日志显示启动正常,但是任何请求都不响应。而在window 10上都正常。版本3.0.0.1.RELEASE

11:52:42,617 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
11:52:42,618 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
11:52:42,622 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/work/powerdesign/classes/logback.xml]
11:52:42,623 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
11:52:42,623 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/work/powerdesign/lib/cloudopt-next-web.jar!/logback.xml]
11:52:42,623 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [file:/work/powerdesign/classes/logback.xml]
11:52:42,748 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
11:52:42,749 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
11:52:42,756 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
11:52:42,763 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
11:52:42,842 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to INFO
11:52:42,842 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
11:52:42,842 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
11:52:42,843 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@a74868d - Registering current configuration as safe fallback point

[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ███╗ ██╗███████╗██╗ ██╗████████╗
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ████╗ ██║██╔════╝╚██╗██╔╝╚══██╔══╝
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ██╔██╗ ██║█████╗ ╚███╔╝ ██║
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ██║╚██╗██║██╔══╝ ██╔██╗ ██║
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ██║ ╚████║███████╗██╔╝ ██╗ ██║
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: Java Version: 11.0.9
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: Java Provider: Red Hat, Inc.
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: System: Linux
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: Time: 2021-05-30 11:52:43
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: Listener Port: 9090
[Cloudopt Next] 2021-05-30 11:52:43 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: -------------------------------------------------------------------------------------------
[Cloudopt Next] 2021-05-30 11:52:43 com.zaxxer.hikari.HikariDataSource [INFO ] - HikariPool-1 - Starting...
[Cloudopt Next] 2021-05-30 11:52:44 com.zaxxer.hikari.HikariDataSource [INFO ] - HikariPool-1 - Start completed.
[Cloudopt Next] 2021-05-30 11:52:44 com.zaxxer.hikari.HikariDataSource [INFO ] - HikariPool-1 - Starting...
[Cloudopt Next] 2021-05-30 11:52:44 com.zaxxer.hikari.HikariDataSource [INFO ] - HikariPool-1 - Start completed.
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [PLUGIN] Registered plugin:net.cloudopt.next.jooq.JooqPlugin
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [FAILURE HANDLER] Registered failure handler:net.cloudopt.next.web.handler.DefaultErrorHandler
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [HANDLER] Registered handler:net.cloudopt.next.web.handler.CorsHandler
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [HANDLER] Registered handler:net.cloudopt.next.web.handler.CookieCorsHandler
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [HANDLER] Registered handler:net.cloudopt.next.web.handler.WafHandler
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [HANDLER] Registered handler:net.cloudopt.next.web.handler.ShowRouteHandler
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource POST :addCellMeta | /api/addCellMeta
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource GET :listGraphFile | /api/listGraphFile
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource POST :modifyGraph | /api/modifyGraph
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource GET :queryCellSchemaMap | /api/queryCellSchemaMap
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource POST :queryGraph | /api/queryGraph
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource GET :querySideBarGroups | /api/querySideBarGroups
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: [RESOURCE] Registered resource POST :save | /api/save
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ==========================================================================================================
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO:  Cloudopt Next started success!
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: http://127.0.0.1:9090
[Cloudopt Next] 2021-05-30 11:52:44 net.cloudopt.next.web.NextServer [INFO ] - ℹ️ INFO: ==========================================================================================================

[root@VM-0-6-centos ~]# curl http://127.0.0.1:9090/static/index.html
curl: (52) Empty reply from server

bug: logger的实现类造成崩溃

我的cookie是这样的:
Cookie : "Phpstorm-385e8778=4b818d7f-e37d-49f1-bd6e-7a0ec9a27d09; PHPSESSID=luks4l55tj9j2t4c8actdkjnh3; Phpstorm-a03fb457=e86b135e-de94-4232-8e3f-b04158ee52fe; loggedon=26d1ebd4ec8c55cc69f190d0d37f6dac; filemanager=lg7p67m427lhmhe3tej9tefq00; fm_current_dir=D%3A%5C; _ga=GA1.1.701572348.1585020446; Phpstorm-66f14207=89186c57-4c50-4c74-ab23-4aa81b6bd591; io=VhmAg7_IBC33-941AAAA; JSESSIONID=B53DBEB5A049B01722CCC240BE257EC9"
其中%3A和%5C这种urlencode过的字符串,会被String.format误识别为标识符,造成格式化字符串报错。
Slf4JLogger 里面的实现,也有点问题,format之后又来一次*args。
logger.info("${Colorer.blue(Logger.configuration.infoPrefix)} ${String.format(message, *args)}", *args)

在实现上slf4j的logger比较好,使用的是{}来标识替代位置,这种不会造成格式化出错问题。

相关源码

logger.info("Cookie : ${Jsoner.toJsonString(resource.request.getHeader("Cookie") ?: "")}")

logger.info("${Colorer.blue(Logger.configuration.infoPrefix)} ${String.format(message, *args)}", *args)

"${Colorer.magenta(Logger.configuration.debugPrefix)} ${String.format(message, *args)}"

netty版本不一致,GraalVM打包netty报错,不知道是不是版本冲突引起。

提几个小小的但是自我感觉非常重要的更新建议哈:
1、netty版本需要更新一下,目前用的3.0.3.0-RELEASE版本,依赖列表可以看到4.1.65跟4.1.75两个版本,然后我看Cloudopt-next饮用的4.1.65,希望可以统一升级为4.1.75,我这边使用GraalVM打包netty报错,不知道是不是由于版本冲突导致的,因此无法打包成native可执行文件。
2、日志那个handle(ShowRouteHandler)的@AutoHandler这个注解希望可以移除掉,目前不太符合我们项目需求,需要自定义,如果自定义,每次请求都打印两部分日志,非常难受。(文档里面的示例可以展示给用户,让用户选择是否要用这个handle,也可以模仿这个handle自定义自己的日志handle)

目前就以上两个问题希望可以尽快解决一下,谢谢各位开源作者可以贡献出这么优质,易用轻量的kotlin的服务端框架!

getRootClassPath错误

Yamler的getRootClassPath方法在打jar包后运行出现异常.
qq 20180322163343.
另外如果是jar的话,似乎获取路径类似D:******.jar!\com**\包名

请增加application.json的处理方式

希望支持从jar包外加载application.json ,因为fatjar里面的这个配置文件修改起来不方便。
我的想法是:
思路一,首先从文件系统的当前路径或config目录下加载的application.json文件,如果加载不到,再从jar包里加载。
思路二,文件系统或config目录下的application.json,和jar包里的application.json,合并到一起,且外部的application.json优先。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.