文档章节

「造个轮子」——设计 HTTP 请求全局上下文

crossoverJie
 crossoverJie
发布于 2018/10/09 08:06
字数 1257
阅读 42
收藏 2

前言

本次 Cicada 已经更新到了 v1.0.3

主要是解决了两个 issue,#9(Boss线程数好像设置有误 ) #8(怎么返回纯字符串内容不要JSON格式?)

所以本次的主要更新为:

  • Cicada 采用合理的线程分配来处理接入请求线程以及 IO 线程。
  • 支持多种响应方式(以前只有 json,现在支持 text)。
  • 为了满足上者引入了 context
  • 优雅停机。

其中我觉得最核心也最有用的就是这个 Context,并为此重构了大部分代码。

多种响应方式

在起初 Cicada 默认只能响应 json,这一点确实不够灵活。加上后续也打算支持模板解析,所以不如直接在 API 中加入可让用户自行选择不同的响应方式。

因此调整后的 API 如下。

想要输出 text/plain 时。

@CicadaAction("textAction")
public class TextAction implements WorkAction {
    @Override
    public void execute(CicadaContext context, Param param) throws Exception {
        String url = context.request().getUrl();
        String method = context.request().getMethod();
        context.text("hello world url=" + url + " method=" + method);
    }
}

而响应输出 application/json 时只需要把需要响应的对象写入到 json() 方法中.

因此原有的业务 action 中也加入了一个上下文的参数:

/**
 * abstract execute method
 * @param context current context
 * @param param request params
 * @throws Exception throw exception
 */
void execute(CicadaContext context ,Param param) throws Exception;

下面就来看看这个 Context 是如何完成的。

Cicada Context

先看看有了这个上下文之后可以做什么。

比如有些场景下我们需要拿到本次请求中的头信息,这时就可以通过这个 Context 对象直接获取。

当然不止是头信息:

  • 获取请求头。
  • 设置响应头。
  • 设置 cookie
  • 获取请求 URL
  • 获取请求的 method(get/post)等。

其实通过这些特点可以看出这些信息其实都和一次 请求、响应 密切相关,并且各个请求之间的信息应互不影响。

这样的特性是不是非常熟悉,没错那就是 ThreadLocal,它可以将每个线程的信息存储起来互不影响。

ThreadLocal 的原理本次不做过多分析,只谈它在 Cicada 中的应用。

CicadaContext.class

先来看看 CicadaContext 这个类的主要成员变量以及方法。

成员变量是两个接口 CicadaRequest、CicadaResponse,名称就能看出肯定是存放请求和响应数据的。

HttpDispatcher.class

想要存放本次请求的上下文自然是在真正请求分发的地方 HttpDispatcher

这里改的较大的就是两个红框处,第一部分是做上下文初始化及赋值。

第二部分自然就是卸载上下文。

先看初始化。

CicadaRequest cicadaRequest = CicadaHttpRequest.init(defaultHttpRequest) ;

首先是将 request 初始化:

CicadaHttpRequest 自然是实现了 CicadaRequest 接口:

这里只保存了请求的 URL、method 等信息,后续要加的请求头也存放在此处即可。

Response 也是同理的。

这两个具体的实现类都私有化了构造函数,防止外部破坏了整体性。

接着将当前请求的上下文保存到了 CicadaContext 中。

CicadaContext.setContext(new CicadaContext(cicadaRequest,cicadaResponse));

而这个函数本质使用的则是 ThreadLocal 来存放 CicadaContext

    public static void setContext(CicadaContext context){
        ThreadLocalHolder.setCicadaContext(context) ;
    }
    
    private static final ThreadLocal<CicadaContext> CICADA_CONTEXT= new ThreadLocal() ;
    
    /**
     * set cicada context
     * @param context current context
     */
    public static void setCicadaContext(CicadaContext context){
        CICADA_CONTEXT.set(context) ;
    }

处理业务及响应

接着就是处理业务,调用不同的 API 做不同响应。

context.text() 来说:

其实就是设置了对应的响应方式、以及把响应内容写入了 CicadaResponsehttpContent 中。

业务处理完后调用 responseContent() 进行响应:

responseContent(ctx,CicadaContext.getResponse().getHttpContent());

其实就是在上下文中拿到的响应方式及响应内容返回给客户端。

卸载上下文

