tctc4869
V2EX  ›  Java

Java 现在有哪些具备极简处理请求功能的 WebMVC 框架?

By tctc4869 at 2020 年 6 月 6 日 · 7203 次点击

目前很多 webMVc 框架,基本都要先写 Controller 类,然后注册或写注解,但对于现在的我来说,类似 Spring MVC 那一套衍生的开发体验不太好,不太利于开发者定制(相对于 node.js )。我想更简单地处理请求,直接用一个匿名类或函数式接口来处理所有的请求。因为越简单,就越容易定制。

比如下面这个: const server = http.createServer((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 条附言  ·  2020 年 6 月 11 日
提供一个方法代码接收所有请求,这个代码可以是函数式接口,也可以是一个抽象类或接口里面的抽象方法,该方法会接收所有的入站请求,开发者也可以在这个方法内直接编写响应代码,直接响应给客户端,不用传达给下一个组件处理,也可以调用请求分派器,或调用自己编写的请求分派器,

本身自带常用的 http 请求内容获取和 http 请求响应方法。例如获取上传文件,跨域处理,输出模板引擎渲染的页面到客户端,输出图片,下载文件,输出字符串等。静态资源过滤

有人提到了 Servlet,不过用 Servlet 要造很多轮子。
64 条回复  •  2020-06-11 11:12:39 +08:00
2kCS5c0b0ITXE5k2
   1
2kCS5c0b0ITXE5k2  
   2020 年 6 月 6 日
Spring boot?
chenuu
   2
chenuu  
   2020 年 6 月 6 日 via Android
fmumu
   3
fmumu  
   2020 年 6 月 6 日 via Android
直接基于 servlet 不就行了
tctc4869
   4
tctc4869  
OP
   2020 年 6 月 6 日
@emeab Spring Boot 和我说的不是一个领域的,应该说是 Spring MVC,但是 Spring MVC 我并没有找到匿名类或函数式接口的请求处理的相关代码
itechify
   5
itechify  
   2020 年 6 月 6 日 via Android
Vert.x
hantsy
   6
hantsy  
   2020 年 6 月 6 日
lavvrence
   7
lavvrence  
   2020 年 6 月 6 日
Kyle18Tang
   8
Kyle18Tang  
   2020 年 6 月 6 日
@hantsy #6 我也想到了 Webflux
hantsy
   10
hantsy  
   2020 年 6 月 6 日
@Kyle18Tang Spring WebMvc 在 Spring 5.2 一样支持 Functional 。

https://github.com/hantsy/spring-webmvc-functional-sample
myCupOfTea
   12
myCupOfTea  
   2020 年 6 月 6 日
Vert.x
myCupOfTea
   13
myCupOfTea  
   2020 年 6 月 6 日
你都提到 nodejs 呢 ,那就 Vert.x
Ariver
   14
Ariver  
   2020 年 6 月 6 日
play
可以一试
hantsy
   15
hantsy  
   2020 年 6 月 6 日
@Ariver Play 不如 Akka Http 舒服
yty2012g
   16
yty2012g  
   2020 年 6 月 6 日
首先,Spring MVC 也是可以只有 request 和 response 参数的,个人觉得并不复杂。其次,按照你的情况,可以推荐你使用 jetty embedded,一个 servlet,参数就是 request 和 response,想怎么定制都行。
6IbA2bj5ip3tK49j
   17
6IbA2bj5ip3tK49j  
   2020 年 6 月 6 日
http://sparkjava.com/documentation#getting-started

个人一些简单的小项目 /工具需要 web 就用这个,完全符合你的要求。
46Gnj0E0OBmad377
   18
46Gnj0E0OBmad377  
   2020 年 6 月 6 日 via iPhone
spark 感觉还成,就是楼上发了文档那个
hantsy
   19
hantsy  
   2020 年 6 月 6 日
@tsaohai 单纯的 Spark 会让你产生混淆,一般会想到 Apache Spark 。
hantsy
   20
hantsy  
   2020 年 6 月 6 日
SparkJava 对 Kotlin 支持不错,想到了 Jetbrains 还有自己的 Ktor 。
zjsxwc
   21
zjsxwc  
   2020 年 6 月 6 日 via Android
web 开发用 grails groovy 挺好的
iyangyuan
   22
iyangyuan  
   2020 年 6 月 7 日 via iPhone
没看到有人推荐 Nutz,看来我真的老了😂
tctc4869
   23
tctc4869  
OP
   2020 年 6 月 7 日
@yty2012g
@hantsy
我想可能搞错了什么,而且我要的并不是所谓的函数式接口来处理请求,我想要的是一个方法处理所有的请求,与函数式接口相差不大,匿名类就可以弄。在这个方法体内,我自己来处理 request 到 response 的流程。然后借助 MVC 框架本身自带的常用响应方式的代码封装,例如响应 body,响应一个视图以及模板渲染,响应文件下载,响应图片生成等,这些 MVC 框架基本都封装好了。而如果用 Servlet,可能还得重复写轮子。

我看了一下目前回复里发的 Spring MVC 的那个演示代码,我基本感觉写的很怪异,而且指明 GET,POST,都指明了请求方法,那就处理不了所有的请求了,代码风格好奇怪,感觉明明可以不用那么奇怪的开发风格。可能我没找到关键地方,在此之前,感觉还是回到 Spring MVC 的传统 Controller 来处理比较好。要么就是 vert.x 来做,至少 vert.x-web 写的不是那么难看,而且可以为一个方法配置处理所有的请求,就是很考验响应式编程代码组织能力。
tctc4869
   24
tctc4869  
OP
   2020 年 6 月 7 日
@iyangyuan nutz 能做?目前为止,我在 nutz 文档中,没有找到含有“直接处理所有的请求”的配置方式说明。
gaius
   25
gaius  
   2020 年 6 月 7 日 via Android
你这个思路不得反射去调方法🐶
watzds
   26
watzds  
   2020 年 6 月 7 日 via Android
处理所有请求有啥好的,那用 filter 吧哈哈
TMaize
   27
TMaize  
   2020 年 6 月 7 日 via Android
试试这个,不过不是标准的 servlet
https://lets-blade.com/
movistar
   28
movistar  
   2020 年 6 月 7 日
如果目标只是想接收所有的 HTTP 请求然后统一处理(类似 gateway 做中转,外加一点点简单逻辑这种场景)
有啥难的啊,现成的 web 框架把对应的 dispatcher 删了重写一个就完事了....
什么 HTTP 框架都好改,又不是不能改框架的源代码....

当然最好的方式当然是用 lua 写在 nginx 上,不过如果只熟悉 Java 技术栈,性能要求也不高的情况下,那都可以
roundgis
   29
roundgis  
   2020 年 6 月 7 日 via Android   ❤️ 1
javalin
46Gnj0E0OBmad377
   30
46Gnj0E0OBmad377  
   2020 年 6 月 7 日
@hantsy #19 我也发现了这个问题,一直不知道怎么称呼这个东西 🤣 是不是就叫 sparkjava 。。。
cgpiao
   31
cgpiao  
   2020 年 6 月 7 日 via Android
Http4k
kidcats
   32
kidcats  
   2020 年 6 月 7 日 via Android
ktor 貌似也不错
hantsy
   33
hantsy  
   2020 年 6 月 7 日
@tctc4869 你可能 Java 8 的语法不熟悉吧。只是把处理的部分抽出来了而已。实际应用所有的代码放到一个方法,不现实。

Spring WebMvc 和 WebFlux 的 API 基本是一致的(当然是不同的实现),除了 MVC 不用 Reactor ( Mono, Flux ),而用传统的 Imperative APIs 外。
hantsy
   34
hantsy  
   2020 年 6 月 7 日
@tctc4869 NodeJS Express 我也写,从来没把所有的逻辑放到一个方法里面,routes 也层层传递下去。放到一个方法(或者 Fun )里面只是做 Demo 的时候才用的。
hantsy
   35
hantsy  
   2020 年 6 月 7 日
@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
realkenshinji
   36
realkenshinji  
   2020 年 6 月 7 日 via iPhone
sparkjava ?
tt0411
   37
tt0411  
   2020 年 6 月 7 日
sparkjava, 写简单的服务够用; 但是当服务复杂性上去后, 还是逐渐走向 spring boot
fanfpy
   38
fanfpy  
   2020 年 6 月 7 日
blade?
xcstream
   39
xcstream  
   2020 年 6 月 7 日
jfinal
751762476
   40
751762476  
   2020 年 6 月 7 日
jooby
Micronaut
vertx
ktor
tctc4869
   41
tctc4869  
OP
   2020 年 6 月 7 日
jfinal 有么? jfinal 还是得写 Controller 把
hantsy
   42
hantsy  
   2020 年 6 月 7 日
@751762476 Micronaut 真心不错,功能很全面。如果厌烦了写 Spring,可以试下这个。
hantsy
   43
hantsy  
   2020 年 6 月 7 日
@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 傻瓜式的自动配置,而坚持用一些简洁的框架(全部手动配置)。
echo1937
   44
echo1937  
   2020 年 6 月 7 日
@hantsy 所谓的性能包袱,实际上就是启动速度慢了,数量众多的自动配置并不影响处理速度。
hantsy
   45
hantsy  
   2020 年 6 月 7 日
@echo1937
1,启动速度慢会影响到开发效率。
2,运行时,处理请求响应速度也会有一定的影响。用 Spring Boot 启动太多的 Bean,很多你可能根本就用不到,导致一个请求内过多生命周期相关 Bean 参与。
3,再就是运行时资源消耗太多了,这个影响也是比较大,最终影响到项目的运维成本,你可能需要更多的硬件。
taoprogramer
   46
taoprogramer  
   2020 年 6 月 9 日
@hantsy
开发效率这个问题你可以用 jrebel 这种工具热加载解决,不需要重启,这些多余的 bean 产生的影响远小于数据库 /中间件读写慢带来的性能问题,绝大部分业务系统只需要在数据读写层面做优化就可以了。
hantsy
   47
hantsy  
   2020 年 6 月 10 日
好了,看到有不少用在用 Vertx 。近两年玩了一下 Vertx+Quarkus+Munity,有一个问题请教,https://stackoverflow.com/questions/62275644/failure-handler-issue-using-vertx-web-routes-and-minity-in-a-quarkus-application
hantsy
   48
hantsy  
   2020 年 6 月 10 日
写 Vertx Web Router 这种感觉太原始了,和 Spring RouterFunction 体验差了点。
tctc4869
   49
tctc4869  
OP
   2020 年 6 月 10 日
@hantsy 我又不是写太多 Vertx Web Router,我就写几个 Router,然后里面执行自己编写的 Web 处理流程代码去了。
hantsy
   50
hantsy  
   2020 年 6 月 10 日
哦,上面写错了,近两年-》近两天。
tctc4869
   51
tctc4869  
OP
   2020 年 6 月 11 日
@hantsy 我补充一下吧,想要的是这样一个 webMVC 框架,要做到,接收所有请求,请求分派处理代码( Controller,Action 之类,action 拦截器之类的),请求响应,这一个流程要解耦成三个,接收所有请求,请求分派,响应请求。其中请求分派处理,我自己定义,
而
响应客户端和获取请求内容,框架本身自带常用请求获取和响应方法,开发者只需调用就可以,例如获取上传文件,跨域处理,下载文件,输出字符串,输出模板引擎渲染的动态页面。输出生成的图片到客户端。也容易扩展

如果用 servlet,那要造很多轮子。而 vert.x-web 是满足这个条件的,代码非常简单,用很简单的代码就能处理所有请求,还自带了一些编辑的请求与响应方法,比如 fileUploads,接收上传文件。sendFile 下载文件。并不是因为 vert.x 有函数式接口,而是因为他做到了将请求接收,请求分派,响应客户端解耦成三个了。也可以不用框架自带的请求分派,自己编写一条请求分派规则都行。这是我喜欢的一点。
hantsy
   52
hantsy  
   2020 年 6 月 11 日
@tctc4869 没看出来那么大差别。
Spring 的 Controller,RouterFunction 最终都是 Spring 底层的 HTTPHandler 处理的。他们差别只是在于 Path 匹配方式,Path 相应的 Handler 写法不一样而已。两种方式几乎可以 100%互换。对于开发人员只是看你喜欢哪种方式而已。

在 Quarkus 中,它扩展原来的 Vertx Web Router,支持 Annotation 方式。https://quarkus.io/guides/reactive-routes
tctc4869
   53
tctc4869  
OP
   2020 年 6 月 11 日
@hantsy 那可以直接用 Spring 底层的那个 HTTPHandler 么?如果能用的话,自己如果要方便获取请求与响应,是不是还得写一套代码?
tctc4869
   54
tctc4869  
OP
   2020 年 6 月 11 日
@tctc4869 我的意思不是写 Controller,action,而是响应客户端,获取请求内容的便捷性。
tctc4869
   55
tctc4869  
OP
   2020 年 6 月 11 日
@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");
}

}
hantsy
   56
