oxygen

badge.svg

license-Apache%202-4EB1BA.svg

轻量级Java框架

介绍

一个轻量级Java框架

oxygen-core

配置管理,支持${attrs.key:defaultValue}表达式获取配置

加解密管理,提供加解密服务内置基础加密实现,例如SHA-1、SHA-256、MD5

异常管理,提供异常包装,统一异常编码,便于国际化

i18n国际化

资源文件加载,提供file,jar,classpath等文件加载

类扫描器

部分工具类

retry重试

oxygen-ioc

基于构造器的轻量级依赖注入

oxygen-aop

基于cglib实现的切面

轻巧简单,可单独使用

可使用注解Aspect或直接实现Interceptor编写切面

oxygen-cache

内置Ehcache和LocalCache缓存

提供基于注解Cacheable的方法缓存

oxygen-job

提供基于注解Scheduled的定时任务

oxygen-jdbc

小巧简单的jdbc实现,纯jdk实现,无第三方jar

支持多数据源

基于sql进行crud,不提供类似Hibernate的链式方法(原因:sql作为数据库领域的DSL,已经很自然优雅,Less is more)

oxygen-web

轻量级web框架支持注解声明和函数式编程

支持Servlet3.0 ServletContainerInitializer 自动加载,省略web.xml

支持i18n动态切换

提供WebHook进行请求拦截处理

支持自定义全局异常处理

特性

轻量级,使用简单

支持插件扩展

函数式编程

流式风格

快速开始

创建Maven项目

-tomcat

vip.justlive

oxygen-web${oxygen.server}

${oxygen.version}

或Gradle

compile 'vip.justlive:oxygen-web-tomcat:$oxygenVersion'

不需要webapp项目框架,支持Servlet3.0

编写 main 函数写一个 Hello World

public static void main(String[] args) {

Router.router().path("/").handler(ctx -> ctx.response().write("hello world"));

Server.server().listen(8080);

}

用浏览器打开 http://localhost:8080 这样就可以看到 hello world 了!

内容详解

注册路由

硬编码方式

Router.router().path("/").handler(ctx -> ctx.response().write("hello world"));

Router.router().path("/get").method(HttpMethod.GET).handler(get);

Router.router().path("/post").method(HttpMethod.POST).handler(post);

注解方式

@Router("/book")

public class BookRouter {

// 视图

@Mapping("/")

public ViewResult index() {

return Result.view("/book.html");

}

// json

@Mapping(value = "/ajax", method = {HttpMethod.POST})

public Book find(RoutingContext ctx) {

// ...

return new Book();

}

}

获取请求参数

表单参数或json请求参数

项目将json请求参数与表单参数合并,使用相同的方法或注解获取

使用RoutingContext获取

Router.router().path("/").handler(ctx -> {

String id = ctx.request().getParam("id");

ctx.response().write(id);

});

使用注解获取

@Mapping(value = "/ajax", method = {HttpMethod.POST})

public Book find(@Param Long id, @Param("tp") String type) {

// ...

return new Book();

}

restful参数

使用RoutingContext获取

Router.router().path("/{id}").handler(ctx -> {

String id = ctx.request().getPathVariable("id");

ctx.response().write(id);

});

使用注解获取

@Mapping(value = "/{id}", method = {HttpMethod.POST})

public void ajax(@PathParam("id") Long id) {

// ...

}

header参数

使用RoutingContext获取

Router.router().path("/").handler(ctx -> {

String id = ctx.request().getHeader("id");

ctx.response().write(id);

});

使用注解获取

@Mapping(value = "/", method = {HttpMethod.POST})

public void ajax(@HeaderParam("id") Long id) {

// ...

}

cookie参数

使用RoutingContext获取

Router.router().path("/").handler(ctx -> {

String id = ctx.request().getCookie("id");

ctx.response().write(id);

});

使用注解获取

@Mapping(value = "/", method = {HttpMethod.POST})

public void ajax(@CookieParam("id") Long id) {

// ...

}

参数转对象

实体类

@Data

public class Book {

private String name;

private String author;

}

使用RoutingContext转换

Router.router().path("/").handler(ctx -> {

// 表单或json请求参数绑定

Book book = ctx.bindParam(Book.class);

// cookie参数绑定

book = ctx.bindCookie(Book.class);

// header参数绑定

book = ctx.bindHeader(Book.class);

// restful参数绑定

book = ctx.bindPathVariables(Book.class);

});

使用注解获取

@Mapping(value = "/", method = {HttpMethod.POST})

