基于 Java8 + Netty4 创造的轻量级、高性能、简洁优雅的Web框架
Java8
Netty4
花 1小时 学会它做点有趣的项目,一款除了Spring系框架的不二之选。
快速开始 | BladeInAction | 视频教程 | 参与贡献 | 捐赠我们 | English
Blade 是一款追求简约、高效的 Web 框架,让 JavaWeb 开发如虎添翼,在性能与灵活性上同时兼顾。 如果你喜欢尝试有趣的事物,相信你会爱上它。 如果觉得这个项目不错可以 star 支持或者 捐赠 它 😊
Blade
JavaWeb
500kb
JAR
CSRF
XSS
BasicAuth
cron
» 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 » 优雅的:Blade 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 » 易部署:支持 maven 打成 jar 包直接运行。
maven
jar
Maven 配置:
Maven
创建一个基础的 Maven 工程
不需要创建 webapp 项目骨架, Blade 没这么麻烦。
webapp
或者 Gradle:
Gradle
compile 'com.bladejava:blade-mvc:2.0.11.ALPHA'
编写 main 函数写一个 Hello World:
main
Hello World
public static void main(String[] args) { Blade.of().get("/", ctx -> ctx.text("Hello Blade")).start(); }
用浏览器打开 http://localhost:9000 这样就可以看到第一个 Blade 应用了!
注册路由
硬编码方式
控制器方式
获取请求参数
表单参数
Restful参数
Body参数
参数转为对象
获取环境配置
获取Header
获取Cookie
静态资源
上传文件
设置会话
渲染到浏览器
渲染JSON
渲染文本
渲染Html
模板渲染
默认模板
Jetbrick模板
重定向
写入Cookie
路由拦截
日志输出
Basic认证
修改服务端口
配置SSL
自定义异常处理
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
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
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 类结构
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 名称
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); }
Environment environment = WebContext.blade().environment(); String version = environment.get("app.version", "0.0.1");;
@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); }
@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
classpath
static
如果要自定义静态资源URL,可以使用下面的代码
Blade.of().addStatics("/mydir");
当然你也可以在配置文件中指定 application.properties (位于classpath之下)
application.properties
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); }
使用 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!"); }
@GetRoute("html") public void printHtml(RouteContext ctx){ ctx.html("<center><h1>I Love Blade!</h1></center>"); }
默认情况下,所有模板文件都 在templates 目录中,大多数情况下你不需要更改它。
在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 模板
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 模板引擎
实现一个 BladeLoader 加载初始化的操作
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); }
<!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
@GetRoute("write-cookie") public void writeCookie(RouteContext ctx){ ctx.cookie("hello", "world"); ctx.cookie("UID", "22", 3600); }
Cookie API
WebHook 是Blade框架中可以在执行路由之前和之后拦截的接口。
WebHook
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 然后添加你喜欢的。
slf4-api
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"); }
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
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); } } }
这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜:
请查看 Apache License