简洁优雅的全栈式 MVC 框架 blade

简洁优雅的全栈式 MVC 框架 blade

Apache
Java 查看源码»
跨平台
2015-07-07
王爵nice

基于 Java8 + Netty4 创造的轻量级、高性能、简洁优雅的Web框架

花 1小时 学会它做点有趣的项目,一款除了Spring系框架的不二之选。

 快速开始 |  BladeInAction |  视频教程 |  参与贡献 |  捐赠我们 |  English

     

Blade是什么?

Blade 是一款追求简约、高效的 Web 框架,让 JavaWeb 开发如虎添翼,在性能与灵活性上同时兼顾。 如果你喜欢尝试有趣的事物,相信你会爱上它。 如果觉得这个项目不错可以 star 支持或者 捐赠 它 😊

功能特性

  • [x] 新一代MVC框架,不依赖更多的库
  • [x] 摆脱SSH的臃肿,模块化设计
  • [x] 源码不到 500kb,学习也简单
  • [x] Restful风格路由设计
  • [x] 模板引擎支持,视图开发更灵活
  • [x] 高性能,100并发下qps 14w/s
  • [x] 运行 JAR 包即可开启 web 服务
  • [x] 支持 CSRF 和 XSS 防御
  • [x] 支持 BasicAuth 和权限管理
  • [x] 流式API风格
  • [x] 支持插件扩展
  • [x] 支持 webjars 资源
  • [x] cron 表达式的定时任务
  • [x] 内置多种常用中间件
  • [x] 内置JSON输出
  • [x] JDK8+

框架概述

» 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。
» 优雅的:Blade 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。
» 易部署:支持 maven 打成 jar 包直接运行。

快速入门

Maven 配置:

创建一个基础的 Maven 工程


 
  1. <dependency> 
  2.     <groupId>com.bladejava</groupId> 
  3.     <artifactId>blade-mvc</artifactId> 
  4.     <version>2.0.11.ALPHA</version> 
  5. </dependency>

不需要创建 webapp 项目骨架, Blade 没这么麻烦。

或者 Gradle:

compile 'com.bladejava:blade-mvc:2.0.11.ALPHA'

编写 main 函数写一个 Hello World

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

用浏览器打开 http://localhost:9000 这样就可以看到第一个 Blade 应用了!

Contents

注册路由

硬编码方式

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

控制器方式

@Path
public class IndexController {

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

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

}

获取请求参数

表单参数

下面是个例子:

使用 RouteContext 获取

public static void main(String[] args) {
    Blade.of().get("/user", ctx -> {
        Integer age = ctx.queryInt("age");
        System.out.println("age is:" + age);
    }).start();
}

使用注解获取

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

在终端下发送数据测试

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

Restful 参数

使用 RouteContext 获取

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

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

    // Start blade
    blade.start();
}

使用注解获取

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

在终端下发送数据测试

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

Body 参数

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

在终端下发送数据测试

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

参数转为对象

这是 User 类结构

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

使用注解获取

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

在终端下发送数据测试

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

自定义 model 名称

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

在终端下发送数据测试

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

Body 参数转对象

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

在终端下发送数据测试

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

获取环境配置

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

获取 Header

使用 RouteContext 获取

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

使用注解获取

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

获取 Cookie

使用 RouteContext 获取

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

使用注解获取

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

静态资源

Blade 内置了一些静态资源目录,只要将资源文件保存在 classpath 下的 static 目录中,然后浏览 http://127.0.0.1:9000/static/style.css

如果要自定义静态资源URL,可以使用下面的代码

Blade.of().addStatics("/mydir");

当然你也可以在配置文件中指定 application.properties (位于classpath之下)

mvc.statics=/mydir

上传文件

使用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);              
    });
}

使用注解获取

@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);
}

设置会话

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

渲染到浏览器

渲染JSON

使用 RouteContext 渲染

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

使用注解获取

这种形式看起来更简洁 

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

渲染文本

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

渲染Html

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

模板渲染

默认情况下,所有模板文件都 在templates 目录中,大多数情况下你不需要更改它。

默认模板

默认情况下,Blade使用内置的模板引擎,如果你真的做一个Web项目可以尝试其他几个扩展,这很简单。

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

