SpringMVC先後端參數交互

Controller中使用JSON方式有多種

關鍵在於ajax請求是將數據以什麼形式傳遞到後臺

HTTP請求中:前端

  • 若是是get請求,那麼表單參數以name=value&name1=value1的形式附到url的後面(QueryString Parameters),
  • 若是是post請求,那麼表單參數是在請求體中,也是以name=value&name1=value1的形式在請求體中(Form Data)

前端經常使用參數提交方式:jquery

  1. POST + JSON字符串形式
  2. POST + JSON對象形式
  3. GET + 參數字符串

方式一: POST + JSON字符串形式,以下:ajax

//前端 

var data = {  
    userAccount: lock_username,  
    userPasswd:md5(lock_password).toUpperCase()  
}  
   
$.ajax({  
    url : ctx + "/unlock.do",  
    type : "POST",  
    data : JSON.stringify(data), //轉JSON字符串  
    dataType: 'json',  
    contentType:'application/json;charset=UTF-8', //contentType很重要     
    success : function(result) {  
        console.log(result);  
    }  
});
 
注意
1.json數據必須用JSON.stringify()方法轉換成字符串
2.contentType不能省略



//後端

@RequestMapping(value = "unlock.do",method = RequestMethod.POST)
@ResponseBody
public Msg methodName(@RequestBody User user) {
    logger.info("user:"+user);
    return Msg.success();
}

注意
@RequestBody不能夠省略,若是不加的話spring mvc後臺沒法接受data參數

@RequestParam 、@RequestBody 說明

@RequestParam用來處理ContentType: 爲 application/x-www-form-urlencoded編碼的內容

@RequestBody該註解經常使用來處理Content-Type: 不是application/x-www-form-urlencoded編碼的內容,例如application/json, application/xml等

@RequestBody接收的是一個Json對象的字符串,而不是一個Json對象。在ajax請求每每傳的都是Json對象,用 JSON.stringify(data)的方式就能將對象變成字符串。

參考資料: https://blog.csdn.net/HelloWorld20151118/article/details/77104047spring

方式二: POST + JSON對象形式,以下:apache

//請求數據,登陸帳號 +密碼  
ar data = {  
     userAccount: lock_username,  
     userPasswd:md5(lock_password).toUpperCase()  
}  
  
$.ajax({  
    url : ctx + "/unlock.do",  
    type : "POST",  
    data : data, //直接用JSON對象
    contentType : "application/x-www-form-urlencoded",
    dataType: 'json',  
    success : function(result) {  
        console.log(result);  
    }  
});  

 

說明:json

  • 若是使用原生AJAX POST請求時,須要明確設置Request Header xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 由於原生AJAX默認使用的Content-Type是text/plain;charset=UTF-8,參數請求體在(Request Payload)中後端

    https://blog.csdn.net/mhmyqn/article/details/25561535tomcat

  • 若是使用jquery的$.ajax post請求是不須要明確設置 "contentType" 這個請求頭,默認已經設置。服務器

    http://www.w3school.com.cn/jquery/ajax_post.aspmvc

tomcat容器會對以下兩種格式數據特殊處理:

  1. 表單提交且Content-Type爲application/x-www-form-urlencoded,由於表單提交數據是鍵值對的方式;
  2. 文件上傳作特殊處理;

tomcat容器對於Content-Type不是application/x-www-form-urlencoded的數據只能經過獲取原始數據流的方式來進行解析,由於請求數據格式不固定,不必定是鍵值對的方式,因此服務器沒法知道具體的處理方式;那麼這樣提交的參數咱們該怎麼獲取呢?固然是使用最原始的方式,讀取輸入流來獲取了(參考:FastJsonHttpMessageConverter),原始方式固然也能夠接收Content-Type是application/x-www-form-urlencoded得POST請求數據

類名:org.apache.catalina.connector.Request

