目前很多 webMVc 框架,基本都要先写 Controller 类,然后注册或写注解,但对于现在的我来说,类似 Spring MVC 那一套衍生的开发体验不太好,不太利于开发者定制(相对于 node.js )。我想更简单地处理请求,直接用一个匿名类或函数式接口来处理所有的请求。因为越简单,就越容易定制。
比如下面这个: const server = http.crateServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World'); });
这是 node.js 的官方网址里的某个演示,非常简单的请求处理,就一个函数来处理所有请求
HttpServer server = Vertx.vertx().createHttpServer(); Router router = Router.router(Vertx.vertx()); router.route().handler(request -> { request.response().end("post");
}); 还有 java 的 vert.x,不过这个是面向完全响应式开发,对个人和团队的响应式知识掌握,以及代码组织能力都有不小的要求。
基本有 request 和 response 两个形式参数,其中 response 封装返回视图,返回 body,下载文件,输出图片,设置响应状态码……等常用响应输出的方法。框架本身已经封装了 session 和静态资源处理。
除了 vert.x,还有哪些 java 框架有这个功能。
1 2kCS5c0b0ITXE5k2 2020-06-06 14:08:31 +08:00 Spring boot? |
![]() | 2 chenuu 2020-06-06 14:10:27 +08:00 via Android |
3 fmumu 2020-06-06 14:11:44 +08:00 via Android 直接基于 servlet 不就行了 |
![]() | 4 tctc4869 OP @emeab Spring Boot 和我说的不是一个领域的,应该说是 Spring MVC,但是 Spring MVC 我并没有找到匿名类或函数式接口的请求处理的相关代码 |
![]() | 5 itechify PRO Vert.x |
6 hantsy 2020-06-06 14:14:52 +08:00 @tctc4869 Spring 5 最大的特点就是 Functional 编程模式。 https://github.com/hantsy/spring-reactive-sample/blob/master/boot-start-routes/src/main/java/com/example/demo/DemoApplication.java |
![]() | 7 lavvrence 2020-06-06 14:17:07 +08:00 使用 Spring WebFlux 试试: https://spring.io/guides/gs/reactive-rest-service/ |
8 Kyle18Tang 2020-06-06 14:18:15 +08:00 @hantsy #6 我也想到了 Webflux |
9 hantsy 2020-06-06 14:18:52 +08:00 |
10 hantsy 2020-06-06 14:45:18 +08:00 @Kyle18Tang Spring WebMvc 在 Spring 5.2 一样支持 Functional 。 https://github.com/hantsy/spring-webmvc-functional-sample |
11 hantsy 2020-06-06 14:52:40 +08:00 |
![]() | 12 myCupOfTea 2020-06-06 15:35:54 +08:00 Vert.x |
![]() | 13 myCupOfTea 2020-06-06 15:36:07 +08:00 你都提到 nodejs 呢 ,那就 Vert.x |
![]() | 14 Ariver 2020-06-06 15:41:57 +08:00 play 可以一试 |
16 yty2012g 2020-06-06 17:21:13 +08:00 首先,Spring MVC 也是可以只有 request 和 response 参数的,个人觉得并不复杂。其次,按照你的情况,可以推荐你使用 jetty embedded,一个 servlet,参数就是 request 和 response,想怎么定制都行。 |
![]() | 17 6IbA2bj5ip3tK49j 2020-06-06 17:23:18 +08:00 |
![]() | 18 46Gnj0E0OBmad377 2020-06-06 18:30:23 +08:00 via iPhone spark 感觉还成,就是楼上发了文档那个 |
20 hantsy 2020-06-06 18:42:02 +08:00 SparkJava 对 Kotlin 支持不错,想到了 Jetbrains 还有自己的 Ktor 。 |
![]() | 21 zjsxwc 2020-06-06 19:55:13 +08:00 via Android web 开发用 grails groovy 挺好的 |
![]() | 22 iyangyuan 2020-06-07 00:22:52 +08:00 via iPhone 没看到有人推荐 Nutz,看来我真的老了 |
![]() | 23 tctc4869 OP @yty2012g @hantsy 我想可能搞错了什么,而且我要的并不是所谓的函数式接口来处理请求,我想要的是一个方法处理所有的请求,与函数式接口相差不大,匿名类就可以弄。在这个方法体内,我自己来处理 request 到 response 的流程。然后借助 MVC 框架本身自带的常用响应方式的代码封装,例如响应 body,响应一个视图以及模板渲染,响应文件下载,响应图片生成等,这些 MVC 框架基本都封装好了。而如果用 Servlet,可能还得重复写轮子。 我看了一下目前回复里发的 Spring MVC 的那个演示代码,我基本感觉写的很怪异,而且指明 GET,POST,都指明了请求方法,那就处理不了所有的请求了,代码风格好奇怪,感觉明明可以不用那么奇怪的开发风格。可能我没找到关键地方,在此之前,感觉还是回到 Spring MVC 的传统 Controller 来处理比较好。要么就是 vert.x 来做,至少 vert.x-web 写的不是那么难看,而且可以为一个方法配置处理所有的请求,就是很考验响应式编程代码组织能力。 |
![]() | 24 tctc4869 OP @iyangyuan nutz 能做?目前为止,我在 nutz 文档中,没有找到含有“直接处理所有的请求”的配置方式说明。 |
![]() | 25 gaius 2020-06-07 00:32:53 +08:00 via Android 你这个思路不得反射去调方法 |
![]() | 26 watzds 2020-06-07 00:41:32 +08:00 via Android 处理所有请求有啥好的,那用 filter 吧哈哈 |
![]() | 27 TMaize 2020-06-07 01:01:29 +08:00 via Android 试试这个,不过不是标准的 servlet https://lets-blade.com/ |
![]() | 28 movistar 2020-06-07 02:11:30 +08:00 如果目标只是想接收所有的 HTTP 请求然后统一处理(类似 gateway 做中转,外加一点点简单逻辑这种场景) 有啥难的啊,现成的 web 框架把对应的 dispatcher 删了重写一个就完事了.... 什么 HTTP 框架都好改,又不是不能改框架的源代码.... 当然最好的方式当然是用 lua 写在 nginx 上,不过如果只熟悉 Java 技术栈,性能要求也不高的情况下,那都可以 |
29 roundgis 2020-06-07 03:14:12 +08:00 via Android ![]() javalin |
![]() | 30 46Gnj0E0OBmad377 2020-06-07 04:07:43 +08:00 @hantsy #19 我也发现了这个问题,一直不知道怎么称呼这个东西 是不是就叫 sparkjava 。。。 |
31 cgpiao 2020-06-07 07:23:22 +08:00 via Android Http4k |
32 kidcats 2020-06-07 08:13:18 +08:00 via Android ktor 貌似也不错 |
33 hantsy 2020-06-07 09:04:52 +08:00 @tctc4869 你可能 Java 8 的语法不熟悉吧。只是把处理的部分抽出来了而已。实际应用所有的代码放到一个方法,不现实。 Spring WebMvc 和 WebFlux 的 API 基本是一致的(当然是不同的实现),除了 MVC 不用 Reactor ( Mono, Flux ),而用传统的 Imperative APIs 外。 |
34 hantsy 2020-06-07 09:07:47 +08:00 @tctc4869 NodeJS Express 我也写,从来没把所有的逻辑放到一个方法里面,routes 也层层传递下去。放到一个方法(或者 Fun )里面只是做 Demo 的时候才用的。 |
35 hantsy 2020-06-07 09:11:03 +08:00 @cgpiao 这个货有一个系列,http 4X, 不过不怎么流行。 Spring 真正做到编程 Functional 化,我们期待 Spring Fu 吧,目前 0.3,我刚开始玩。 https://github.com/hantsy/spring-kotlin-dsl-sample/blob/master/kofu-reactive-mongo/src/main/kotlin/com/example/demo/DemoApplication.kt |
![]() | 36 realkenshinji 2020-06-07 09:47:26 +08:00 via iPhone sparkjava ? |
![]() | 37 tt0411 2020-06-07 12:36:18 +08:00 sparkjava, 写简单的服务够用; 但是当服务复杂性上去后, 还是逐渐走向 spring boot |
![]() | 38 fanfpy 2020-06-07 13:09:11 +08:00 blade? |
![]() | 39 xcstream 2020-06-07 16:03:09 +08:00 jfinal |
![]() | 40 751762476 2020-06-07 16:34:32 +08:00 jooby Micronaut vertx ktor |
![]() | 41 tctc4869 OP jfinal 有么? jfinal 还是得写 Controller 把 |
43 hantsy 2020-06-07 19:22:06 +08:00 @tt0411 这个跟工具框架本身没有什么关系,关键生态不一样。Spring 的生态太成熟,使用它是为了偷懒。 其实项目到了一定程度,你会发现 Spring Boot 默认自动配置会成为很大一个性能包袱,加载的东西太多了。 我的最简单的例子,同样的 CRUD 功能(使用数据库)在 Quarkus 下启动快很多,如果用 Native Image 打包,最终启动会比 Spring Boot 快 20 倍以上。 https://github.com/hantsy/quarkus-sample/blob/master/docs/01-start.md 使用 Native Image 打包在 Docker 中启动仅 0.267 秒。 有些具有极客文化的小公司很抵制 Spring Boot 傻瓜式的自动配置,而坚持用一些简洁的框架(全部手动配置)。 |
45 hantsy 2020-06-07 20:35:59 +08:00 @echo1937 1,启动速度慢会影响到开发效率。 2,运行时,处理请求响应速度也会有一定的影响。用 Spring Boot 启动太多的 Bean,很多你可能根本就用不到,导致一个请求内过多生命周期相关 Bean 参与。 3,再就是运行时资源消耗太多了,这个影响也是比较大,最终影响到项目的运维成本,你可能需要更多的硬件。 |
46 taoprogramer 2020-06-09 14:07:24 +08:00 @hantsy 开发效率这个问题你可以用 jrebel 这种工具热加载解决,不需要重启,这些多余的 bean 产生的影响远小于数据库 /中间件读写慢带来的性能问题,绝大部分业务系统只需要在数据读写层面做优化就可以了。 |
47 hantsy 2020-06-10 09:23:12 +08:00 好了,看到有不少用在用 Vertx 。近两年玩了一下 Vertx+Quarkus+Munity,有一个问题请教,https://stackoverflow.com/questions/62275644/failure-handler-issue-using-vertx-web-routes-and-minity-in-a-quarkus-application |
48 hantsy 2020-06-10 09:29:39 +08:00 写 Vertx Web Router 这种感觉太原始了,和 Spring RouterFunction 体验差了点。 |
![]() | 49 tctc4869 OP @hantsy 我又不是写太多 Vertx Web Router,我就写几个 Router,然后里面执行自己编写的 Web 处理流程代码去了。 |
50 hantsy 2020-06-10 11:45:40 +08:00 哦,上面写错了,近两年-》近两天。 |
![]() | 51 tctc4869 OP @hantsy 我补充一下吧,想要的是这样一个 webMVC 框架,要做到,接收所有请求,请求分派处理代码( Controller,Action 之类,action 拦截器之类的),请求响应,这一个流程要解耦成三个,接收所有请求,请求分派,响应请求。其中请求分派处理,我自己定义, 而 响应客户端和获取请求内容,框架本身自带常用请求获取和响应方法,开发者只需调用就可以,例如获取上传文件,跨域处理,下载文件,输出字符串,输出模板引擎渲染的动态页面。输出生成的图片到客户端。也容易扩展 如果用 servlet,那要造很多轮子。而 vert.x-web 是满足这个条件的,代码非常简单,用很简单的代码就能处理所有请求,还自带了一些编辑的请求与响应方法,比如 fileUploads,接收上传文件。sendFile 下载文件。并不是因为 vert.x 有函数式接口,而是因为他做到了将请求接收,请求分派,响应客户端解耦成三个了。也可以不用框架自带的请求分派,自己编写一条请求分派规则都行。这是我喜欢的一点。 |
52 hantsy 2020-06-11 09:05:10 +08:00 @tctc4869 没看出来那么大差别。 Spring 的 Controller,RouterFunction 最终都是 Spring 底层的 HTTPHandler 处理的。他们差别只是在于 Path 匹配方式,Path 相应的 Handler 写法不一样而已。两种方式几乎可以 100%互换。对于开发人员只是看你喜欢哪种方式而已。 在 Quarkus 中,它扩展原来的 Vertx Web Router,支持 Annotation 方式。https://quarkus.io/guides/reactive-routes |
![]() | 53 tctc4869 OP @hantsy 那可以直接用 Spring 底层的那个 HTTPHandler 么?如果能用的话,自己如果要方便获取请求与响应,是不是还得写一套代码? |
![]() | 55 tctc4869 OP @hantsy 能直接做到类似下面的代码么? 演示代码: public void handler(request,response){ if(request.path=="/test/test2"&& request.mothed=="Post"){ response.endError(403) }else if(request.path=="/test/test3"){ response.end("hello word"); }else if(request.path=="/test/test4"){ response.set("abc","123"); response.View("/test/test4.html"); }else if(request.path=="/test/test5"){ Set<File> files= request.getFiles(); }else if(request.path=="/test/test6"){ response.endFile(new File("d:/1.txt")) }else{ response.sendRedirect("www.baidu.com"); } } |
56 hantsy 2020-06-11 09:41:41 +08:00 @tctc4869 不管是上面我的 Spring MVC Functional,还是 Vertx,还是什么其它都是可以写成这样。只是为了代码维护,按路由规则拆开而已。 你这种 ifelse hole 在正式项目中,只要是个正常人都接受不了这种代码。 |
57 hantsy 2020-06-11 09:47:30 +08:00 你可以直接用原始 Servlet 就好了,满足你的全部要求。 https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html override `service` 方法就行了,其它 doXXX 直接调用 service 。 |
![]() | 58 putaozhenhaochi 2020-06-11 09:58:38 +08:00 Micronaut |
61 hantsy 2020-06-11 10:35:34 +08:00 写一个 Servlet,比如叫 MyServlet,映射到所有的 Request,/* 剩下的就是一个方法接收两个参数 request, response,想怎么搞都行。 没遇到 Apache Struts 1 之前,很多人都是这么写的。恶梦一般的回忆。那是 15 年前的事了。 |
![]() | 62 tctc4869 OP @hantsy 我的目的是拦截所有请求,调用自己的路由规则处理请求,同时需要便捷的请求内容获取和响应客户端的工具类。 正因为 servlet 太原始了,我才不想用 servlet,servlet 获取请求内容和设置响应的代码有点嗦,如果要编写响应ajax,文件下载,文件上传,渲染动态页面(不是 jsp,是 html ),就得写重复的工具轮子。 国内有一个叫 jfinal 的框架做到了,它有一个 handler 组件,组成非常简单,能拦截任何请求,可以在当前直接处理请求响应客户端,也可以下一步用框架自带的路由规则处理,也可以调用开发者自己定义的路由规则处理。而且还封装了 request,response 工具类。非常方便。 |
63 hantsy 2020-06-11 11:11:17 +08:00 @tctc4869 Spring Reactive 中 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/server/HandlerFunction.html 还上面提到的 Spring WebMvc Functional 版本与这个类似,只是不用 Reactor 。我上面帖出的代码,都是用 Method Reference (如果用 Labmda 也一样),你找不到这个接口痕迹而已。 |
64 hantsy 2020-06-11 11:12:39 +08:00 |