ITPub博客

首页 > 应用开发 > > 轻量级 Java 框架 JOxygen

轻量级 Java 框架 JOxygen

作者:penny_liang 时间:2019-10-16 10:15:12 0 删除 编辑

JOxygen

轻量级Java框架


介绍

一个轻量级Java框架

oxygen-core 核心部分

基于cglib的aop实现

提供缓存管理和基于注解的缓存,内置LocalCache和Ehcache实现,可扩展

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

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

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

提供基于构造器注入的ioc(原因:依赖链清晰,并可任意切换ioc实现)

定时任务服务,内置提供了基于注解的定时任务服务

├─ src/main

│─ java/.../core //oxygen-core代码目录

│ │- aop //aop实现目录

│ │- cache //缓存实现目录

│ │- config //配置实现目录

│ │- constant //常量目录

│ │- convert //类型转换实现目录

│ │- crypto //密码加密目录

│ │- domain //基础实体目录

│ │- exception //异常管理目录

│ │- io //io读写目录

│ │- ioc //ioc实现目录

│ │- job //定时任务实现目录

│ │- scan //类扫描实现目录

│ │- util //工具类目录

│ │- Bootstrap.java //框架启动引导类

│ └- Plugin.java //插件接口

└─ resources/META-INF/services

└- ...core.Plugin //Plugin服务实现配置文件

oxygen-jdbc jdbc实现

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

支持多数据源

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

├─ src/main

│─ java/.../jdbc //oxygen-jdbc代码目录

│ │- config //配置数据源目录

│ │- handler //处理器目录,包括结果集处理 行处理 列处理

│ │- interceptor //拦截器目录,拦截sql执行前后及异常

│ │- record //基础crud

│ │- Jdbc.java //Jdbc核心操作类,提供crud操作

│ │- JdbcException.java //jdbc异常封装

│ └- JdbcPlugin.java //jdbc插件,与oxygen-core配套使用

└─ resources/META-INF/services

│- ...handler.ColumnHandler //列处理服务配置文件

└- ...core.Plugin //增加jdbcPlugin服务实现,与oxygen-core配套使用

oxygen-web

项目使用了Servlet3.0的ServletContainerInitializer接口

在servlet中可自动加载,不需要在web.xml中配置

使用@Router标记路由文件

使用@Mapping标记请求路径处理方法

参数绑定的取值域使用@Param,@HeaderParam,@CookieParam,@PathParam指定,默认为@Param

参数绑定支持简单类型 + Map<String,Object> + 用户实体类

支持返回Json、视图或自定义实现(文件下载等)

├─ src/main

│─ java/.../web //oxygen-web代码目录

│ │- handler //参数绑定处理

│ │- http //http请求解析

│ │- mapping //url映射,参数映射相关注解和实体

│ │- router //一个示例路由(获取服务器时间)

│ │- server //内置server接口和启动类

│ │- view //视图解析

│ │- DefaultWebAppInitializer.java //默认初始化实现

│ │- DispatcherServlet.java //路由分发器

│ │- WebAppInitializer.java //web自动初始化接口,提供给用户自定义使用

│ │- WebContainerInitializer.java //容器自动初始化

│ │- WebConf.java //web配置

│ └- WebPlugin.java //web插件

└─ resources/META-INF/services

│- ...ServletContainerIntializer //servlet3.0规范

│- ...core.Plugin //增加web插件

│- ...ParamHandler //参数处理服务

│- ...RequestParse //请求解析服务

└- ...ViewResolver //视图解析服务

特性

轻量级,注释完善,使用简单

使用ServiceLoader加载插件,易于扩展

安装

添加依赖到你的 pom.xml:

vip.justlive

oxygen-core

${oxygen.version}

vip.justlive

oxygen-jdbc

${oxygen.version}

vip.justlive

oxygen-web

${oxygen.version}

vip.justlive

oxygen-web-tomcat

${oxygen.version}

快速开始

基础返回

使用 Resp 作为返回

// 成功返回 code 00000

Resp.success(Object obj);

// 错误返回 默认code 99999

Resp.error(String msg);

// 错误返回 自定义code

Resp.error(String code, String msg);

异常处理

使用 Exceptions 抛出异常

// 创建 ErrorCode

ErrorCode err = Exceptions.errorCode(String module, String code);

ErrorCode err = Exceptions.errorMessage(String module, String code, String message);

// 抛出unchecked异常

throw Exceptions.wrap(Throwable e);

throw Exceptions.wrap(Throwable e, String code, String message);

