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