hantsy  
   2020 年 6 月 11 日
@tctc4869 不管是上面我的 Spring MVC Functional,还是 Vertx,还是什么其它都是可以写成这样。只是为了代码维护,按路由规则拆开而已。

你这种 ifelse hole 在正式项目中,只要是个正常人都接受不了这种代码。
hantsy
   57
hantsy  
   2020 年 6 月 11 日
你可以直接用原始 Servlet 就好了,满足你的全部要求。

https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html

override `service` 方法就行了,其它 doXXX 直接调用 service 。
putaozhenhaochi
   58
putaozhenhaochi  
   2020 年 6 月 11 日
Micronaut
tctc4869
   59
tctc4869  
OP
   2020 年 6 月 11 日
@xcstream jfinal,找到了,jfinal 的 handler 可以做到
tctc4869
   60
tctc4869  
OP
   2020 年 6 月 11 日
@hantsy 你误解的很厉害了。一个演示代码就让你觉得对方是个只想写 ifelse 的笨蛋
hantsy
   61
hantsy  
   2020 年 6 月 11 日
写一个 Servlet,比如叫 MyServlet,映射到所有的 Request,/*
剩下的就是一个方法接收两个参数 request, response,想怎么搞都行。

没遇到 Apache Struts 1 之前,很多人都是这么写的。恶梦一般的回忆。那是 15 年前的事了。
tctc4869
   62
tctc4869  
OP
   2020 年 6 月 11 日
@hantsy 我的目的是拦截所有请求,调用自己的路由规则处理请求,同时需要便捷的请求内容获取和响应客户端的工具类。

正因为 servlet 太原始了,我才不想用 servlet,servlet 获取请求内容和设置响应的代码有点啰嗦,如果要编写响应 ajax,文件下载,文件上传,渲染动态页面(不是 jsp,是 html ),就得写重复的工具轮子。

国内有一个叫 jfinal 的框架做到了,它有一个 handler 组件,组成非常简单,能拦截任何请求,可以在当前直接处理请求响应客户端,也可以下一步用框架自带的路由规则处理,也可以调用开发者自己定义的路由规则处理。而且还封装了 request,response 工具类。非常方便。
hantsy
   63
hantsy  
   2020 年 6 月 11 日
@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 也一样),你找不到这个接口痕迹而已。
© 2026 V2EX · 72ms · 3.9.8.5