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

前言
本次 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() 来说:

其实就是设置了对应的响应方式、以及把响应内容写入了 CicadaResponse 的 httpContent 中。
业务处理完后调用 responseContent() 进行响应:
responseContent(ctx,CicadaContext.getResponse().getHttpContent());
其实就是在上下文中拿到的响应方式及响应内容返回给客户端。
卸载上下文
最后有点非常重要,那就是 卸载上下文。
如果这里不做处理,之后随着请求的增多,ThreadLocal 里存放的数据也越来越多,最终肯定会导致内存溢出。
所以 CicadaContext.removeContext() 就是为了及时删除当前上下文。
优雅停机
最后还新增了一个停机的方法。

其实也就是利用 Hook 函数实现的。
由于目前 Cicada 开的线程,占用的资源都不是特别多,所以只是关闭了 Netty 所使用的线程。
如果后续新增了自身的线程等资源,那也可以全部放到这里来进行释放。
总结
Cicada 已经更新了 4 个版本,雏形都有了。
后续会重点实现模板解析和注解请求路由完成,把 MVC 中的 view 完成就差不多了。
还没有了解的朋友可以点击下面链接进入主页了解下
「造个轮子」——设计 HTTP 请求全局上下文的更多相关文章
- 「造个轮子」——cicada 设计一个配置模块
前言 在前两次的 cicada 版本中其实还不支持读取配置文件,比如对端口.路由的配置. 因此我按照自己的想法创建了一个 issue ,也收集到了一些很不错的建议. 最终其实还是按照我之前的想法来做了 ...
- 「造个轮子」——cicada 源码分析
前言 两天前写了文章<「造个轮子」--cicada(轻量级 WEB 框架)> 向大家介绍了 cicada 之后收到很多反馈,也有许多不错的建议. 同时在 GitHub 也收获了 80 几颗 ...
- 「造个轮子」——cicada(轻量级 WEB 框架)
前言 俗话说 「不要重复造轮子」,关于是否有必要不再本次讨论范围. 创建这个项目的主要目的还是提升自己,看看和知名类开源项目的差距以及学习优秀的开源方式. 好了,现在着重来谈谈 cicada 这个项目 ...
- 零元学Expression Design 4 - Chapter 3 看小光被包围了!!如何活用「Text On Path」设计效果
原文:零元学Expression Design 4 - Chapter 3 看小光被包围了!!如何活用「Text On Path」设计效果 本章将教大家如何活用「Text On Path」,做出文绕图 ...
- 迄今为止最硬核的「Java8时间系统」设计原理与使用方法
为了使本篇文章更容易让读者读懂,我特意写了上一篇<任何人都需要知道的「世界时间系统」构成原理,尤其开发人员>的科普文章.本文才是重点,绝对要读,走起! Java平台时间系统的设计方案 几乎 ...
- Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子
这个是转载自:http://www.cnblogs.com/keyindex/archive/2012/08/11/2634005.html(那个比较容易忘记,希望博主不要生气的) 前言 本文假定读者 ...
- 企业运营对 DevOps 的「傲慢与偏见」
摘要:出于各种原因,并非所有人都信任 DevOps .有些人觉得 DevOps 只不过给开发者改善产品提供了一个途径而已,还有的人觉得 DevOps 是一堆悦耳的空头支票,甚至有人认为 DevOps ...
- [译]聊聊C#中的泛型的使用(新手勿入) Seaching TreeVIew WPF 可编辑树Ztree的使用(包括对后台数据库的增删改查) 字段和属性的区别 C# 遍历Dictionary并修改其中的Value 学习笔记——异步 程序员常说的「哈希表」是个什么鬼?
[译]聊聊C#中的泛型的使用(新手勿入) 写在前面 今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发 ...
- 面试都在问的「微服务」「RPC」「服务治理」「下一代微服务」一文带你彻底搞懂!
❝ 文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) ❞ 单体式应用程序 与微服务相对的另一个概念是传统的「单体式应用程 ...
随机推荐
- 实验二《Java面向对象程序设计》实验报告
一.实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 二.实验步骤 (一)单元测试 1.三种代码:伪代码.测 ...
- 从Facebook数据泄露事件看大数据时代的个人信息安全问题
进入21世纪后,互联网开始大规模普及,线上业务和线上服务也开始逐渐走入人们的生活.尤其在智能手机和移动互联网诞生以后,人们对网络的依赖更是与日俱增.然而,伴随而来的则是涉及个人隐私的信息安全问题.个人 ...
- 通过zuul修改请求参数——对请求参数进行解密
zuul是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用,Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架,Zuul 相当于是设备和 ...
- 3dmax 3dmax计算机要求 3dmax下载
渲染首先是要X64兼容台式电脑,笔记本不行,笔记本就是学生拿来玩还行,渲染大图笔记本真的是发热. 配置一般的电脑和笔记本千万不要尝试安装3dmax2019了,很卡的,3dmax2019只有64位,没有 ...
- MongoDB 用Robomong可视化工具操作的 一些简单语句
一.数据更新 db.getCollection('表名').update({ "字段":{$in:["值"]} }, //更新条件 {$set:{ " ...
- java方法的调用
各种方法的调用实例 package cn.edu.fhj.day004; public class FunctionDemo { // 定义全局的变量 public int a = 3; public ...
- 蓝鲸单机安装mysql问题记录
1.注意默认启动用户为mysql 2.由于执行指令用的root,有些文件会生成为root用户 3.注意将datadir basedir socket dir 修改称mysql chown mys ...
- [LeetCode] Shifting Letters 漂移字母
We have a string S of lowercase letters, and an integer array shifts. Call the shift of a letter, th ...
- GYM 101617 F
说到这题还要提到周日下午训练赛,都进去了hmc说他这场单切过准备换一场. 很不幸的是我当时已经开了这个几何题, 开场就开几何是什么鬼啊!!! 给你n个圆,找一点在所有园内并且离原点最远.(保证有解) ...
- 关于如何在Visual Studio上仿真调试安卓的U3D应用
正巧最近需要开发一个安卓手机上的Unity3D游戏功能,想着既然要开发么,当然需要调试.本来的话一些基础功能是不需要使用仿真模拟器,直接在U3D的开发编辑器上就能调试,不过有一些安卓上才能执行,比如 ...