public void ajax(@Param Book b1, @CookieParam Book b2, @HeaderParam Book b3, @PathParam Book b4) {

// ...

}

静态资源

内置默认将classpath下/public,/static作为静态资源目录,支持webjars,映射到/public

自定义静态资源可使用下面代码

Router.staticRoute().prefix("/lib").location("classpath:lib");

也可以通过配置文件指定

web.static.prefix=/public

web.static.path=/public,/static,classpath:/META-INF/resources/webjars

上传文件

使用RoutingContext获取

Router.router().path("/").handler(ctx -> {

MultipartItem file = ctx.request().getMultipartItem("file");

// ...

});

使用注解获取

@Mapping("/")

public void upload(MultipartItem image, @MultipartParam("file1") MultipartItem file) {

// 不使用注解则使用方法参数名作为请求参数名称

// 使用注解指定请求参数名称

}

结果渲染

渲染json

// 使用RoutingContext返回

Router.router().path("/").handler(ctx -> {

ctx.response().json(new Book("Java", "xxx"));

});

// 注解式

@Mapping("/")

public Book find() {

// 直接返回对象,框架默认处理成json

return new Book("Java", "xxx");

}

渲染文本

// 使用RoutingContext返回

Router.router().path("/").handler(ctx -> {

ctx.response().text("hello world");

});

渲染html

// 使用RoutingContext返回

