Based on Java8 + Netty4 to create a lightweight, high-performance, simple and elegant Web framework 😋
Spend 1 hour to learn it to do something interesting, a tool in addition to the other available frameworks.
🐾 Quick Start | 🎬 Video Tutorial | 🌚 Documentation | 📗 Guidebook | 💰 Donate | 🇨🇳 简体中文
Blade is a pursuit of simple, efficient Web framework, so that JavaWeb development becomes even more powerful, both in performance and flexibility. If you like to try something interesting, I believe you will love it. If you think it's good, you can support it with a star or by donating 😊
- A new generation MVC framework that doesn't depend on other libraries
- Get rid of SSH's bloated, modular design
- Source is less than
500kb, learning it is also simple - RESTful-style routing design
- Template engine support, view development more flexible
- High performance, 100 concurrent qps 20w/s
- Run the
JARpackage to open the web service - Streams-style API
CSRFandXSSdefenseBasic AuthandAuthorization- Supports plug-in extensions
- Support webjars resources
- Tasks based on
cronexpressions - Built-in a variety of commonly used middleware
- Built-in JSON output
- JDK8 +
» Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day.
» Elegance: blade supports the RESTful style routing interface, has no invasive interceptors and provides the writing of a DSL grammar.
» Easy deploy: supports maven package jar file running.
Create a basic Maven or Gradle project.
Do not create a
webappproject, Blade does not require much trouble.
Run with Maven:
<dependency> <groupId>com.bladejava</groupId> <artifactId>blade-mvc</artifactId> <version>2.0.15.RELEASE</version> </dependency>or Gradle:
compile 'com.bladejava:blade-mvc:2.0.15.RELEASE'Write the main method and the Hello World:
publicstaticvoidmain(String[] args){Blade.of().get("/", ctx -> ctx.text("Hello Blade")).start()}Open http://localhost:9000 in your browser to see your first Blade application!
Register RouteGet Request ParametersGet EnvironmentGet HeaderGet CookieStatic ResourceUpload FileSet SessionRender To BrowserRender TemplateRedirectsWrite CookieWeb HookLoggingBasic AuthChange Server PortConfiguration SSLCustom Exception Handler
publicstaticvoidmain(String[] args){// Create Blade,using GET、POST、PUT、DELETEBlade.of() .get("/user/21", getting) .post("/save", posting) .delete("/remove", deleting) .put("/putValue", putting) .start()}@PathpublicclassIndexController{@GetRoute("signin") publicStringsignin(){return"signin.html"} @PostRoute("signin") @JSONpublicRestResponsedoSignin(RouteContextctx){// do somethingreturnRestResponse.ok()} }Here is an example:
By Context
publicstaticvoidmain(String[] args){Blade.of().get("/user", ctx ->{Integerage = ctx.fromInt("age"); System.out.println("age is:" + age)}).start()}By Annotation
@PostRoute("/save") publicvoidsavePerson(@ParamStringusername, @ParamIntegerage){System.out.println("username is:" + username + ", age is:" + age) }Test it with sample data from the terminal
curl -X GET http://127.0.0.1:9000/user?age=25curl -X POST http://127.0.0.1:9000/save -F username=jack -F age=16By RouteContext
publicstaticvoidmain(String[] args){Bladeblade = Blade.of(); // Create a route: /user/:uidblade.get("/user/:uid", ctx ->{Integeruid = ctx.pathInt("uid"); ctx.text("uid : " + uid)}); // Create two parameters routeblade.get("/users/:uid/post/:pid", ctx ->{Integeruid = ctx.pathInt("uid"); Integerpid = ctx.pathInt("pid"); Stringmsg = "uid = " + uid + ", pid = " + pid; ctx.text(msg)}); // Start bladeblade.start()}By Annotation
@GetRoute("/users/:username/:page") publicvoiduserTopics(@PathParamStringusername, @PathParamIntegerpage){System.out.println("username is:" + usernam + ", page is:" + page) }Test it with sample data from the terminal
curl -X GET http://127.0.0.1:9000/users/biezhi/2publicstaticvoidmain(String[] args){Blade.of().post("/body", ctx ->{System.out.println("body string is:" + ctx.bodyToString()) }).start()}Test it with sample data from the terminal
curl -X POST http://127.0.0.1:9000/body -d '{"username":"biezhi","age":22}'This is the User model.
publicclassUser{privateStringusername; privateIntegerage; // getter and setter }By Annotation
@PostRoute("/users") publicvoidsaveUser(@ParamUseruser){System.out.println("user => " + user)}Test it with sample data from the terminal
curl -X POST http://127.0.0.1:9000/users -F username=jack -F age=16Custom model identification
@PostRoute("/users") publicvoidsaveUser(@Param(name="u") Useruser){System.out.println("user => " + user)}Test it with sample data from the terminal
curl -X POST http://127.0.0.1:9000/users -F u[username]=jack -F u[age]=16Body Parameter To Model
publicvoidgetUser(@BodyParamUseruser){System.out.println("user => " + user)}Test it with sample data from the terminal
curl -X POST http://127.0.0.1:9000/body -d '{"username":"biezhi","age":22}'Environmentenvironment = WebContext.blade().environment(); Stringversion = environment.get("app.version", "0.0.1");By Context
@GetRoute("header") publicvoidgetHeader(RouteContextctx){System.out.println("Host => " + ctx.header("Host")); // get useragentSystem.out.println("UserAgent => " + ctx.userAgent()); // get client ipSystem.out.println("Client Address => " + ctx.address())}By Annotation
@GetRoute("header") publicvoidgetHeader(@HeaderParamStringHost){System.out.println("Host => " + Host)}By Context
@GetRoute("cookie") publicvoidgetCookie(RouteContextctx){System.out.println("UID => " + ctx.cookie("UID"))}By Annotation
@GetRoute("cookie") publicvoidgetCookie(@CookieParamStringUID){System.out.println("Cookie UID => " + UID)}Blade builds a few static resource catalog, as long as you will save the resource file in the static directory under the classpath, and then browse http://127.0.0.1:9000/static/style.css
If you want to customize the static resource URL
Blade.of().addStatics("/mydir");Of course you can also specify it in the configuration file. application.properties (location in classpath)
mvc.statics=/mydirBy Request
@PostRoute("upload") publicvoidupload(Requestrequest){request.fileItem("img").ifPresent(fileItem ->{fileItem.moveTo(newFile(fileItem.getFileName()))})}By Annotation
@PostRoute("upload") publicvoidupload(@MultipartParamFileItemfileItem){// Save to new pathfileItem.moveTo(newFile(fileItem.getFileName()))}publicvoidlogin(Sessionsession){// if login successsession.attribute("login_key", SOME_MODEL)}By Context
@GetRoute("users/json") publicvoidprintJSON(RouteContextctx){Useruser = newUser("biezhi", 18); ctx.json(user)}By Annotation
This form looks more concise 😶
@GetRoute("users/json") @JSONpublicUserprintJSON(){returnnewUser("biezhi", 18)}@GetRoute("text") publicvoidprintText(RouteContextctx){ctx.text("I Love Blade!")}@GetRoute("html") publicvoidprintHtml(RouteContextctx){ctx.html("<center><h1>I Love Blade!</h1></center>")}By default all template files are in the templates directory; in most of the cases you do not need to change it.
By default, Blade uses the built-in template engine, which is very simple. In a real-world web project, you can try several other extensions.
publicstaticvoidmain(String[] args){Blade.of().get("/hello", ctx ->{ctx.attribute("name", "biezhi"); ctx.render("hello.html")}).start(Hello.class, args)}The hello.html template
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>Hello Page</title></head><body><h1>Hello, ${name}</h1></body></html>Config Jetbrick Template
Create a BladeLoader class and load some config
@BeanpublicclassTemplateConfigimplementsBladeLoader{@Overridepublicvoidload(Bladeblade){blade.templateEngine(newJetbrickTemplateEngine())} }Write some data for the template engine to render
publicstaticvoidmain(String[] args){Blade.of().get("/hello", ctx ->{Useruser = newUser("biezhi", 50); ctx.attribute("user", user); ctx.render("hello.html")}).start(Hello.class, args)}The hello.html template
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>Hello Page</title></head><body><h1>Hello, ${user.username}</h1> #if(user.age > 18) <p>Good Boy!</p> #else <p>Gooood Baby!</p> #end </body></html>@GetRoute("redirect") publicvoidredirectToGithub(RouteContextctx){ctx.redirect("https://github.com/biezhi")}@GetRoute("write-cookie") publicvoidwriteCookie(RouteContextctx){ctx.cookie("hello", "world"); ctx.cookie("UID", "22", 3600)}WebHook is the interface in the Blade framework that can be intercepted before and after the execution of the route.
publicstaticvoidmain(String[] args){// All requests are exported before execution beforeBlade.of().before("/*", ctx ->{System.out.println("before...")}).start()}Blade uses slf4j-api as logging interface, the default implementation of a simple log package (modified from simple-logger); if you need complex logging you can also use a custom library, you only need to exclude the blade-log from the dependencies.
privatestaticfinalLoggerlog = LoggerFactory.getLogger(Hello.class); publicstaticvoidmain(String[] args){log.info("Hello Info,{}", "2017"); log.warn("Hello Warn"); log.debug("Hello Debug"); log.error("Hello Error")}Blade includes a few middleware, like Basic Authentication; of course, it can also be customized to achieve more complex goals.
publicstaticvoidmain(String[] args){Blade.of().use(newBasicAuthMiddleware()).start()}Specify the user name and password in the application.properties configuration file.
http.auth.username=admin http.auth.password=123456There are three ways to modify the port: hard coding it, in a configuration file, and through a command line parameter.
Hard Coding
Blade.of().listen(9001).start();Configuration For application.properties
server.port=9001Command Line
java -jar blade-app.jar --server.port=9001Configuration For application.properties
server.ssl.enable=true server.ssl.cert-path=cert.pem server.ssl.private-key-path=private_key.pem server.ssl.private-key-pass=123456Blade has an exception handler already implemented by default; if you need to deal with custom exceptions, you can do it like follows.
@BeanpublicclassGlobalExceptionHandlerextendsDefaultExceptionHandler{@Overridepublicvoidhandle(Exceptione){if (einstanceofCustomException){CustomExceptioncustomException = (CustomException) e; Stringcode = customException.getCode(); // do something } else{super.handle(e)} } }Besides looking easy, the features above are only the tip of the iceberg, and there are more surprises to see in the documentation and sample projects:
- Twitter: biezhi
- Mail: [email protected]
- Telegram Group
Thanks goes to these wonderful people
Contributions of any kind are welcome!
Please see Apache License
