Javalin - 发现 Java 的可爱之处

2022-08-31 17:58:07 +08:00
 SuperMild

多年以前我看到一篇神奇的文章 Java for Everything, 其中提出了一个大胆的想法:就连脚本小工具都用 Java 来写。

我读了这篇文章,但并没有立即使用 Java, 而是写了一段时间 Go, 又写了一段时间 Python, 最近想起这篇文章,就想用 Java 写点东西。

Java 的优点

  1. 易学 (而且程序员几乎都或多或少已经学过), 学习资料丰富
  2. 工具齐全 (比如有 IntelliJ IDEA, 有 maven)
  3. 生态强大,第三方库丰富
  4. 稳重感、安心感。Java 经过了多年工业级考验,能带给我很 "稳" 的心理暗示, 有一种脚踏实地的安全感。

Java 的缺点

本来 Java 是很啰嗦的,这是它最被诟病的地方了。

但现在 Java 有了 record, lambda, Stream API, var(类型推断) 等等, 已经变得不是太啰嗦了,根据我狭隘的个人经验,甚至认为比 Go, Python 更简洁。

Monostich (单行诗)

以前我喜欢用 Go 来做一些自用的小软件,做一个本地网站通过访问网页来使用, 最近想做一个叫 monostich 的小工具,就尝试用 Java 来做。

主要功能

monostich 的功能非常简单。

与 Go 语言代码对比

这次我用 Javalin 来做本地网站,并且采用了以前我写 Go 时的代码组织方式, 因此两种语言可以做个对比。

程序入口: main.go 与 Main.java 对比

可见, Go 与 Java 的代码几乎一模一样:

// github.com/ahui2016/dictplus/blob/main/main.go

func main() {
	e := echo.New()
	e.Static("/public", "public")
	e.File("/", "public/index.html")

	api := e.Group("/api", sleep)
	api.POST("/get-word", getWordHandler)
	api.POST("/add-word", addWordHandler)
	api.POST("/update-word", updateWordHandler)
	api.POST("/delete-word", deleteWordHandler)
	api.POST("/search-words", searchHandler)

	e.Logger.Fatal(e.Start(*addr))
}
// github.com/ahui2016/monostich/.../App.java

public class App {
    public static void main(String[] args) {
        Javalin app = Javalin.create(config ->
            config.addStaticFiles(staticFiles -> {
                staticFiles.hostedPath = "/";
                staticFiles.directory = "/public";
                staticFiles.location = Location.CLASSPATH;
            })).start(port);
    
        app.post("/api/insert-poem", Handle.insertPoem);
        app.post("/api/update-poem", Handle.updatePoem);
        app.post("/api/delete-poem", Handle.deletePoem);
        app.post("/api/get-poem", Handle.getPoem);
        app.post("/api/search-poems", Handle.searchPoems);
    }
}

Handler

可见, Go 比 Java 多了一些 if err != nil, 其余代码几乎一模一样:

// github.com/ahui2016/dictplus/blob/main/handler.go

func addWordHandler(c echo.Context) error {
	w := new(Word)
	if err := c.Bind(w); err != nil {
		return err
	}
	if err := db.InsertNewWord(w); err != nil {
		return err
	}
	return c.JSON(OK, Text{w.ID})
}
// github.com/ahui2016/monostich/.../Handle.java

static Handler insertPoem = ctx -> {
    var form = ctx.bodyAsClass(PoemForm.class);
    var poem = db.insertPoem(form);
    ctx.json(poem);
};

数据库

在上面 Handler 的代码中, db.InsertNewWord() 与 db.insertPoem() 的具体实现如下所示。

可以看到, Go 的代码还是受到了 if err != nil 的困扰,显得很啰嗦, 而 Java 采用 Stream API 的好处是非常明显的,代码简洁了很多。

// github.com/ahui2016/dictplus/.../database.go

func (db *DB) InsertNewWord(w *Word) (err error) {
	tx := db.mustBegin()
	defer tx.Rollback()

	if w.ID, err = getNextID(tx, word_id_key); err != nil {
		return
	}
	w.CTime = util.TimeNow()
	if err = insertWord(tx, w); err != nil {
		return
	}
	err = tx.Commit()
	return
}
// github.com/ahui2016/monostich/.../DB.java

Poem insertPoem(PoemForm form) {
    return jdbi.withHandle(handle -> handle.inTransaction(h -> {
        var poem = new Poem(getNextId(h), form.title(), form.stich(), Util.now());
        h.createUpdate(Stmt.INSERT_POEM)
                .bindMap(poem.toMap())
                .execute();
        return poem;
    }));
}

相关链接

本软件后端采用 Javalin, 前端采用 mj.js, 相关介绍请看以下链接。

4190 次点击
所在节点    Java
31 条回复
makelove
2022-08-31 21:03:31 +08:00
java 还是不太行,很多年没写过 java 了,当年觉得 java 实在算不上好用,比如没有关键字参数,不知道现在有没有了
wdhwg001
2022-09-01 06:34:27 +08:00
@qW7bo2FbzbC0 我私底下觉得这纯属微软管太宽了,啥都是第一方的,所以社区没有造轮子的热情。

这个策略本身就不对,正确的是把基础的打好,然后 fund 一些好的第三方框架,出钱出力去帮忙补测试覆盖,提升性能和出钱 audit 代码。
CodeCodeStudy
2022-09-01 09:10:55 +08:00
java17 支持多行字符串了吗
chrawsl
2022-09-01 09:25:49 +08:00
@wdhwg001 但是第一方轮子确实好用(
qinxi
2022-09-01 09:58:40 +08:00
fenglangjuxu
2022-09-01 10:36:38 +08:00
看了下 好牛逼 和 spring boot 完全两个样子
和 go 挺像的
fgwmlhdkkkw
2022-09-01 10:39:03 +08:00
那你有什么理由拒绝 kotlin 呢?还有 async 用。
CodeCodeStudy
2022-09-01 10:41:17 +08:00
@qinxi #25 感谢! 20 年才搞这个,晚了点吧,早就该推出来了
promisenev
2022-09-01 14:32:35 +08:00
scala YYDS
wetalk
2022-09-01 15:17:12 +08:00
Kotlin ,Scala ,Groovy 任君挑选
SuperMild
2022-09-01 21:06:49 +08:00
@fenglangjuxu 是呀,我从 Go 转过来感觉很舒服。但如果正经项目还是用 spring boot 比较好,业余小项目用 Javalin 很方便。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/876788

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX