{"id":25569330,"url":"https://github.com/rife2/rife2","last_synced_at":"2026-01-12T08:40:24.407Z","repository":{"id":62414282,"uuid":"559706011","full_name":"rife2/rife2","owner":"rife2","description":"Full-stack, no-declaration, framework to quickly and effortlessly create web applications with modern Java.","archived":false,"fork":false,"pushed_at":"2025-11-18T03:29:57.000Z","size":6439,"stargazers_count":243,"open_issues_count":4,"forks_count":17,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-11-18T05:29:15.074Z","etag":null,"topics":["continuations","framework","java","rife","rife2","template-engine","web","web-framework"],"latest_commit_sha":null,"homepage":"https://rife2.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rife2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-30T22:58:43.000Z","updated_at":"2025-11-18T03:30:02.000Z","dependencies_parsed_at":"2023-10-20T16:33:48.418Z","dependency_job_id":"5880e672-0838-48aa-96dc-4bc084a60ffb","html_url":"https://github.com/rife2/rife2","commit_stats":null,"previous_names":["gbevin/rife2"],"tags_count":69,"template":false,"template_full_name":null,"purl":"pkg:github/rife2/rife2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rife2%2Frife2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rife2%2Frife2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rife2%2Frife2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rife2%2Frife2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rife2","download_url":"https://codeload.github.com/rife2/rife2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rife2%2Frife2/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28337599,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuations","framework","java","rife","rife2","template-engine","web","web-framework"],"created_at":"2025-02-21T00:02:17.609Z","updated_at":"2026-01-12T08:40:24.396Z","avatar_url":"https://github.com/rife2.png","language":"Java","readme":"[![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Java](https://img.shields.io/badge/java-17%2B-blue)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)\n[![bld](https://img.shields.io/badge/2.3.0-FA9052?label=bld\u0026labelColor=2392FF)](https://rife2.com/bld)\n[![Release](https://img.shields.io/github/release/rife2/rife2.svg)](https://github.com/rife2/rife2/releases/latest)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.uwyn.rife2/rife2/badge.svg?color=blue)](https://maven-badges.herokuapp.com/maven-central/com.uwyn.rife2/rife2)\n[![GitHub Snapshot](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Fcom%2Fuwyn%2Frife2%2Frife2%2Fmaven-metadata.xml)](https://github.com/rife2/rife2/packages/2214743/versions)\n[![bld-ci](https://github.com/rife2/rife2/actions/workflows/bld.yml/badge.svg)](https://github.com/rife2/rife2/actions/workflows/bld.yml)\n[![Tests](https://rife2.com/tests-badge/badge/com.uwyn.rife2/rife2)](https://github.com/rife2/rife2/actions/workflows/bld.yml)\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/rife2/rife2/raw/main/images/rife2_logo.png\" width=\"200\"\u003e\u003c/p\u003e\n\n# Welcome\n\nRIFE2 is a full-stack, no-declaration, framework to quickly and effortlessly\ncreate web applications with modern Java.\n\nRIFE2 is built on the foundations of the original RIFE framework that was\npopular from 2002-2010. Since then, the world and Java have changed and many of\nthe original RIFE APIs could finally be replaced with pure Java, no-XML,\nno-YAML, leaving only type-safe expressive code.\n\nRIFE2 preserves most of the original features and adds new ones, for a fraction\nof the footprint and with even greater developer productivity than before.\nRIFE2 is created by Geert Bevin, one of the first Java Champions and speaker at\nmany Java conferences.\n\n\u003e **TIP:** If you use IntelliJ IDEA as your IDE, consider installing the\n\u003e [RIFE2 IDEA Plug-in](https://github.com/rife2/rife2-idea).  \n\u003e It will greatly enhance your coding experience.\n\n**This is a quick tutorial, the [full documentation](https://github.com/rife2/rife2/wiki)\ncontains a lot more information.**\n\n**The [RIFE2 Javadocs](https://rife2.github.io/rife2/) complement the\ndocumentation with many more details.**\n\n\u003ca href=\"https://www.youtube.com/watch?feature=player_embedded\u0026v=AZWzYwAHDIE\" target=\"_blank\"\u003e\n \u003cimg src=\"https://img.youtube.com/vi/AZWzYwAHDIE/maxresdefault.jpg\" alt=\"Watch the video\" width=\"640\" height=\"360\" border=\"0\" /\u003e\n\u003c/a\u003e\n\n## Why RIFE2?\n\nA frequently asked question is: \"Why choose RIFE2 over other popular frameworks\"?\n\nThe short answer is that *RIFE2 is different*, it's designed to create web\napplications quickly with small teams. It has challenged and will always\nchallenge the status-quo. It's not meant to replace enterprise-level frameworks\nlike Spring or JEE, though I've used it for enterprise applications. RIFE2\nleverages the power of the Java platform for web applications that you'd usually\nwrite with scripting languages. Productivity and maintainability is key, and\nyou'll find that you get 90% of the work done for 10% of the effort, and can\nstill integrate with other Java libraries and frameworks where you need it.\n\nRIFE2 has features that after 20 years still can't be found elsewhere:  \nweb continuations, bidirectional template engine, bean-centric metadata system,\nfull-stack without dependencies, metadata-driven SQL builders, content\nmanagement framework, full localization support, resource abstraction, persisted\ncron-like scheduler, continuations-based workflow engine.\n\nMost of these features have stood the test of time and after 20 years still\nprove to be great choices for web application development. RIFE2 has learned\nfrom decades of experience and improves on these original features in many ways.\n\nRIFE2 also has features that have been adopted by others, but that usually lack\nthe convenience of the tight integration throughout a full-stack.\n\nFor instance: out-of-container tests can analyze the structure of the resulting\ntemplates without having to parse HTML, the authentication system is built from\nall the other pieces of the full-stack and seamlessly integrates into your web\napplication, URLs are generated from the configuration you created without the\nrisk of becoming stale, the logic-less templates are really purely content\ndriven and can generate any text-based format (JSON, XML, HTML, SVG, SQL), ...\nand much more.\n\n*RIFE2 is the red pill*, ready to show you how deep the rabbit hole can go, if\nyou're up for it!\n\n# Quickstart\n\n## Hello World Example\n\nThis is how you get started with a `Hello World` site.\n\n```java\npublic class HelloWorld extends Site {\n    public void setup() {\n        get(\"/hello\", c -\u003e c.print(\"Hello World\"));\n    }\n\n    public static void main(String[] args) {\n        new Server().start(new HelloWorld());\n    }\n}\n```\n\nThe `main` method spins up the integrated embedded Jetty server, so that you can\nimmediately start coding. The same `HelloWorld` class can be added as a\nparameter value to your `web.xml`, requiring absolute no changes to your code\nbetween development and production.\n\nOut-of-container testing is a first-class citizen in RIFE2, directly interacting\nwith your `Site` class to simulate full request-response interactions,\nwithout having to spin up a servlet container.\n\nThis is how you could test the example above with JUnit 5:\n\n```java\nclass HelloTest {\n    @Test void verifyHelloWorld() {\n        var m = new MockConversation(new HelloWorld());\n        assertEquals(\"Hello World\", m.doRequest(\"/hello\").getText());\n    }\n}\n```\n\n## Type-safe Links and URLs\n\nOne of the most brittle aspects of web application development is typing links\nand URLs as text literals, without anything guaranteeing they remain correct\nwhen your routes change or when you deploy your application in different web\napplication contexts. RIFE2's routing API allows all your application links to\nbe generated correctly without any effort on your behalf.\n\nLet's add a new route that contains an HTML link towards the previous Hello\nWorld route.\n\nYou can see that routes don't have to be created inside the `setup()` method,\nbut can also be created as part of your `Site`'s construction, allowing the\nroutes to be stored in fields.\n\n```java\npublic class HelloLink extends Site {\n    Route hello = get(\"/hello\", c -\u003e c.print(\"Hello World\"));\n    Route link = get(\"/link\", c-\u003e c.print(\"\u003ca href='\" + c.urlFor(hello) + \"'\u003eHello\u003c/a\u003e\"));\n\n    public static void main(String[] args) {\n        new Server().start(new HelloLink());\n    }\n}\n```\n\nWe can now test this as such:\n\n```java\nclass HelloTest {\n    @Test void verifyHelloLink() {\n        var m = new MockConversation(new HelloLink());\n        assertEquals(\"Hello World\", m.doRequest(\"/link\")\n            .getParsedHtml().getLinkWithText(\"Hello\")\n            .follow().getText());\n    }\n}\n```\n\n## Bidirectional Logic-Less Templates\n\nThe main impetus that had me create RIFE2, was RIFE's unique template engine.\n\nRIFE2's templates contain two main concepts:\n* *values* - that can be filled in with content and data\n* *blocks* - that will be stripped away and that provide content snippets\n\nYour Java code will compose the final layout by assigning and appending blocks,\nand by putting data into values. Let's rewrite the `HelloLink` example above with a template.\n\nIn this example, no template manipulation is done in Java yet.\n\nInstead, it introduces the `{{v route:hello/}}` value tag, which will\nautomatically be replaced with the URL of the route that is available with that\nfield name in your active `Site`.\n\n```java\npublic class HelloTemplate extends Site {\n    Route hello = get(\"/hello\", c -\u003e c.print(\"Hello World\"));\n    Route link = get(\"/link\", c-\u003e c.print(c.template(\"HelloTemplate\")));\n\n    public static void main(String[] args) {\n        new Server().start(new HelloTemplate());\n    }\n}\n```\nWith `HelloTemplate.html` being:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003cbody\u003e\n\u003ca href=\"{{v route:hello/}}\"\u003eHello\u003c/a\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nNote that RIFE2 internally transforms your templates into Java classes by\ngenerating optimized bytecode.\n\nThis happens on-the-fly during development. For production, templates can be\npre-compiled, making them incredibly fast. \n\n## Template Manipulation\n\nLet's change the example some more and create a single route that can respond to\nboth `get` and `post` requests.\n\n* the `get` request will display a form with a single button to click.\n* the `post` request will receive the form's submission and display `Hello World`.\n\n```java\npublic class HelloForm extends Site {\n    Route hello = route(\"/hello\", c -\u003e {\n        var t = c.template(\"HelloForm\");\n        switch (c.method()) {\n            case GET -\u003e t.setBlock(\"content\", \"form\");\n            case POST -\u003e t.setBlock(\"content\", \"text\");\n        }\n        c.print(t);\n    });\n\n    public static void main(String[] args) {\n        new Server().start(new HelloForm());\n    }\n}\n```\n\nWith `HelloForm.html` being:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003cbody\u003e\n\u003c!--v content/--\u003e\n\u003c!--b form--\u003e\n\u003cform action=\"{{v route:action:hello/}}\" method=\"post\" name=\"hello\"\u003e\n  \u003c!--v route:inputs:hello/--\u003e\n  \u003cinput type=\"submit\" name=\"Submit\"\u003e\n\u003c/form\u003e\n\u003c!--/b--\u003e\n\u003c!--b text--\u003e\u003cp id=\"greeting\"\u003eHello World\u003c/p\u003e\u003c!--/b--\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003e **NOTE:** that the `route:` value tag from the above has been split into\n\u003e `route:action:` and `route:inputs:`, generating hidden HTML form inputs for\n\u003e parameters instead of query string parameters.\n\nYou can see that the template contains all the pieces to create both pages:\n\n* the value named `content`\n* the block named `form`\n* the block named `text`\n\nIn Java, we simply assign either block to the value, depending on what we want\nto display.\n\nAnother benefit is that RIFE2's template tags can be HTML comments, making them\ncompletely invisible. This allows you to work on your HTML design as usual and\npreview the template file with a regular browser.\n\nFinally, let's include a test for this functionality:\n\n```java\nclass HelloTest {\n    @Test void verifyHelloForm() {\n        var m = new MockConversation(new HelloForm());\n        var r = m.doRequest(\"/hello\").getParsedHtml()\n            .getFormWithName(\"hello\").submit();\n        assertEquals(\"Hello World\", r.getParsedHtml()\n            .getDocument().body()\n            .getElementById(\"greeting\").text());\n    }\n}\n```\n\n## Just the top of the rabbit hole\n\nThanks for reading until the end!\n\nThis was merely a quick introduction to whet your appetite, RIFE2 comes with a\ncomprehensive and easy to read manual with many examples and pragmatic\nexplanations.\n\nIf you have any questions, suggestions, ideas or just want to chat, feel free\nto post on the [forums](https://forum.uwyn.com) or to join\nus on [Discord](https://discord.gg/DZRYPtkb6J).\n\n**Read more in the [full documentation](https://github.com/rife2/rife2/wiki)\nand [RIFE2 Javadocs](https://rife2.github.io/rife2/).**\n","funding_links":[],"categories":["开发框架"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frife2%2Frife2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frife2%2Frife2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frife2%2Frife2/lists"}