throw Exceptions.wrap(Throwable e, ErrorCode errorCode, Object... arguments);

// 抛出业务异常 不含堆栈信息

throw Exceptions.fail(ErrorCode errCode, Object... params);

throw Exceptions.fail(String code, String message, Object... params);

// 抛出故障异常 包含堆栈信息

throw Exceptions.fault(ErrorCode errCode, Object... params);

throw Exceptions.fault(String code, String message, Object... params);

throw Exceptions.fault(Throwable e, ErrorCode errCode, Object... params);

throw Exceptions.fault(Throwable e, String code, String message, Object... params)

IOC

通过注解使用IOC容器

// 在配置文件中添加扫包路径

main.class.scan=com.xxx.xxx,com.aaa.bbb

// 使用 @Configuration 和 @Bean

@Configuration

public class Conf {

@Bean

Inter noDepBean() {

return new NoDepBean();

}

}

// 使用 @Bean 和 @Inject

@Bean("depBean")

public class DepBean implements Inter {

private final NoDepBean noDepBean;

@Inject

public DepBean(NoDepBean noDepBean) {

this.noDepBean = noDepBean;

}

...

}

// 运行时获取bean

Inter inter = BeanStore.getBean("depBean", Inter.class);

AOP

通过注解使用AOP

// 定义使用了Log注解的方法aop处理

@Before(annotation = Log.class)

public void log(Invocation invocation) {

...

}

// 目标方法添加注解

@Log

public void print() {

...

}

定时任务

使用注解 @Scheduled 标记一个方法需要作为定时任务

onApplicationStart(), cron(), fixedDelay(), or fixedRate() 必须配置其中一个

// 固定延迟任务 任务结束时间-下一个开始时间间隔固定

@Scheduled(fixedDelay = "500")

public void run1() {

...

}

// 固定周期任务 任务开始时间-下一个开始时间固定

@Scheduled(fixedRate = "600")

public void run2() {

...

}

// cron任务,并且程序启动后异步执行一次

@Scheduled(cron = "0/5 * * * * ?", onApplicationStart = true, async = true)

public void run3() {

...

}

缓存

使用缓存有两种方式:

JCache.cache() 获取缓存然后调用api

使用 @Cacheable 注解给方法添加缓存

// 使用缓存api

Cache cache = JCache.cache(cacheName);

T value = cache.get(key, clazz);

cache.set(key, value, duration, timeUnit);

...

// 使用注解

@Cacheable

public Object method() {

...

}

@Cacheable(key = "args[0]", duration = 10, timeUnit = TimeUnit.MINUTES)

public Object method(Object arg0, Object arg1) {

...

}

Jdbc

基础使用

可配置多数据源

使用Jdbc进行crud

使用ResultSetHandler 进行自定义类型转换处理

开启关闭事务

// 单独使用 需要自己创建并添加数据源

...

// 添加主数据源

Jdbc.addPrimaryDataSource(DataSource dataSource)

// 添加多数据源

Jdbc.addDataSource(String name, DataSource dataSource)

// crud

T Jdbc.query(String sql, Class clazz, Object... params)

List Jdbc.queryForList(String sql, Class clazz, Object... params)

Map Jdbc.queryForMap(String sql, Object... params)

List> Jdbc.queryForMapList(String sql, Object... params)

// 可自定义返回处理

T Jdbc.query(String sql, ResultSetHandler handler, Object... params)

int Jdbc.update(String sql, Object... params)

// 开启主数据源的事务

Jdbc.startTx()

// 开启指定数据源的事务

Jdbc.startTx(String dataSourceName)

// 关闭主数据源的事务

Jdbc.closeTx()

// 关闭指定数据源的事务

Jdbc.closeTx(String dataSourceName)

// 回滚事务

Jdbc.rollbackTx()

// 回滚指定数据源的事务

Jdbc.rollbackTx(String dataSourceName)

// 基础crud

Option opt = new Option()

...

Record.insert(opt)

Record.findById(Option.class, 1)

Record.find(opt)

Record.update(opt)

Record.deleteById(Option.class, 1)

Record.delete(opt);

// 配合oxygen-core使用, 只需在配置文件中配置数据源即可自动装载

// 多数据源名称

datasource.multi=a

// 主数据源

datasource.logSql=true

datasource.driverClassName=org.h2.Driver

datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

datasource.username=sa

datasource.password=sa

// 数据源a

datasource.a.driverClassName=org.h2.Driver

datasource.a.url=jdbc:h2:mem:a;DB_CLOSE_DELAY=-1

