JOxygen 2.0 发布,支持函数式编程、web 编程更加简便

栏目: 软件资讯 · 发布时间: 5年前

内容简介:虽然不提倡重复造轮子,但好处之一是轮子可以造成方的 2.0全新升级重构版,让web编程更简单 public static void main(String[] args) { Router.router().path("/").handler(ctx -> ctx.response().write("h...

虽然不提倡重复造轮子,但好处之一是轮子可以造成方的JOxygen 2.0 发布,支持函数式编程、web 编程更加简便

2.0全新升级重构版,让web编程更简单

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

  • 注册路由
    • 硬编码方式
    • 注解方式
  • 获取请求参数
    • 表单参数或json请求参数
    • restful参数
    • header参数
    • cookie参数
    • 参数转对象
  • 静态资源
  • 上传文件
  • 结果渲染
    • 渲染json
    • 渲染文本
    • 渲染html
    • 渲染模板
    • 重定向
    • 写入cookie
    • 添加header
  • 拦截器
  • 异常处理
  • 部署项目
    • 修改端口
    • 运行项目

注册路由

硬编码方式

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("<html><body><span>hello world</span></body></html>");
});

渲染模板

内置支持了jspthymeleaf模板,默认对应resources下的WEB-INFtemplates目录

# 可通过下面配置进行更改模板目录
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<String, Object> attrs = new HashMap<>();
  // ...
  ctx.response().template("index.html", attrs);
});

// 注解式
@Mapping("/")
public Result index() {
  return Result.view("index.html");
}

@Mapping("/")
public Result index() {
  Map<String, Object> 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");
}

拦截器

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

运行项目

使用内嵌容器启动

启动类

public class Application {
  public static void main(String[] args) {
    Server.server().listen();
  }
}

通用打包方式

  • ${mainClass}为上面的启动类
  • 会生成lib目录存放依赖jar
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>${maven.compiler.source}</source>
        <target>${maven.compiler.target}</target>
        <encoding>UTF-8</encoding>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>${mainClass}</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
        <execution>
          <id>copy</id>
          <phase>package</phase>
          <goals>
            <goal>copy-dependencies</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

打成fat-jar:

  • 使用springboot打包插件
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>1.3.8.RELEASE</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

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

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

<!-- 解决默认打war包报错 webxml attribute is required -->
<properties>
  <failOnMissingWebXml>false</failOnMissingWebXml>
</properties>

外部化配置

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

##### 基础配置
# 配置覆盖地址,用户外部配置覆盖项目配置 例 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=
# 默认静态资源请求前缀
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
# 是否开启模板缓存
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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

爆品方法论

爆品方法论

陈轩 / 2019-1-6 / 49

作者利用自己在品牌定位和爆品营销领域十三年的实践历练,结合移动社交媒体、爆品营销策略和社会心理学,精心筛选出上百个经典的营销案例,既分享了爆品内容的炮制方法和营销原理,也分享了爆品内容的推广技巧,告诉读者如何用移动社交媒体来颠覆传统营销模式,如何用互联网思维来玩转营销,实现低成本、高销量、大传播,成功打造市场爆品。一起来看看 《爆品方法论》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具