hello.html 模板

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

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

</body>
</html>

Jetbrick模板

配置 Jetbrick 模板引擎

实现一个 BladeLoader 加载初始化的操作

@Bean
public class TemplateConfig implements BladeLoader {

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

}

写一点数据让模板渲染

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

hello.html 模板

<!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

重定向

@GetRoute("redirect")
public void redirectToGithub(RouteContext ctx){
    ctx.redirect("https://github.com/biezhi");
}

Redirect API

写入Cookie

@GetRoute("write-cookie")
public void writeCookie(RouteContext ctx){
    ctx.cookie("hello", "world");
    ctx.cookie("UID", "22", 3600);
}

Cookie API

路由拦截

WebHook 是Blade框架中可以在执行路由之前和之后拦截的接口。

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

日志输出

Blade 使用 slf4-api 作为日志接口,默认实现一个简单的日志(从simple-logger修改),如果你需要复杂的日志记录你也可以使用其他的日志框架,你只需要在依赖关系中排除 blade-log 然后添加你喜欢的。

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认证

Blade 内置了几个中间件,当你需要Basic认证时可以使用如下代码,当然也可以定制来实现。

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

在 application.properties 配置文件中指定用户名和密码。

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

修改服务端口

有三种方式修改端口,硬编码,配置文件,启动命令行参数。

硬编码

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

配置文件 application.properties

server.port=9001

命令行

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

配置SSL

配置文件 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=123456

自定义异常处理

默认情况下,Blade 已经实现了一个异常处理器,有时你需要处理自定义异常,因此你可以尝试像下面这样使用。

@Bean
public class GolbalExceptionHandler extends DefaultExceptionHandler {

    @Override
    public void handle(Exception e) {
        if (e instanceof CustomException) {
            CustomException customException = (CustomException) e;
            String code = customException.getCode();
            // do something
        } else {
            super.handle(e);
        }
    }

}

这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜:

联系我们

  • Twitter: biezhi
  • Mail: biezhi.me#gmail.com

开源协议

请查看 Apache License

的码云指数为
超过 的项目
加载中

评论(2)

小小胖
小小胖
#blade# 不错,搞了三个月今天上线,www.kooteam.com
异教邪徒
王老师,在github上学习您的wechart-api项目,但是运行扫描之后心跳检测一直是1102,还有就是WeChatApiImpl类有错误,望老师看一下吧,卡了好久了
红白机
红白机
#blade#不错,mark,留着学习!
MartinBockZhu
MartinBockZhu
mark #blade#

Blade 2.0.5 发布,高性能简洁优雅的 MVC 框架

支持 WebSocket 支持 SSL 配置 支持自定义启动 BannerText 支持自定义启动线程名称 支持自定义业务线程前缀 获取 Environment 参数允许设置默认值 升级 Netty 版本到 4.1.18.Final 修复获取客...

2017/12/16 17:06

Blade 1.4.0-beta 发布,简洁优雅的JavaWeb框架

English Blade是什么? blade是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 如果你喜欢,欢迎 Star and Fork, 谢谢! 官网地址:http://bladejava.com 特性 轻量级。代码简洁,结构清晰...

2015/10/23 09:33

blade 1.2.6 发布,简洁强大的 javaweb 框架

blade 是一个简洁强大的web框架,它内置了IOC管理,拦截器配置,REST API开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送,HTTP请求等常用功能。 blade1.2.6 更新如...

2015/08/12 17:36

没有更多内容

加载失败,请刷新页面

没有更多内容

暂无问答

java实现短地址服务

很多情况下URL太长并不是很好的,经常会遇到t.cn, url.cn, 126.fm, itc.cn, is.gd, bit.ly, x.co等短地址域名,下面用java实现

2015/07/28 16:01
1K
1
一场版本升级引发的性能血案的追凶过程

## 1. 故事的开始 上周 ActFramework 推出 [act-1.8.8-RC4 版本](https://www.oschina.net/news/96046/act-starter-1-8-8-0-released) 后, 我兴致勃勃更新了 [TFB 性能 PK 项目](https://git...

2018/05/21 13:28
2.8K
9

没有更多内容

加载失败,请刷新页面

没有更多内容

返回顶部
顶部