protected void parseParameters() {
    this.parametersParsed = true;
    Parameters parameters = this.coyoteRequest.getParameters();
    boolean success = false;

    try {
        parameters.setLimit(this.getConnector().getMaxParameterCount());
        String enc = this.getCharacterEncoding();
        boolean useBodyEncodingForURI = this.connector.getUseBodyEncodingForURI();
        if(enc != null) {
            parameters.setEncoding(enc);
            if(useBodyEncodingForURI) {
                parameters.setQueryStringEncoding(enc);
            }
        } else {
            parameters.setEncoding("ISO-8859-1");
            if(useBodyEncodingForURI) {
                parameters.setQueryStringEncoding("ISO-8859-1");
            }
        }

        parameters.handleQueryParameters();
        if(this.usingInputStream || this.usingReader) {
            success = true;
            return;
        }

        if(!this.getConnector().isParseBodyMethod(this.getMethod())) {
            success = true;
            return;
        }

        String contentType = this.getContentType();
        if(contentType == null) {
            contentType = "";
        }

        int semicolon = contentType.indexOf(59);
        if(semicolon >= 0) {
            contentType = contentType.substring(0, semicolon).trim();
        } else {
            contentType = contentType.trim();
        }
        // 這裏是處理文件上傳請求  
        if("multipart/form-data".equals(contentType)) {
            this.parseParts(false);
            success = true;
            return;
        }
        // 這裏若是contentType是非application/x-www-form-urlencoded請求直接返回,再也不進行處理。
        // 從上面代碼能夠看出,Content-Type==不是application/x-www-form-urlencoded==的POST請求是不會讀取請求體數據和進行相應的參數處理的,即不會解析表單數據來放到request parameter map中。因此經過request.getParameter(name)是獲取不到的。
        if(!"application/x-www-form-urlencoded".equals(contentType)) {
            success = true;
            return;
        }

        int len = this.getContentLength();
        if(len <= 0) {
            if("chunked".equalsIgnoreCase(this.coyoteRequest.getHeader("transfer-encoding"))) {
                Object formData1 = null;

                Context context;
                byte[] formData2;
                try {
                    formData2 = this.readChunkedPostBody();
                } catch (IllegalStateException var17) {
                    parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
                    context = this.getContext();
                    if(context != null && context.getLogger().isDebugEnabled()) {
                        context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var17);
                    }

                    return;
                } catch (IOException var18) {
                    parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
                    context = this.getContext();
                    if(context != null && context.getLogger().isDebugEnabled()) {
                        context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var18);
                    }

                    return;
                }

                if(formData2 != null) {
                    parameters.processParameters(formData2, 0, formData2.length);
                }
            }
        } else {
            int formData = this.connector.getMaxPostSize();
            Context e;
            if(formData >= 0 && len > formData) {
                e = this.getContext();
                if(e != null && e.getLogger().isDebugEnabled()) {
                    e.getLogger().debug(sm.getString("coyoteRequest.postTooLarge"));
                }

                this.checkSwallowInput();
                parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
                return;
            }

            e = null;
            byte[] e1;
            if(len < 8192) {
                if(this.postData == null) {
                    this.postData = new byte[8192];
                }

                e1 = this.postData;
            } else {
                e1 = new byte[len];
            }

            try {
                if(this.readPostBody(e1, len) != len) {
                    parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE);
                    return;
                }
            } catch (IOException var19) {
                Context context1 = this.getContext();
                if(context1 != null && context1.getLogger().isDebugEnabled()) {
                    context1.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), var19);
                }

                parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
                return;
            }
            // 處理POST請求參數,把它放到requestparameter map中(即request.getParameterMap獲取到的Map,request.getParameter(name)也是從這個Map中獲取的)
            parameters.processParameters(e1, 0, len);
        }

        success = true;
    } finally {
        if(!success) {
            parameters.setParseFailedReason(FailReason.UNKNOWN);
        }

    }

}
protected int readPostBody(byte[] body, int len) throws IOException {
    int offset = 0;

    do {
        int inputLen = this.getStream().read(body, offset, len - offset);
        if(inputLen <= 0) {
            return offset;
        }

        offset += inputLen;
    } while(len - offset > 0);

    return len;
}   


類:com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter

@Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage ) throws IOException, HttpMessageNotReadableException {
    return readType(getType(clazz, null), inputMessage);
}

private Object readType(Type type, HttpInputMessage inputMessage) throws IOException {
    try {
        InputStream in = inputMessage.getBody();
        return JSON.parseObject(in, fastJsonConfig.getCharset(), type, fastJsonConfig.getFeatures());
    } catch (JSONException ex) {
        throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);
    } catch (IOException ex) {
        throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
    }
}


原始方式接收數據,本身開發:

private String getRequestPayload(HttpServletRequest req) {  
    StringBuildersb = new StringBuilder();  
    try(BufferedReaderreader = req.getReader();) {  
       char[]buff = new char[1024];  
       intlen;  
       while((len = reader.read(buff)) != -1) {  
                sb.append(buff,0, len);  
       }  
    }catch (IOException e) {  
       e.printStackTrace();  
    }  
    returnsb.toString();  
} 

方式三: GET + 參數字符串請求

$.ajax({  
    url : ctx + "/unlock.do",  
    type : "GET",  
    dataType: "text",   
    data : "userAccount="+lock_username+"&userPasswd=" + hex_md5(lock_password).toUpperCase(),//等價於URL後面拼接參數  
    success : function(result) {  
        console.log(result);  
    }  
}); 

或者

ar data = {  
     userAccount: lock_username,  
     userPasswd:md5(lock_password).toUpperCase()  
}  
$.ajax({  
    url : ctx + "/unlock.do",  
    type : "GET",  
    dataType: "text",   
    data : data,//等價於URL後面拼接參數  
    success : function(result) {  
        console.log(result);  
    }  
});

jquery:GET方式(選項processData:true狀況下) data請求中將附加在 URL 後 

 

相關文章
相關標籤/搜索