MiniHttpServer

Mini Http Server for Java (Android)

MiniHttpServer

一:开发环境

Mac OS 10、Java 1.8、IDEA(Gradle工程)

二:介绍

一款基于Java Nio实现的Http解析框架,支持常见的请求解析和逻辑;采用单线程解析多线程业务处理方案,内置线程池方便线程管理;支持静态文件下载;支持表单参数和文件上传,支持PUT文件上传。解析成功后返回HttpRequest和HttpResponse。除常见的接口请求返回外,HttpResponse可以向客户端发送跨域请求结果,也可以发送文件,支持区分附件模式。

三:特点

  • 纯Java API实现,性能好
  • 基于Java Nio,异步机制,相比传统IO,有更高的性能。
  • 体积小,代码少,支持Http部分协议,满足绝大部分需求。
  • 支持POST表单数据和多文件上传。
  • 支持PUT上传文件,自动保存到file目录。
  • 支持发送文件到客户端。
  • 支持发送重定向等基本http协议内容。
  • 支持反馈跨域请求。
  • 支持自定义header。

四:引入(最新版本)

  1. Maven
<dependency>
  <groupId>com.itgowo</groupId>
  <artifactId>MiniHttpServer</artifactId>
  <version>0.0.21</version>
  <type>pom</type>
</dependency>
  1. Gradle
implementation 'com.itgowo:MiniHttpServer:0.0.21'

五:初始化(库Jar中有Demo类,可以参考)

Demo.java

  1. 创建MiniHttpServer
    MiniHttpServer 继承自Thread,复写了Thread.start()方法,与MiniHttpServer.startServer()方法作用相同,不会冲突。
MiniHttpServer miniHttpServer = new MiniHttpServer(); 
  1. 设置初始信息
public void init(boolean isBlocking, InetSocketAddress inetSocketAddress, String webDir, onHttpListener onHttpListener)
参数 推荐值 说明
isBlocking false 是否用阻塞模式,推荐false,Nio特点就是非阻塞
inetSocketAddress InetSocketAddress(port) 服务使用哪个端口
webDir "/web" 服务器静态目录,file和temp目录会在webDir中
onHttpListener new 实现类 服务器接收Http请求回调,如果是文件则FileList中有文件信息

3.设置文件存储策略

当有文件上传到服务器时,默认保存在webDir里的file目录下,创建UUID命名的目录,将上传的文件放入其中,文件名已Http信息fileName命名,防止重名文件冲突。例 web/file/02e86423-d1bd-4218-8f70-a7c73c71bf62/test.png
默认每次server初始化后执行清理功能。需要手动执行使用这个方法miniHttpServer.getFileManager().cleanOldFile();

  httpServer.setFileLimit(long fileSize, long fileLastTime);
参数 推荐值 说明
fileSize 1024 * 1024 * 500 file文件夹存储阈值,超过执行清理功能,
fileLastTime 1000 * 60 * 60 * 24 * 7 最后编辑时间计算存储时间,默认保留7天内文件
  1. onHttpListener类
public void onError(Throwable throwable)`

public void onHandler(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception`

六:情景

1. 获取header

    Map<String, String> headers = httpRequest.getHeaders();
    boolean hasContentType = httpRequest.containsHeader(HttpHeaderNames.CONTENT_TYPE);
    String contentType = httpRequest.getHeaders().get(HttpHeaderNames.CONTENT_TYPE);

2. 获取Parms,参数操作,来源一:url中"?"后面解析出来的参数键值对;来源二:POST表单参数解析

    Map<String, String> parms = httpRequest.getParms();
    String userId = httpRequest.getParms().get("userId");

3. 客户端GET请求资源

    if (HttpMethod.GET == httpRequest.getMethod()) {
        if (httpRequest.getUri().equalsIgnoreCase("/")) {
            httpRequest.setUri("/index.html");
        }
        //缓存策略,浏览器指定时间内只获取一次文件,如果sendFile()包含cacheControl参数,则不需要在设置,设置了以单独设置为准。没有cacheControl的方法则默认没有此参数
        httpResponse.addHeader(HttpHeaderNames.CACHE_CONTROL, HttpHeaderValues.MAX_AGE + "=3600");

//      httpResponse.sendFile(httpNioServer.getFileManager().getFile(httpRequest.getUri()));
//      httpResponse.sendFile(httpNioServer.getFileManager().getFile(httpRequest.getUri()), true);
        //cacheControl参数添加了不一定起作用,如果单独加了header,则此方法参数无效
        httpResponse.sendFile(httpNioServer.getFileManager().getFile(httpRequest.getUri()), HttpStatus.OK, 3600, true);
    }