datasource.a.username=sa

datasource.a.password=sa

自定义列类型转换

实现 ColumnHandler 接口进行自定义处理

增加 META-INF/services/vip.justlive.oxygen.jdbc.handler.ColumnHandler 文件,添加实现类的类名

public class MyColumnHandler implements ColumnHandler {

@Override

public boolean supported(Class type) {

...

}

@Override

public Object fetch(ResultSet rs, int index) throws SQLException {

...

}

}

// 新增或修改 META-INF/services/vip.justlive.oxygen.jdbc.handler.ColumnHandler 添加自定义类名

xxx.xxx.MyColumnHandler

增加jdbc拦截

实现 JdbcInterceptor 接口

调用 Jdbc.addJdbcInterceptor 添加拦截

// 内置的sql打印拦截

@Slf4j

public class LogSqlJdbcInterceptor implements JdbcInterceptor {

@Override

public void before(String sql, List

if (log.isDebugEnabled()) {

log.debug("execute sql: {} -> params: {}", sql, params);

}

}

}

// 添加拦截器

Jdbc.addJdbcInterceptor(JdbcInterceptor interceptor)

web

基础使用

使用@Router @Mapping @Param...等注解进行定义路由类和请求方法以及绑定参数

使用View进行视图跳转,非void,View的返回值默认使用json处理

线程内使用Request.current(),Response.current()获取请求和返回

// 使用 @Router标记路由

@Router("/common")

public class CommonRouter {

// 标记请求路径和请求方式,默认支持所有请求 当返回值不是void且非View则为返回json

@Mapping(value = "/localDate",method = HttpMethod.GET)

public Resp localDate() {

return Resp.success(

LocalDate.now().plusDays(offset).atStartOfDay(ZoneOffset.systemDefault()).toInstant()

.toEpochMilli());

}

// 页面渲染 需要返回View

@Mapping("/index")

public View index() {

View view = new View();

view.setPath("/index.jsp");

return view;

}

// 重定向

@Mapping("/view")

public View index() {

View view = new View();

// 相对路径为容器内跳转 使用http://xxx则绝对跳转

view.setPath("/index");

view.setRedirect(true);

return view;

}

// 文件下载

@Mapping("download")

public void download(HttpServletResponse resp) throws IOException {

resp.setCharacterEncoding("utf-8");

resp.setContentType("application/octet-stream;charset=utf-8");

resp.setHeader("Content-disposition", "attachment;filename=xx.txt");

Files.copy(new File("xxx.txt"), resp.getOutputStream());

}

}

// 获取当前线程的Request Response

Request.current()

Response.current()

// 配置404错误页面跳转

web.error.404.page=

// 配置404自定义处理

web.error.404.handler=

// 配置500错误页面跳转

web.error.500.page=

// 配置500自定义处理

web.error.500.handler=

自定义视图解析

实现ViewResolver接口

通过ServiceLoader或WebPlugin.addViewResolver的方式进行添加自定义视图解析

// 内置的重定向和json解析器

public class DefaultViewResolver implements ViewResolver {

@Override

public boolean supported(Object data) {

// 重定向

if (data != null && data.getClass() == View.class && ((View) data).isRedirect()) {

return true;

}

// null 或者 非view 返回json

return data == null || data.getClass() != View.class;

}

@Override

public void resolveView(HttpServletRequest request, HttpServletResponse response, Object data) {

try {

if (data != null && data.getClass() == View.class) {

View view = (View) data;

String redirectUrl = view.getPath();

if (!redirectUrl.startsWith(Constants.HTTP_PREFIX) && !redirectUrl

.startsWith(Constants.HTTPS_PREFIX)) {

redirectUrl = request.getContextPath() + view.getPath();

}

response.sendRedirect(redirectUrl);

} else {

response.getWriter().print(JSON.toJSONString(data));

}

} catch (IOException e) {

throw Exceptions.wrap(e);

}

}

}

添加web启动执行类

只需实现WebAppInitializer接口,容器会自动加载

public class MyWebAppInitializer implements WebAppInitializer {

@Override

public void onStartup(ServletContext context) {

...

}

@Override

public int order() {

...

}

}

使用内置容器启动

依赖 oxygen-web-tomcat

在main中使用 Server.start启动

vip.justlive

oxygen-web-tomcat

${oxygen.version}

public static void main(String[] args) {

// 启动容器

Server.start();

...

// 关闭容器

Server.stop();

params) {

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/714/viewspace-3139785/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-12

  • 博文量
    189
  • 访问量
    1737