/blade

:rocket: Lightning fast and elegant mvc framework for Java8

Primary LanguageJavaApache License 2.0Apache-2.0

Based on Java8 + Netty4 to create lightweight, high-performance, simple and elegant Web framework 😋

Spend 1 hour to learn it to do something interesting, a Spring in addition to the framework of the best choice.

🐾 Quick Start | 📘 Blade In Action | 🎬 Video Tutorial | 🌚 Contribution | 💰 Donate | 🇨🇳 简体中文


What Is Blade?

Blade is a pursuit of simple, efficient Web framework, so that JavaWeb development even more powerful, both in performance and flexibility. If you like to try something interesting, I believe you will love it. If you think this item is good can star support or donate it 😊

Features

  • A new generation of MVC frameworks that do not depend on more libraries
  • Get rid of SSH's bloated, modular design
  • Source less than 500kb, learning is also simple
  • Restful style routing design
  • Template engine support, view development more flexible
  • High performance, 100 concurrent qps 14w/s
  • Run the JAR package to open the web service
  • Streaming API style
  • Supports plug-in extensions
  • Support webjars resources
  • Based on cron expression of tasks
  • Built-in a variety of commonly used middleware
  • Built-in JSON output
  • JDK8 +

Overview

» 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 DSL grammar.
» Easy deploy: support maven package jar file running.

Quick Start

Run with Maven

Create a basic Maven project

<dependency>
    <groupId>com.bladejava</groupId>
    <artifactId>blade-mvc</artifactId>
    <version>2.0.8-BETA1</version>
</dependency>

Do not create a webapp project, blade is not so much trouble.

or Gradle:

compile 'com.bladejava:blade-mvc:2.0.8-BETA1'

Write main method, try Hello World

public static void main(String[] args) {
    Blade.me().get("/", (req, res) -> {
        res.text("Hello Blade");
    }).start();
}

Using browser open http://localhost:9000 so you can see the first Blade application!

Contents

Register Route

HardCode

public static void main(String[] args) {
    // Create Blade,using GET、POST、PUT、DELETE
    Blade.me()
        .get("/user/21", getting)
        .post("/save", posting)
        .delete("/remove", deleting)
        .put("/putValue", putting)
        .start();
}

Controller

@Path
public class IndexController {

    @GetRoute("signin")
    public String signin(){
        return "signin.html";
    }

    @PostRoute("signin")
    @JSON
    public RestResponse doSignin(Request request){
        // do something
        return RestResponse.ok();
    }

}

Get Request Parameters

Form Parameters

Here is an example:

By Request

public static void main(String[] args) {
    Blade.me().get("/user", ((request, response) -> {
         Optional<Integer> ageOptional = request.queryInt("age");
         ageOptional.ifPresent(age -> System.out.println("age is:" + age));
     })).start();
}

By Annotation

@PostRoute("/save")
public void savePerson(@Param String username, @Param Integer age){
  System.out.println("username is:" + username + ", age is:" + age)
}

The terminal sends a data test

curl -X GET http://127.0.0.1:9000/user?age=25
curl -X POST http://127.0.0.1:9000/save -F username=jack -F age=16

Path Parameters

By Request

public static void main(String[] args) {
    Blade blade = Blade.me();
    // Create a route: /user/:uid
    blade.get("/user/:uid", (request, response) -> {
		Integer uid = request.pathInt("uid");
		response.text("uid : " + uid);
	});

    // Create two parameters route
    blade.get("/users/:uid/post/:pid", (request, response) -> {
		Integer uid = request.pathInt("uid");
		Integer pid = request.pathInt("pid");
		String msg = "uid = " + uid + ", pid = " + pid;
		response.text(msg);
	});

    // Start blade
    blade.start();
}

By Annotation

@GetRoute("/users/:username/:page")
public void userTopics(@PathParam String username, @PathParam Integer page){
  System.out.println("username is:" + usernam + ", page is:" + page)
}

The terminal sends a data test

curl -X GET http://127.0.0.1:9000/users/biezhi/2

Body Parameters