4. 客户端POST请求,POST请求,常见的Body传Json文本或者表单上传文件

    if (HttpMethod.POST == httpRequest.getMethod()) {
        if (httpRequest.isMultipart_formdata()) {
            Map<String, File> fileMap = httpRequest.getFileList();
          //  httpResponse.sendData(HttpStatus.OK);
            httpResponse.setData(Arrays.toString(fileMap.values().toArray())).sendData(HttpStatus.OK);
        } else {
            String requestBody = httpRequest.getBody();
            httpResponse.setData(requestBody).sendData(HttpStatus.OK);
        }
    }

5. 客户端OPTIONS请求,OPTIONS请求,跨域请求最多的是ajax发出的,应对web请求

    if (HttpMethod.OPTIONS == httpRequest.getMethod()) {
        httpResponse.sendOptionsResult();
    }

6. 客户端PUT请求,跟POST表单上传文件不同,Http中Body默认为一个文件,临时存在temp目录,PUT如果需要传递文件名请在headers中添加自定义数据。

    if (HttpMethod.PUT == httpRequest.getMethod()) {
        Map<String, File> fileMap = httpRequest.getFileList();
        httpResponse.sendData(HttpStatus.OK);
    }

7. 客户端其他请求,HEAD、DELETE、TRACE、CONNECT、PATCH 等不常见,需要自己返回结果即可,无特殊需求。

8. 重定向

    httpResponse.sendRedirect("http://www.baidu.com");

七:关键类

HttpRequest

变量 说明
socketChannel 与客户端连接通信的连接通道
clientId 与Nio中Channel绑定,连接唯一标记
method Http报文中的请求方式(GET/POST/PUT和DELETE等
uri Http报文中Method后面的路径,最开始以"/"开始
protocolVersion Http协议版本
queryParameterString url中"?"后面参数原始数据
parms 来源一:url中"?"后面解析出来的参数键值对;来源二:POST表单参数解析
headers Http的header参数,Key-Value形式
remoteIp 客户端IP
contentLength body长度
multipart_formdata 是否是表单数据,如果为true,则需要检查下是否有文件上传,fileList
body PUT方式的Body会存到文件里,此处值为空,POST表单上传文件,Body也为空,请检查fileList
fileList PUT方式的Body会存到fileList中,POST表单上传文件,Body也为空,也会存到fileList
其他方法 说明
isApplicationJson() ContentType是不是Json类型
containsFile(String key) fileList中是否包含该文件名的文件
containsHeader(String key) headers中是否包含该参数
addToFileList(String key, File file) 添加文件到fileList,内部方法
addFileList(Map<String, File> fileList) 添加到fileList,内部方法
isGzip() 是否启用了Gzip,第一版不考虑加入此功能
isKeepAlive() 是否保持连接
sendData(ByteBuffer byteBuffer) 向客户端发送消息,最原始方式,http协议格式请用HttpResponse

HttpResponse

变量 说明
socketChannel 与客户端连接通信的连接通道
httpRequest httpRequest对象
status HttpStatus常量
mimeType 内容类型ContentType
data 返回客户端数据,ByteBuffer或其子类
header 返回客户端Http的header信息
keepAlive 告诉客户端是否维持连接
其他方法 说明
addHeader(String name, String value) 添加返回客户端Http的header信息
sendOptionsResult() 返回Options请求回答,默认允许所有
sendRedirect(String newUrl) 让客户端重定向到新地址
sendFile(File file, HttpStatus httpStatus, boolean autoHtmltoNotAttachment) 向客户端发送符合Http协议的文件,如果是html文件,则没有attachment标记,浏览器不按附件下载,按网页打开
sendData(HttpStatus status) 向客户端发送信息,如果有body需先setBody()
getDefaultMimeType(File file) 根据文件扩展名返回ContentType

八:小期待

以下项目都是我围绕远程控制写的项目和子项目。都给star一遍吧。😍

项目(Github) 语言 其他地址 运行环境 项目说明
RemoteDataControllerForWeb JavaScript 简书 浏览器 远程数据调试控制台Web端
RemoteDataControllerForAndroid Java 简书 Android设备 远程数据调试Android端
RemoteDataControllerForServer Java 简书 运行Java的设备 远程数据调试Server端
MiniHttpClient Java 简书 运行Java的设备 精简的HttpClient
MiniHttpServer Java 简书 运行Java的设备 支持部分Http协议的Server
MiniTCPClient Java 简书 运行Java的设备 TCP长连接库,支持粘包拆包处理
PackageMessage Java 简书 运行Java的设备 TCP粘包与半包解决方案
ByteBuffer Java 简书 运行Java的设备 二进制处理工具类
DataTables.AltEditor JavaScript 简书 浏览器 Web端表格编辑组件

我的小站:IT狗窝
技术联系QQ:1264957104

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容