V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tctc4869
V2EX  ›  Java

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

  •  
  •   tctc4869 · 2020-06-06 14:04:56 +08:00 · 6041 次点击
    这是一个创建于 1665 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前很多 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-06-11 08:48:08 +08:00
    提供一个方法代码接收所有请求,这个代码可以是函数式接口,也可以是一个抽象类或接口里面的抽象方法,该方法会接收所有的入站请求,开发者也可以在这个方法内直接编写响应代码,直接响应给客户端,不用传达给下一个组件处理,也可以调用请求分派器,或调用自己编写的请求分派器,

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

    有人提到了 Servlet,不过用 Servlet 要造很多轮子。
    64 条回复    2020-06-11 11:12:39 +08:00
    2kCS5c0b0ITXE5k2
        1
    2kCS5c0b0ITXE5k2  
       2020-06-06 14:08:31 +08:00
    Spring boot?
    chenuu
        2
    chenuu  
       2020-06-06 14:10:27 +08:00 via Android
    fmumu
        3
    fmumu  
       2020-06-06 14:11:44 +08:00 via Android
    直接基于 servlet 不就行了
    tctc4869
        4
    tctc4869  
    OP
       2020-06-06 14:11:51 +08:00
    @emeab Spring Boot 和我说的不是一个领域的,应该说是 Spring MVC,但是 Spring MVC 我并没有找到匿名类或函数式接口的请求处理的相关代码
    oneisall8955
        5
    oneisall8955  
       2020-06-06 14:13:09 +08:00 via Android
    Vert.x
    hantsy
        6
    hantsy  
       2020-06-06 14:14:52 +08:00
    jaylee4869
        7
    jaylee4869  
       2020-06-06 14:17:07 +08:00
    Kyle18Tang
        8
    Kyle18Tang  
       2020-06-06 14:18:15 +08:00
    @hantsy #6 我也想到了 Webflux
    hantsy
        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
    myCupOfTea
        12
    myCupOfTea  
       2020-06-06 15:35:54 +08:00
    Vert.x
    myCupOfTea
        13
    myCupOfTea  
       2020-06-06 15:36:07 +08:00
    你都提到 nodejs 呢 ,那就 Vert.x
    Ariver
        14
    Ariver  
       2020-06-06 15:41:57 +08:00
    play
    可以一试
    hantsy
        15
    hantsy  
       2020-06-06 15:55:25 +08:00
    @Ariver Play 不如 Akka Http 舒服
    yty2012g
        16
    yty2012g  
       2020-06-06 17:21:13 +08:00
    首先,Spring MVC 也是可以只有 request 和 response 参数的,个人觉得并不复杂。其次,按照你的情况,可以推荐你使用 jetty embedded,一个 servlet,参数就是 request 和 response,想怎么定制都行。
    6IbA2bj5ip3tK49j
        17
    6IbA2bj5ip3tK49j  
       2020-06-06 17:23:18 +08:00
    http://sparkjava.com/documentation#getting-started

    个人一些简单的小项目 /工具需要 web 就用这个,完全符合你的要求。
    tsaohai
        18
    tsaohai  
       2020-06-06 18:30:23 +08:00 via iPhone
    spark 感觉还成,就是楼上发了文档那个
    hantsy
        19
    hantsy  
       2020-06-06 18:41:15 +08:00
    @tsaohai 单纯的 Spark 会让你产生混淆,一般会想到 Apache Spark 。
    hantsy
        20
    hantsy  
       2020-06-06 18:42:02 +08:00
    SparkJava 对 Kotlin 支持不错,想到了 Jetbrains 还有自己的 Ktor 。
    zjsxwc
        21
    zjsxwc  
       2020-06-06 19:55:13 +08:00 via Android
    web 开发用 grails groovy 挺好的
    iyangyuan
        22
    iyangyuan  
       2020-06-07 00:22:52 +08:00 via iPhone
    没看到有人推荐 Nutz,看来我真的老了😂
    tctc4869
        23
    tctc4869  
    OP
       2020-06-07 00:23:42 +08:00
    @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-06-07 00:30:25 +08:00
    @iyangyuan nutz 能做?目前为止,我在 nutz 文档中,没有找到含有“直接处理所有的请求”的配置方式说明。
    gaius
        25
    gaius  
       2020-06-07 00:32:53 +08:00 via Android
    你这个思路不得反射去调方法🐶
    watzds
        26
    watzds  
       2020-06-07 00:41:32 +08:00 via Android
    处理所有请求有啥好的,那用 filter 吧哈哈
    TMaize
        27
    TMaize  
       2020-06-07 01:01:29 +08:00 via Android
    试试这个,不过不是标准的 servlet
    https://lets-blade.com/
    movistar
        28
    movistar  
       2020-06-07 02:11:30 +08:00
    如果目标只是想接收所有的 HTTP 请求然后统一处理(类似 gateway 做中转,外加一点点简单逻辑这种场景)
    有啥难的啊,现成的 web 框架把对应的 dispatcher 删了重写一个就完事了....
    什么 HTTP 框架都好改,又不是不能改框架的源代码....

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

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

    响应客户端和获取请求内容,框架本身自带常用请求获取和响应方法,开发者只需调用就可以,例如获取上传文件,跨域处理,下载文件,输出字符串,输出模板引擎渲染的动态页面。输出生成的图片到客户端。也容易扩展

    如果用 servlet,那要造很多轮子。而 vert.x-web 是满足这个条件的,代码非常简单,用很简单的代码就能处理所有请求,还自带了一些编辑的请求与响应方法,比如 fileUploads,接收上传文件。sendFile 下载文件。并不是因为 vert.x 有函数式接口,而是因为他做到了将请求接收,请求分派,响应客户端解耦成三个了。也可以不用框架自带的请求分派,自己编写一条请求分派规则都行。这是我喜欢的一点。
    hantsy
        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
    tctc4869
        53
    tctc4869  
    OP
       2020-06-11 09:16:50 +08:00
    @hantsy 那可以直接用 Spring 底层的那个 HTTPHandler 么?如果能用的话,自己如果要方便获取请求与响应,是不是还得写一套代码?
    tctc4869
        54
    tctc4869  
    OP
       2020-06-11 09:17:57 +08:00
    @tctc4869 我的意思不是写 Controller,action,而是响应客户端,获取请求内容的便捷性。
    tctc4869
        55
    tctc4869  
    OP
       2020-06-11 09:35:58 +08:00
    @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-06-11 09:41:41 +08:00
    @tctc4869 不管是上面我的 Spring MVC Functional,还是 Vertx,还是什么其它都是可以写成这样。只是为了代码维护,按路由规则拆开而已。

    你这种 ifelse hole 在正式项目中,只要是个正常人都接受不了这种代码。
    hantsy
        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 。
    putaozhenhaochi
        58
    putaozhenhaochi  
       2020-06-11 09:58:38 +08:00
    Micronaut
    tctc4869
        59
    tctc4869  
    OP
       2020-06-11 10:16:00 +08:00
    @xcstream jfinal,找到了,jfinal 的 handler 可以做到
    tctc4869
        60
    tctc4869  
    OP
       2020-06-11 10:29:48 +08:00
    @hantsy 你误解的很厉害了。一个演示代码就让你觉得对方是个只想写 ifelse 的笨蛋
    hantsy
        61
    hantsy  
       2020-06-11 10:35:34 +08:00
    写一个 Servlet,比如叫 MyServlet,映射到所有的 Request,/*
    剩下的就是一个方法接收两个参数 request, response,想怎么搞都行。

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

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

    国内有一个叫 jfinal 的框架做到了,它有一个 handler 组件,组成非常简单,能拦截任何请求,可以在当前直接处理请求响应客户端,也可以下一步用框架自带的路由规则处理,也可以调用开发者自己定义的路由规则处理。而且还封装了 request,response 工具类。非常方便。
    hantsy
        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 也一样),你找不到这个接口痕迹而已。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2763 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:35 · PVG 19:35 · LAX 03:35 · JFK 06:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.