最后有点非常重要,那就是 卸载上下文

如果这里不做处理,之后随着请求的增多,ThreadLocal 里存放的数据也越来越多,最终肯定会导致内存溢出。

所以 CicadaContext.removeContext() 就是为了及时删除当前上下文。

优雅停机

最后还新增了一个停机的方法。

其实也就是利用 Hook 函数实现的。

由于目前 Cicada 开的线程,占用的资源都不是特别多,所以只是关闭了 Netty 所使用的线程。

如果后续新增了自身的线程等资源,那也可以全部放到这里来进行释放。

总结

Cicada 已经更新了 4 个版本,雏形都有了。

后续会重点实现模板解析和注解请求路由完成,把 MVC 中的 view 完成就差不多了。

还没有了解的朋友可以点击下面链接进入主页了解下。

https://github.com/TogetherOS/cicada

© 著作权归作者所有

crossoverJie

crossoverJie

粉丝 738
博文 99
码字总数 191646
作品 0
江北
后端工程师
私信 提问
【Getty】Java NIO框架设计与实现

前言 Getty是我为了学习 Java NIO 所写的一个 NIO 框架,实现过程中参考了 Netty 的设计,同时使用 Groovy 来实现。虽然只是玩具,但是麻雀虽小,五脏俱全,在实现过程中,不仅熟悉了 NIO 的...

风马萧萧
02/01
0
0
Express开发实例(1) —— Hello,world!

Express是NodeJs开发中最常用的基础模块。NodeJs本身有Http模块,但是易用性并不好,因此有人在此基础上开发了Express模块。 什么是express express提供了丰富的路由功能,以及模板引擎。 方...

青夜之衫
2017/12/04
0
0
使用nginx+tomcat实现集群

1、工具及版本 nginx1.8.1 tomcat8.5.23 jdk1.8 2、开始 下载tomcat8,在百度中输入tomcat8下载,点第一个链接 进入tomcat8下载页面,选择8.5.23版本,点红色部分进行下载 3、新建一个文件夹t...

ytangdigl
2017/10/31
0
0
「造个轮子」——cicada 源码分析

前言 两天前写了文章《「造个轮子」——cicada(轻量级 WEB 框架)》 向大家介绍了 之后收到很多反馈,也有许多不错的建议。 同时在 GitHub 也收获了 80 几颗 小♥♥(绝对不是刷的。。) 也有...

crossoverJie
2018/09/05
0
0
张明云的Live——安卓 SDK 开发实战经验分享

零 Live主题本次Live入口:安卓 SDK 开发实战经验分享 一 关于我 我是张明云,常活跃于知乎和简书,知乎 Android 开发 和 编程 话题下优秀回答者;简书《Android 开发经验谈》专题管理员,超...

张明云
2016/12/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

无回路有向图的拓扑排序

因公司业务需要,在表单中每个字段都会配置自动计算,但自动计算公式中会引用到其他字段中的值。所以希望可以根据计算公式,优先计算引用的公式。所以最终使用了无回路有向图的扩扑排序来实现...

兜兜毛毛
38分钟前
3
0
如何抢占云栖大会C位?史上最强强强攻略来了

点击观看视频: APSARA云栖大会开发者情怀 原文链接 本文为云栖社区原创内容,未经允许不得转载。

阿里云官方博客
51分钟前
5
0
Kubernetes 从懵圈到熟练:集群服务的三个要点和一种实现

作者 | 声东 阿里云售后技术专家<br /> 文章来源:Docker,点击查看原文。 <br />以我的经验来讲,理解 Kubernetes 集群服务的概念,是比较不容易的一件事情。尤其是当我们基于似是而非的理解...

阿里巴巴云原生
54分钟前
7
0
PHP7.3的新特性

2018年12月6日,PHP7.3正式版发布,在PHP7.2基础上进行了大量错误修复和安全优化,性能提升10%! 从目前的更新说明来看,PHP 7.3 并不是一个主打新特性的版本,包含更多的是 bug 修复。PHP 7...

迅睿CMS-PHP开源CMS程序
59分钟前
7
0
Tomcat 应用中并行流带来的类加载问题

本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/f-X3n9cvDyU5f5NYH6mhxQ 作者:肖铭轩、王道环 随着 Java8 的不断流行,越来越多的开发人员使用并行流(parallel)...

vivo互联网技术
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部