public static void main(String[] args) {
    Blade.me().post("/body", ((request, response) -> {
      System.out.println("body string is:" + request.bodyToString())
    }).start();
}

The terminal sends a data test

curl -X POST http://127.0.0.1:9000/body -d '{"username":"biezhi","age":22}'

Parse To Model

This is User model.

public class User {
  private String username;
  private Integer age;
  // getter and setter
}

By Annotation

@PostRoute("/users")
public void saveUser(@Param User user){
    System.out.println("user => " + user);
}

The terminal sends a data test

curl -X POST http://127.0.0.1:9000/users -F username=jack -F age=16

Custom model identification

@PostRoute("/users")
public void saveUser(@Param(name="u") User user){
    System.out.println("user => " + user);
}

The terminal sends a data test

curl -X POST http://127.0.0.1:9000/users -F u[username]=jack -F u[age]=16

Body Parameter To Model

public void getUser(@BodyParam User user){
    System.out.println("user => " + user);
}

The terminal sends a data test

curl -X POST http://127.0.0.1:9000/body -d '{"username":"biezhi","age":22}'

Get Environment

Environment environment = WebContext.blade().environment();
String version = environment.get("app.version", "0.0.1");;

Get Header

By Request

@GetRoute("header")
public void getHeader(Request request){
  System.out.println("Host => " + request.header("Host"));
  // get useragent
  System.out.println("UserAgent => " + request.userAgent());
  // get client ip
  System.out.println("Client Address => " + request.address());
}

By Annotation

@GetRoute("header")
public void getHeader(@HeaderParam String Host){
  System.out.println("Host => " + Host);
}

Get Cookie

By Request

@GetRoute("cookie")
public void getCookie(Request request){
  System.out.println("UID => " + request.cookie("UID").get());
  request.cookie("UID").ifPresent(System.out::println);
}

By Annotation

@GetRoute("cookie")
public void getCookie(@CookieParam String UID){
  System.out.println("Cookie UID => " + UID);
}

Static Resource

Blade built 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.me().addStatics("/mydir");

Of course you can also specify in the configuration file. app.properties (location in classpath)

mvc.statics=/mydir

Upload File

By Request

@PostRoute("upload")
public void upload(Request request){
    request.fileItem("img").ifPresent(fileItem -> {
        byte[] data = fileItem.getData();
        // Save the temporary file to the specified path
        Files.write(Paths.get(filePath), data);
    });
}

By Annotation

@PostRoute("upload")
public void upload(@MultipartParam FileItem fileItem){
    byte[] data = fileItem.getData();
    // Save the temporary file to the specified path
    Files.write(Paths.get(filePath), data);
}

Set Session

public void login(Session session){
  // if login success
  session.attribute("login_key", SOME_MODEL);
}

Render To Browser

Render JSON

By Response

@GetRoute("users/json")
public void printJSON(Response response){
  User user = new User("biezhi", 18);
  response.json(user);
}

By Annotation

This form looks more concise 😶

@GetRoute("users/json")
@JSON
public User printJSON(){
  return new User("biezhi", 18);
}

Render Text

@GetRoute("text")
public void printText(Response response){
  response.text("I Love Blade!");
}

Render Html

@GetRoute("html")
public void printHtml(Response response){
  response.html("<center><h1>I Love Blade!</h1></center>");
}

Render Template

By default all template files are in the templates directory, most of the cases you do not need to change it.

Default Template

By default, the Blade uses the built-in template engine, which is very simple if you really do a web project can try several other extensions.

public static void main(String[] args) {
    Blade.me().get("/hello", ((request, response) -> {
                request.attribute("name", "biezhi");
                response.render("hello.html");
            }))
            .start(Hello.class, args);
}

The hello.html template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello Page</title>
</head>
<body>

  <h1>Hello, ${name}</h1>

</body>
</html>

Jetbrick Template

Config Jetbrick Template

Create a BeanProcessor class

@Bean
public class TemplateConfig implements BeanProcessor {

    @Override
    public void processor(Blade blade) {
        blade.templateEngine(new JetbrickTemplateEngine());
    }

}

Write some data for the template engine to render

public static void main(String[] args) {
    Blade.me().get("/hello", ((request, response) -> {
                User user = new User("biezhi", 50);
                request.attribute("user", user);
                response.render("hello.html");
            }))
            .start(Hello.class, args);
}

The hello.html template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="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>

Render API

Redirects

@GetRoute("redirect")
public void redirectToGithub(Response response){

  response.redirect("https://github.com/biezhi");

}

Redirect API

Write Cookie

@GetRoute("write-cookie")
public void writeCookie(Response response){

  response.cookie("hello", "world");
  response.cookie("UID", "22", 3600);

}

Cookie API

Web Hook

WebHook is the interface in the Blade framework that can be intercepted before and after the execution of the route.

public static void main(String[] args) {
    // All requests are exported before execution before
    Blade.me().before("/*", (request, response) -> {
        System.out.println("before...");
    }).start();
}

Logging

Blade using slf4-api as a log interface, the default implementation of a simple log package (modified from simple-logger), if you need complex logging you can also use custom, you only need to exclude the blade-log in dependencies.

private static final Logger log = LoggerFactory.getLogger(Hello.class);

public static void main(String[] args) {
  log.info("Hello Info, {}", "2017");
  log.warn("Hello Warn");
  log.debug("Hello Debug");
  log.error("Hello Error");
}

Basic Auth

Blade built a few middleware, when you need Basic certification can be used, of course, can also be customized to achieve.

public static void main(String[] args) {
  Blade.me().use(new BasicAuthMiddleware()).start();
}

Specify the user name and password in the app.properties configuration file.

http.auth.username=admin
http.auth.password=123456

Change Server Port

There are three ways to modify the port, hard coding, configuration files, start the command line parameters.

Hard Coding

Blade.me().listen(9001).start();

Configuration For app.properties

server.port=9001

Command Line

java -jar blade-app.jar --server.port=9001

Configuration SSL

Configuration For app.properties

server.ssl.enable=true
server.ssl.cert-path=cert.pem
server.ssl.private-key-path=private_key.pem
server.ssl.private-key-pass=123456

Custom Exception Handler

Blade has already implemented an exception handler by default, and sometimes you need to deal with custom exceptions, so you can do it.

@Bean
public class GolbalExceptionHandler extends DefaultExceptionHandler {

    @Override
    public void handle(Exception e) {
        if (e instanceof ValidateException) {
            ValidateException validateException = (ValidateException) e;
            String msg = validateException.getErrMsg();
            WebContext.response().json(RestResponse.fail(msg));
        } else {
            super.handle(e);
        }
    }

}

How easy it all looks, but the features above are the tip of the iceberg, and there are more surprises to see in the documentation and sample projects:

Change Logs

See Here

Contact

Contributors

Thanks goes to these wonderful people


王爵nice

ccqy66

王晓辉(Eddie)

代码家

David Dong

José Vieira Neto

Schneeman

Mohd Farid

sumory

Uday K

Antony Kwok
     

Contributions of any kind are welcome!

Licenses

Please see Apache License