android界的spring-boot http服務框架

570622566發表於2017-12-14

雖然標題是有點浮誇,但的確實現了部分功能

有時候要用android當伺服器去進行資料傳輸,如區域網的檔案傳輸功能,這些用http服務去做是比較好的選擇. 既然要用到http服務,那使用NanoHttpd是最好的選擇之一,只有一個檔案但可以完成很多http服務的功能. 但使用NanoHttpd的時候會有很多的不便,例如我們每次都要對uri進行分析,這樣就使得程式碼臃腫,請求的方法過多的話,那看上去就會一臉懵,大大的降低程式碼可讀性.

對於使用NanoHttpd的各種不便,然後就二次封裝了下,就出了我個人認為是android界的spring-boot的http服務框架(有點傻的想法).

DEMO程式碼

程式碼編寫風格

android界的spring-boot http服務框架

get請求返回html資料

android界的spring-boot http服務框架
以物件返回

android界的spring-boot http服務框架
android界的spring-boot http服務框架
請求時傳人json資料

是不是有點像spring的風格,程式碼瞬間就簡潔了.整個人瞬間愉悅起來.

框架原理

是根據NanoHttpd二次開發,主要使用了註解反射來實現url的對映,程式碼也不多,輕量級,以下是關鍵程式碼

    /**
     * 解析註解檔案
     *
     * @param session
     * @param file_name
     * @return
     */
    private Response responseData(IHTTPSession session, String file_name) {
        Response response;
        Object[] objects = null;
        try {
            Map<String, java.lang.reflect.Method> methods = FHttpManager.getFHttpManager().getMethods();
            java.lang.reflect.Method method = methods.get(file_name);
            if (method != null) {
                method.setAccessible(true); //允許修改反射屬性
                Class cla = method.getDeclaringClass();//獲取該方法所在的類
                Object obj = cla.newInstance();//例項化類
                Class<?>[] parameterTypes = method.getParameterTypes(); //獲得方法所有引數的型別
                if (parameterTypes.length > 0) {
                    objects = new Object[parameterTypes.length];
                    Map<String, String> sessionMap = session.getParms();//獲取請求引數
                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();//獲取方法引數裡的註解
                    for (int i = 0; i < parameterAnnotations.length; i++) {
                        if (parameterTypes[i] == IHTTPSession.class) {
                            objects[i] = session;
                        } else if (parameterTypes[i] == Map.class) {
                            objects[i] = sessionMap;
                        } else {
                            Annotation parameterAnnotation = parameterAnnotations[i][0];//獲取引數中的第一個註解。所以每個引數只能只有一個註解
                            if (parameterAnnotation.annotationType() == RequestBody.class) {//返回物件
                                byte[] buf = new byte[(int) ((HTTPSession) session).getBodySize()];
                                session.getInputStream().read(buf, 0, buf.length);
                                objects[i] = new Gson().fromJson(new String(buf), parameterTypes[I]);
                            } else if (parameterAnnotation.annotationType() == RequestParam.class) {//返回指定param
                                objects[i] = dataConversion(parameterTypes[i], sessionMap, (RequestParam) parameterAnnotation);
                            }
                        }
                    }
                }
                response = responseBody(method.getReturnType(), method.invoke(obj, objects), method.isAnnotationPresent(ResponseBody.class));
            } else {
                response = newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, file_name + " Not Found");
            }
        } catch (Exception e) {
            response = newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, e.getMessage());
        }
        return response;
    }
複製程式碼

框架功能及使用

1. 框架功能介紹

這是根據NanoHttpd二次開發的一個輕量級,使用簡單,功能比較強大的一個http服務框架. 可以實現:

  1. 支援get請求
  2. 支援post請求
  3. 支援檔案上傳
  4. 支援檔案下載
  5. 支援自定義埠號
  6. 支援自定義靜態資源目錄(預設assets的根目錄,也可以指定sd卡的自定義目錄)
  7. 支援靜態資原始檔過濾(由於指定的是assets根目錄,會有很多系統自帶的xml檔案,就做了這個)
  8. 支援註解的使用(這框架不用註解還真沒法用)
  9. 支援以物件來響應
  10. 支援請求以物件接收
  11. ... 基本滿足http服務的正常使用需求(硬是瞎編了那麼多功能...)

2.框架裡的幾個註解

註解 含義
@RequestBody 方法裡的屬性註解,使用該註解可指定以物件返回 主要用於處理json請求
@RequestParam("") 方法裡的屬性註解,使用該註解可指定param值返回 主要用於處理get,post的請求
@RequestMapping("") 方法註解, 使用該註解是對映url ,把url 指定到對應的方法中處理資料
@ResponseBody 方法註解,使用該方法可以物件返回經過處理吐出json資料返回給客戶端

以上註解的使用可看前面的圖片

3. 框架使用

  1. gradle新增
compile 'cn.hotapk:fhttpserver:0.2.0'
複製程式碼
  1. manifest新增許可權
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
複製程式碼
  1. 初始化
fHttpManager = FHttpManager.init(this, UserController.class);
fHttpManager.setPort(9999);
...
複製程式碼

UserController.class 是進行url對映的類, 可新增多個這樣的類

public class UserController {

    @RequestMapping("userls")
    public NanoHTTPD.Response getUserLs() {
        return setResponse("user列表");
    }

    @ResponseBody
    @RequestMapping("getuser")
    public UserBean getUser() {
        return new UserBean("admin", "admin");
    }
...
複製程式碼
  1. 開啟http服務
fHttpManager.startServer();
複製程式碼
  1. 檔案下載
   NanoHTTPD.Response response = NanoHTTPD.newChunkedResponse(NanoHTTPD.Response.Status.OK, "application/octet-stream", inputStream);//這代表任意的二進位制資料傳輸。

   response.addHeader("Accept-Ranges", "bytes");

   response.addHeader("Content-Disposition", "attachment; filename="+"test.java")//可以這裡返回檔名稱

複製程式碼
  1. 檔案上傳
   /**
       * 檔案上傳
       *
       * @param session
       * @param fileDir 儲存檔案的目錄
       * @param parm    上傳檔案的引數
       * @return
       */
      public static boolean uploadFile(NanoHTTPD.IHTTPSession session, String fileDir, String parm) {
          Map<String, String> files = new HashMap<>();
          try {
              session.parseBody(files);
              Map<String, String> parms = session.getParms();
              return FFileUtils.copyFileTo(files.get(parm), fileDir + "/" + parms.get(parm));
          } catch (IOException e) {
              e.printStackTrace();
          } catch (NanoHTTPD.ResponseException e) {
              e.printStackTrace();
          }
          return false;
      }

複製程式碼
  1. index.html 檔案衝突

該框架預設開啟index.html檔案,如果不希望用這檔名可如下修改

fHttpManager.setIndexName(" ")
複製程式碼
  1. 瀏覽器開啟

預設使用8080埠,瀏覽器訪問http://xxx.xx.xx.xx:8080 即可

4. 框架使用demo

這塊就不出詳細demo了 可以到我另外一個專案檢視 這是一個android除錯資料庫的神器

5.框架程式碼講解

這方面就不講了,主要使用註解反射實現,其它也沒什麼的了

6.框架名稱

FHttpServer

以上是FHttpServer框架的全部內容,謝謝觀看,歡迎使用. 同時希望各位在使用中遇到什麼問題或建議可以用以下聯絡方式進行反饋

android開發討論群 320120776

個人部落格

github地址(感興趣的話,不妨點贊支援下)

相關文章