1. 程式人生 > >SpringMVC獲得請求引數值的幾種方法

SpringMVC獲得請求引數值的幾種方法

    有不少同事在工作過程中,會遇到分不清如何獲得請求引數值的情況,明明自己測試過的介面是可以獲得引數的值的,而給第三方呼叫的時候就不可以,這些情況不甚列舉。下面博主就給大家詳細介紹SpringMVC獲得請求引數獲取的幾種方法。

 

首先介紹幾種常見的Request請求方式

首先介紹幾種常見的Request請求方式,以PostMan發起請求為例

  •   get方法:最為簡單,既將引數新增到請求URL當中,如:http://localhost:8080/demo/web/getrequestvalue/addUserByBeanUseRequestBody?age=10&name=yun
  •   post(Content-Type: application/x-www-form-urlencoded):瀏覽器的原生 form 表單,如果不設定 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交資料。請求類似於下面這樣(略掉無關的請求頭):
          POST http://www.example.com HTTP/1.1
          Content-Type: application/x-www-form-urlencoded;charset=utf-8
          title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

     

  •   post(Content-Type: multipart/form-data):使用表單上傳檔案時,必須讓 form 的 enctyped 等於這個值。用於上傳檔案與KeyValue共同存在的請求。
  •   post(Content-Type: application/json):現在越來越多的人把它作為請求頭,用來告訴服務端訊息主體是序列化後的 JSON 字串。使用最為廣泛。

 

通過HttpServletRequest接收

最原始的方法,在業務程式碼開發中,不推薦使用,無法到達高效開發的目的。

    /**
     * 最原始的方法,在業務程式碼開發中,不推薦使用,無法到達高效開發的目的:</br>
     * 通過HttpServletRequest接收:
     *  get方式可以獲得引數的值
     *  post方式(Content-Type: application/x-www-form-urlencoded)可以獲得引數的值
     *  post方式(Content-Type: multipart/form-data)可以獲得引數的值
     *  post方式(Content-Type: application/json)無法獲得引數的值
     */
    @RequestMapping("/addUserByServletRequest")
    public ApiResponse addUserByServletRequest(HttpServletRequest request){
        User user = new User();
        user.setName(request.getParameter("name"));
        user.setAge(Integer.parseInt(request.getParameter("age")));
        log.debug(logSintring+user);
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

將請求Key作為介面入參方式

    /**
     * 將請求Key作為介面入參方式,也是較為傳統的方法,無法到達高效開發的目的:</br>
     *  get方式可以獲得引數的值
     *  post方式(Content-Type: application/x-www-form-urlencoded)可以獲得引數的值
     *  post方式(Content-Type: multipart/form-data)可以獲得引數的值
     *  post方式(Content-Type: application/json)無法獲得引數的值,報錯:"Optional int parameter '**' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type."
     */
    @RequestMapping("/addUserByKeyByKey")
    public ApiResponse addUserByKeyByKey(String name, int age){
        User user = new User();
        user.setName(name);
        user.setAge(age);
        log.debug(logSintring+user);
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

通過POJOBean作為RestApi介面的入參

    /**
     * 通過POJOBean作為RestApi介面的入參(SpringMVC做對映),此種方式在實際業務開發中較為實用:</br>
     *  get方式可以獲得引數的值
     *  post方式(Content-Type: application/x-www-form-urlencoded)可以獲得引數的值
     *  post方式(Content-Type: multipart/form-data)可以獲得引數的值
     *  post方式(Content-Type: application/json)無法獲得引數的值。這種方式必須使用@RequestBody註解在入參當中。
     */
    @RequestMapping("/addUserByBean")
    public ApiResponse addUserByBean(User user){
        log.debug(logSintring+user);
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

通過POJOBean前面加@RequestBody註解作為RestApi介面的入參

    /**
     * 通過POJOBean前面加@RequestBody註解作為RestApi介面的入參(SpringMVC做對映),此種方式在實際業務開發中較為實用,配合研發規範,可以達到較高效開發效率:</br>
     *  get方式不支援,報錯:Required request body is missing:
     *  post方式(Content-Type: application/x-www-form-urlencoded)不可以,報錯:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
     *  post方式(Content-Type: multipart/form-data)不可以,報錯:Content type 'multipart/form-data;boundary=----WebKitFormBoundaryQQDXKavdsLyPAphR;charset=UTF-8' not supported
     *  post方式(Content-Type: application/json)可以獲得引數的值
     */
    @RequestMapping("/addUserByBeanUseRequestBody")
    public ApiResponse addUserByBeanUseRequestBody(@RequestBody User user){
        log.debug(logSintring+user.toString());
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

通過@PathVariable註解獲得請求URL中的引數值

    /**
     * 通過@PathVariable註解獲得請求URL中的引數值,此種方式在實際業務開發中較為少見,此種情況符合Restful規範,但是使用不是很方便,尤其是在做介面自動化測試的時候,資料加密也比較困難,建議較少使用:</br>
     *  get方式支援,需要請求URL路徑中有這些資訊
     *  post方式:不管是哪種方式都不支援。 如果post請求的URL路徑符合PathVariable也是規則,也是可以獲得引數的
     */
    @RequestMapping("/addUserByPathValue/{useName}/{userAge}")
    public ApiResponse addUserByPathValue(@PathVariable String useName, @PathVariable("userAge") int age){
        User user = new User();
        user.setAge(age);
        user.setName(useName);
        log.debug(logSintring+user);
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

通過@RequestParam註解獲得請引數值

    /**
     * 通過@RequestParam註解獲得請引數值,此種方式在實際業務開發中使用較多,此種情況符合Restful規範,但是使用不是很方便,尤其是在做介面自動化測試的時候,資料加密也比較困難,建議較少使用:</br>
     *  get方式支援,需要請求URL路徑中有這些資訊
     *  post方式(Content-Type: application/x-www-form-urlencoded)可以。 但是 required = false, defaultValue = "99" 不起作用,即age必須要有此請求引數
     *  post方式(Content-Type: multipart/form-data) 可以。 但是 required = false, defaultValue = "99" 不起作用,即age必須要有此請求引數
     *  post方式(Content-Type: application/json) 不可以。
     */
    @RequestMapping("/addUserByRequestParam")
    public ApiResponse addUserByRequestParam(@RequestParam("name") String userName,
                                             @RequestParam(value = "age", required = false, defaultValue = "99") int userAge){
        User user = new User(userName,userAge);
        log.debug(logSintring+user);
        return new ApiResponse.ApiResponseBuilder().data(user).build();
    }

 

最佳實踐

如上有這麼多獲得請求引數值的方法,那麼在實際工作中,哪些最建議使用呢。 現在大家的開發模式都是前後端分離開發,所以使用“post方式(Content-Type: application/json)”作為Ajax最為常見,故Spring端使用“@RequestBody Bean”獲得請求引數值最為方便高效,使用頻率也最高。用此方式再配合"hibernate validate"工具,可以很方便的做引數校驗工作。 在一個人數較多的研發團隊中,使用此規範(雖然很多時間不符合Restful風格),可以讓團隊產生很高的研發效率,此種規範產生的介面文件,在給測試人員做介面自動化測試工作中,也會帶來很大的便捷性,不然不同的請求風格、不同的請求型別與或者引數的方法,將大大降低測試人員做介面自動化指令碼編寫的速度。本博文的示例程式碼見GitHub《https://github.com/yun19830206/JavaTechnicalSummary/blob/master/Rd_Standard/src/main/java/com/cloud/rdstandard/web/GetHttpRequestParamValueDemo.java