Router.router().path("/").handler(ctx -> {

ctx.response().html("

hello world");

});

渲染模板

内置支持了jsp和thymeleaf模板,默认对应resources下的WEB-INF和templates目录

# 可通过下面配置进行更改模板目录

web.view.jsp.prefix=WEB-INF

web.view.thymeleaf.prefix=/templates

模板使用

// 使用RoutingContext

Router.router().path("/").handler(ctx -> {

ctx.response().template("index.html");

});

Router.router().path("/").handler(ctx -> {

Map attrs = new HashMap<>();

// ...

ctx.response().template("index.html", attrs);

});

// 注解式

@Mapping("/")

public Result index() {

return Result.view("index.html");

}

@Mapping("/")

public Result index() {

Map attrs = new HashMap<>();

// ...

return Result.view("index.html").addAttributes(attrs);

}

重定向

Router.router().path("/").handler(ctx -> {

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

});

@Mapping("/a")

public Result index() {

// 内部地址 相对于根目录: /b

// return Result.redirect("/b");

// 内部地址 相对于当前路径: /a/b

// return Result.redirect("b");

// 协议地址

return Result.redirect("https://github.com/justlive1");

}

写入cookie

@Mapping("/")

public void index(RoutingContext ctx) {

ctx.response().setCookie("hello", "world");

ctx.response().setCookie("java", "script", 100);

ctx.response().setCookie("uid", "xxx", ".justlive.vip", "/", 3600, true);

}

添加header

@Mapping("/")

public void index(RoutingContext ctx) {

ctx.response().setHeader("hello", "world");

}

写入session

@Mapping("/")

public void index(RoutingContext ctx) {

ctx.request().getSession().put("key", "value");

}

拦截器

WebHook是拦截器接口,可以实现执行前、执行后和结束拦截处理

@Slf4j

@Bean

public class LogWebHook implements WebHook {

@Override

public boolean before(RoutingContext ctx) {

log.info("before");

return true;

}

@Override

public void after(RoutingContext ctx) {

log.info("after");

}

@Override

public void finished(RoutingContext ctx) {

log.info("finished");

}

}

异常处理

框架默认提供了一个异常处理器,如需自定义处理异常,可以像下面这样使用

@Bean

public class CustomExceptionHandler extends ExceptionHandlerImpl {

@Override

public void handle(RoutingContext ctx, Exception e, int status) {

if (e instanceof CustomException) {

// do something

} else {

super.handle(ctx, e, status);

}

}

}

部署项目

修改端口

编码指定

Server.server().listen(8080);

配置文件

server.port=8081

启动命令

java -jar -Dserver.port=8090 app.jar

运行项目

使用内嵌容器启动

启动类

public class Application {

public static void main(String[] args) {

Server.server().listen();

}

}

通用打包方式

${mainClass}为上面的启动类

会生成lib目录存放依赖jar

org.apache.maven.plugins

maven-compiler-plugin

${maven.compiler.source}

${maven.compiler.target}

UTF-8

org.apache.maven.plugins

maven-jar-plugin

true

lib/

${mainClass}

org.apache.maven.plugins

maven-dependency-plugin

copy

package

copy-dependencies

${project.build.directory}/lib

打成fat-jar:

使用springboot打包插件

org.springframework.boot

spring-boot-maven-plugin

1.3.8.RELEASE

package

repackage

使用外部容器(jetty、tomcat等)

无需web.xml配置,打包成war放入容器即可,实现机制可查看WebContainerInitializer

false

外部化配置

框架可以通过使用配置文件进行修改默认属性

##### 基础配置

# 配置覆盖地址,用户外部配置覆盖项目配置 例 file:/config/*.properties,classpath*:/config/*.properties,xx.properties

config.override.path=

# 类扫描路径属性

main.class.scan=vip.justlive

# 临时文件根目录

main.temp.dir=.oxygen

# 缓存实现类,自定义缓存时使用

cache.impl.class=

##### web

# embedded 启动端口

server.port=8080

# context path

server.contextPath=

# session失效时间,单位秒

web.session.expired=3600

# 默认静态资源请求前缀

web.static.prefix=/public

# 默认静态资源目录

web.static.path=/public,/static,classpath:/META-INF/resources/webjars

# 静态资源缓存时间

web.static.cache=3600

# jsp路径前缀

web.view.jsp.prefix=WEB-INF

# thymeleaf 路径前缀

web.view.thymeleaf.prefix=/templates

# thymeleaf 视图后缀

web.view.thymeleaf.suffix=.html

# 内置简单视图处理 路径前缀

web.view.simple.prefix=/templates

# 内置简单视图处理 视图后缀

web.view.simple.suffix=.htm

# 是否开启模板缓存

web.view.cache.enabled=true

##### 定时任务job

# job线程名称格式

job.thread.name.format=jobs-%d

# job核心线程池大小

job.core.pool.size=10

##### i18n国际化

# i18n配置文件地址

i18n.path=classpath:message/*.properties

# i18n默认语言

i18n.default.language=zh

# i18n默认国家

i18n.default.country=CN

# i18n参数key

i18n.param.key=locale

# i18n Session key

i18n.session.key=I18N_SESSION_LOCALE

##### jetty

# 虚拟主机

server.jetty.virtualHosts=

# 连接器在空闲状态持续该时间后(单位毫秒)关闭

server.jetty.idleTimeout=30000

# 温和的停止一个连接器前等待的时间(毫秒)

server.jetty.stopTimeout=30000

# 等待处理的连接队列大小

server.jetty.acceptQueueSize=

# 允许Server socket被重绑定,即使在TIME_WAIT状态

server.jetty.reuseAddress=true

# 是否启用servlet3.0特性

server.jetty.configurationDiscovered=true

# 最大表单数据大小

server.jetty.maxFormContentSize=256 * 1024 * 1024

# 最大表单键值对数量

server.jetty.maxFormKeys=200

##### tomcat

# 最大请求队列数

server.tomcat.acceptCount=100

# 最大连接数

server.tomcat.maxConnections=5000

# 最大工作线程数

server.tomcat.maxThreads=200

# 最小线程数

server.tomcat.minSpareThreads=10

# 最大请求头数据大小

server.tomcat.maxHttpHeaderSize=8 * 1024

# 最大表单数据大小

server.tomcat.maxHttpPostSize=2 * 1024 * 1024

# 连接超时

server.tomcat.connectionTimeout=20000

# URI解码编码

server.tomcat.uriEncoding=utf-8

# 调用backgroundProcess延迟时间

server.tomcat.backgroundProcessorDelay=10

# 是否启用访问日志

server.tomcat.accessLogEnabled=false

# 访问日志是否开启缓冲

server.tomcat.accessLogBuffered=true

# 是否设置请求属性,ip、host、protocol、port

server.tomcat.accessLogRequestAttributesEnabled=false

# 每日日志格式

server.tomcat.accessLogFileFormat=.yyyy-MM-dd

# 日志格式

server.tomcat.accessLogPattern=common

##### undertow

# 主机名

server.undertow.host=0.0.0.0

# io线程数

server.undertow.ioThreads=

# worker线程数

server.undertow.workerThreads=

# 是否开启gzip压缩

server.undertow.gzipEnabled=false

# gzip处理优先级

server.undertow.gzipPriority=100

# 压缩级别,默认值 -1。 可配置 1 到 9。 1 拥有最快压缩速度,9 拥有最高压缩率

server.undertow.gzipLevel=-1

# 触发压缩的最小内容长度

server.undertow.gzipMinLength=1024

# url是否允许特殊字符

server.undertow.allowUnescapedCharactersInUrl=true

# 是否开启http2

server.undertow.http2enabled=false

联系信息

java 轻量级 job_oxygen: 一个轻量级Java框架,包含ioc、aop、config、cache、job、Jdbc、web等...相关推荐

  1. getconnection java_在MyEclipse用java写的一个GetConnection1.java,用于连接MySQL,却总是出错。(没有财富值了,见谅!)...

    在MyEclipse用java写的一个GetConnection1.java,用于连接MySQL,却总是出错.求救!!!packageJavaBean1;importjava.sql.*;import ...

  2. java play_Play是一个全栈框架

    背景 没有了Spring MVC,你就什么都不会了吗? no no no ! 作为一个工程师你必须了解更多,Play MVC就是是你必备的技能,Play framework非常强大堪比Spring f ...

  3. 邯郸 java高级_一个高级java工程师的进阶之路

    1. JAVA.要想成为JAVA(高级)工程师肯定要学习JAVA.一般的程序员或许只需知道一些JAVA的语法结构就可以应付了.但要成为JAVA(高级) 工程师,您要对JAVA做比较深入的研究.您应该多 ...

  4. 计算机编程老鸟的心得,java入门123——一个老鸟java学习心得.docx

    java入门123--一个老鸟的java学习心得 学习Java心得体会 学习了一学期的Java课程,觉得是该总结自己的心得体会了.开始学习任何一门课(包括java),兴趣最重要.一直觉得自己在学计算机 ...

  5. JAVA三维可视化组件:Matplot 3D for JAVA(V3.0) 一个纯JAVA开发的科学数据可视化组件包 类似 Python 的matplotlib(含示例代码)

    目录 概述 组件下载及项目地址 效果展示和示例代码 概述 Matplot3D for JAVA(V3.0) 是一个基于JAVA SE 1.8环境开发的三维图形图表组件. 组件由纯JAVA SE 实现( ...

  6. Java 如何判断一个字符串中是否包含某一 子字符串

    对于以上问题的解决,我一般使用String.indexOf("子串")的方式解决,  请看代码: public class IndexOfTest {public static v ...

  7. 使用java代码判断一个字符串里是否包含中文字符

    测试代码: package unicode;import org.apache.commons.lang3.StringUtils;public class ChineseTest {public s ...

  8. java国际象棋_chess 一个用JAVA编写的国际象棋的程序 - 下载 - 搜珍网

    一个java做的国际象棋小游戏/build/javaChess.jar 一个java做的国际象棋小游戏/docs/javadoc/allclasses-frame.html 一个java做的国际象棋小 ...

  9. java drawboard_学习一个月JAVA写的黑白棋程序(欢迎高手来指点)

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 public void clean(Graphics g) //清屏 { g.setColor(0xffffff); g.fillRect(0,0,180 ...

最新文章

  1. Nature Method :Rob Knight发布Striped UniFrac算法轻松分析微生物组大数据
  2. 13. python 类
  3. CentOS7 0安装Maven
  4. webService初探
  5. 小黑小波比.搭建个人网站
  6. 休眠锁定模式– OPTIMISTIC_FORCE_INCREMENT锁定模式如何工作
  7. String Start!
  8. 背后的故事之 - 快乐的Lambda表达式(二)
  9. Java开发者必备:超全的Java问题排查工具单
  10. linux服务器用户组和权限管,linux 用户管理,用户权限管理,用户组管理
  11. library的英语怎么读音_如何让你的英语口音无限接近母语者?英语语音语调的独家训练方法...
  12. TCPIP详解三次握手和四次挥手
  13. 网页版office服务器,Office 网页版服务说明
  14. 6.2 数据通路的建立
  15. 女程序员:秃头的富婆不好当
  16. (2)ARCH效应、均值方程、GARCH族模型、对波动率建模、预测(包含R语言代码)
  17. web页面实现拨打电话,发短信等功能
  18. 读书笔记--《原则》
  19. java面试-多线程常见面试题
  20. bk-02 C++ vector用法 博客园

热门文章

  1. 【秃头系列】-【本科生毕设论文格式Word】自动生成页面布局
  2. 如何免费获取县级气象数据?
  3. C3P0的使用 Spring配置数据库连接池
  4. python用来查看变量类型的函数是什么_python查看变量类型的函数
  5. 计算机文化基础008,2013 中国成人教育 翻转课堂在高校计算机文化基础课中的应用研究_刘桂花...
  6. 小程序推送服务通知(前后端代码)
  7. Linux比windows更适合工作和娱乐
  8. html5保护环境作品,保护环境的绘画作品图片
  9. 传奇自定义技能栏技术分享-GEE
  10. DM数据库开启归档模式的三种方式