Mini Http Server for Java (Android)
MiniHttpServer
一:開發(fā)環(huán)境
Mac OS 10、Java 1.8、IDEA(Gradle工程)
二:介紹
一款基于Java Nio實(shí)現(xiàn)的Http解析框架,支持常見的請(qǐng)求解析和邏輯;采用單線程解析多線程業(yè)務(wù)處理方案,內(nèi)置線程池方便線程管理;支持靜態(tài)文件下載;支持表單參數(shù)和文件上傳,支持PUT文件上傳。解析成功后返回HttpRequest和HttpResponse。除常見的接口請(qǐng)求返回外,HttpResponse可以向客戶端發(fā)送跨域請(qǐng)求結(jié)果,也可以發(fā)送文件,支持區(qū)分附件模式。
三:特點(diǎn)
- 純Java API實(shí)現(xiàn),性能好
- 基于Java Nio,異步機(jī)制,相比傳統(tǒng)IO,有更高的性能。
- 體積小,代碼少,支持Http部分協(xié)議,滿足絕大部分需求。
- 支持POST表單數(shù)據(jù)和多文件上傳。
- 支持PUT上傳文件,自動(dòng)保存到file目錄。
- 支持發(fā)送文件到客戶端。
- 支持發(fā)送重定向等基本http協(xié)議內(nèi)容。
- 支持反饋跨域請(qǐng)求。
- 支持自定義header。
- Maven
<dependency>
<groupId>com.itgowo</groupId>
<artifactId>MiniHttpServer</artifactId>
<version>0.0.21</version>
<type>pom</type>
</dependency>
- Gradle
implementation 'com.itgowo:MiniHttpServer:0.0.21'
五:初始化(庫(kù)Jar中有Demo類,可以參考)
Demo.java
- 創(chuàng)建MiniHttpServer
MiniHttpServer 繼承自Thread,復(fù)寫了Thread.start()方法,與MiniHttpServer.startServer()方法作用相同,不會(huì)沖突。
MiniHttpServer miniHttpServer = new MiniHttpServer();
- 設(shè)置初始信息
public void init(boolean isBlocking, InetSocketAddress inetSocketAddress, String webDir, onHttpListener onHttpListener)
| 參數(shù) |
推薦值 |
說(shuō)明 |
| isBlocking |
false |
是否用阻塞模式,推薦false,Nio特點(diǎn)就是非阻塞 |
| inetSocketAddress |
InetSocketAddress(port) |
服務(wù)使用哪個(gè)端口 |
| webDir |
"/web" |
服務(wù)器靜態(tài)目錄,file和temp目錄會(huì)在webDir中 |
| onHttpListener |
new 實(shí)現(xiàn)類 |
服務(wù)器接收Http請(qǐng)求回調(diào),如果是文件則FileList中有文件信息 |
3.設(shè)置文件存儲(chǔ)策略
當(dāng)有文件上傳到服務(wù)器時(shí),默認(rèn)保存在webDir里的file目錄下,創(chuàng)建UUID命名的目錄,將上傳的文件放入其中,文件名已Http信息fileName命名,防止重名文件沖突。例 web/file/02e86423-d1bd-4218-8f70-a7c73c71bf62/test.png
默認(rèn)每次server初始化后執(zhí)行清理功能。需要手動(dòng)執(zhí)行使用這個(gè)方法miniHttpServer.getFileManager().cleanOldFile();
httpServer.setFileLimit(long fileSize, long fileLastTime);
| 參數(shù) |
推薦值 |
說(shuō)明 |
| fileSize |
1024 * 1024 * 500 |
file文件夾存儲(chǔ)閾值,超過(guò)執(zhí)行清理功能, |
| fileLastTime |
1000 * 60 * 60 * 24 * 7 |
最后編輯時(shí)間計(jì)算存儲(chǔ)時(shí)間,默認(rèn)保留7天內(nèi)文件 |
- 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,參數(shù)操作,來(lái)源一:url中"?"后面解析出來(lái)的參數(shù)鍵值對(duì);來(lái)源二:POST表單參數(shù)解析
Map<String, String> parms = httpRequest.getParms();
String userId = httpRequest.getParms().get("userId");
3. 客戶端GET請(qǐng)求資源
if (HttpMethod.GET == httpRequest.getMethod()) {
if (httpRequest.getUri().equalsIgnoreCase("/")) {
httpRequest.setUri("/index.html");
}
//緩存策略,瀏覽器指定時(shí)間內(nèi)只獲取一次文件,如果sendFile()包含cacheControl參數(shù),則不需要在設(shè)置,設(shè)置了以單獨(dú)設(shè)置為準(zhǔn)。沒有cacheControl的方法則默認(rèn)沒有此參數(shù)
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參數(shù)添加了不一定起作用,如果單獨(dú)加了header,則此方法參數(shù)無(wú)效
httpResponse.sendFile(httpNioServer.getFileManager().getFile(httpRequest.getUri()), HttpStatus.OK, 3600, true);
}
4. 客戶端POST請(qǐng)求,POST請(qǐng)求,常見的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請(qǐng)求,OPTIONS請(qǐng)求,跨域請(qǐng)求最多的是ajax發(fā)出的,應(yīng)對(duì)web請(qǐng)求
if (HttpMethod.OPTIONS == httpRequest.getMethod()) {
httpResponse.sendOptionsResult();
}
6. 客戶端PUT請(qǐng)求,跟POST表單上傳文件不同,Http中Body默認(rèn)為一個(gè)文件,臨時(shí)存在temp目錄,PUT如果需要傳遞文件名請(qǐng)?jiān)趆eaders中添加自定義數(shù)據(jù)。
if (HttpMethod.PUT == httpRequest.getMethod()) {
Map<String, File> fileMap = httpRequest.getFileList();
httpResponse.sendData(HttpStatus.OK);
}
7. 客戶端其他請(qǐng)求,HEAD、DELETE、TRACE、CONNECT、PATCH 等不常見,需要自己返回結(jié)果即可,無(wú)特殊需求。
8. 重定向
httpResponse.sendRedirect("http://www.baidu.com");
七:關(guān)鍵類
HttpRequest
| 變量 |
說(shuō)明 |
| socketChannel |
與客戶端連接通信的連接通道 |
| clientId |
與Nio中Channel綁定,連接唯一標(biāo)記 |
| method |
Http報(bào)文中的請(qǐng)求方式(GET/POST/PUT和DELETE等 |
| uri |
Http報(bào)文中Method后面的路徑,最開始以"/"開始 |
| protocolVersion |
Http協(xié)議版本 |
| queryParameterString |
url中"?"后面參數(shù)原始數(shù)據(jù) |
| parms |
來(lái)源一:url中"?"后面解析出來(lái)的參數(shù)鍵值對(duì);來(lái)源二:POST表單參數(shù)解析 |
| headers |
Http的header參數(shù),Key-Value形式 |
| remoteIp |
客戶端IP |
| contentLength |
body長(zhǎng)度 |
| multipart_formdata |
是否是表單數(shù)據(jù),如果為true,則需要檢查下是否有文件上傳,fileList |
| body |
PUT方式的Body會(huì)存到文件里,此處值為空,POST表單上傳文件,Body也為空,請(qǐng)檢查fileList |
| fileList |
PUT方式的Body會(huì)存到fileList中,POST表單上傳文件,Body也為空,也會(huì)存到fileList |
| 其他方法 |
說(shuō)明 |
| isApplicationJson() |
ContentType是不是Json類型 |
| containsFile(String key) |
fileList中是否包含該文件名的文件 |
| containsHeader(String key) |
headers中是否包含該參數(shù) |
addToFileList(String key, File file) |
添加文件到fileList,內(nèi)部方法 |
addFileList(Map<String, File> fileList) |
添加到fileList,內(nèi)部方法 |
| isGzip() |
是否啟用了Gzip,第一版不考慮加入此功能 |
| isKeepAlive() |
是否保持連接 |
| sendData(ByteBuffer byteBuffer) |
向客戶端發(fā)送消息,最原始方式,http協(xié)議格式請(qǐng)用HttpResponse |
HttpResponse
| 變量 |
說(shuō)明 |
| socketChannel |
與客戶端連接通信的連接通道 |
| httpRequest |
httpRequest對(duì)象 |
| status |
HttpStatus常量 |
| mimeType |
內(nèi)容類型ContentType |
| data |
返回客戶端數(shù)據(jù),ByteBuffer或其子類 |
| header |
返回客戶端Http的header信息 |
| keepAlive |
告訴客戶端是否維持連接 |
| 其他方法 |
說(shuō)明 |
| addHeader(String name, String value) |
添加返回客戶端Http的header信息 |
| sendOptionsResult() |
返回Options請(qǐng)求回答,默認(rèn)允許所有 |
| sendRedirect(String newUrl) |
讓客戶端重定向到新地址 |
| sendFile(File file, HttpStatus httpStatus, boolean autoHtmltoNotAttachment) |
向客戶端發(fā)送符合Http協(xié)議的文件,如果是html文件,則沒有attachment標(biāo)記,瀏覽器不按附件下載,按網(wǎng)頁(yè)打開 |
| sendData(HttpStatus status) |
向客戶端發(fā)送信息,如果有body需先setBody() |
| getDefaultMimeType(File file) |
根據(jù)文件擴(kuò)展名返回ContentType |
八:小期待
以下項(xiàng)目都是我圍繞遠(yuǎn)程控制寫的項(xiàng)目和子項(xiàng)目。都給star一遍吧。??
我的小站:IT狗窩
技術(shù)聯(lián)系QQ:1264957104