轻量级 Java 框架 JOxygen

码农软件 · 软件分类 · Web框架 · 2019-03-24 07:56:53

软件介绍

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:

<!-- 核心包 包含aop ioc 异常处理 缓存 定时任务等 -->
<dependency>
    <groupId>vip.justlive</groupId>
    <artifactId>oxygen-core</artifactId>
    <version>${oxygen.version}</version>
</dependency>

<!-- jdbc实现 可单独使用 -->
<dependency>
    <groupId>vip.justlive</groupId>
    <artifactId>oxygen-jdbc</artifactId>
    <version>${oxygen.version}</version>
</dependency>

<!-- web实现 已依赖了core -->
<dependency>
    <groupId>vip.justlive</groupId>
    <artifactId>oxygen-web</artifactId>
    <version>${oxygen.version}</version>
</dependency>

<!-- 已依赖了web 并提供了embeded tomcat -->
<dependency>
    <groupId>vip.justlive</groupId>
    <artifactId>oxygen-web-tomcat</artifactId>
    <version>${oxygen.version}</version>
</dependency>

快速开始

基础返回

使用 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<T> clazz, Object... params)
List<T> Jdbc.queryForList(String sql, Class<T> clazz, Object... params)
Map<String, Object> Jdbc.queryForMap(String sql, Object... params)
List<Map<String, Object>> Jdbc.queryForMapList(String sql, Object... params)
// 可自定义返回处理
T Jdbc.query(String sql, ResultSetHandler<T> 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<Object> params) {
    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接口

  • 通过ServiceLoaderWebPlugin.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启动

<!-- 已依赖了web 并提供了embeded tomcat -->
<dependency>
    <groupId>vip.justlive</groupId>
    <artifactId>oxygen-web-tomcat</artifactId>
    <version>${oxygen.version}</version>
</dependency>


public static void main(String[] args) {
  // 启动容器
  Server.start();
  ...
  // 关闭容器
  Server.stop();
}

本文地址:https://codercto.com/soft/d/2027.html

Hit Refresh

Hit Refresh

Satya Nadella、Greg Shaw / HarperBusiness / 2017-9-26 / USD 20.37

Hit Refresh is about individual change, about the transformation happening inside of Microsoft and the technology that will soon impact all of our lives—the arrival of the most exciting and disruptive......一起来看看 《Hit Refresh》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码