图书预定系统ssm

Ajax传参到后台 400 Bad Request如何解决

此问题解决了花了半天。特此记录一下

jsp页面发送ajax请求,返回请求错误信息400.

我把出错原因定位在,ajax所传的参数非法上。后台springmvc的控制器识别不了,导致提示错的请求400

用了很多办法,改写参数,都还是报原来错误

data : JSON.stringify({json数据})  //1)尝试用转换

var param = {json格式数据};

data : param //2)尝试用变量方式

Java  Springmvc controller代码。接收请求

//ajax json
	@RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {
			"application/json; charset=utf-8" })
	@ResponseBody
	private Result<AppointExecution> appoint(@PathVariable("bookId") Long bookId, @RequestParam("studentId") Long studentId) {
		if (studentId == null || studentId.equals("")) {
			return new Result<>(false, "学号不能为空");
		}
.........
}

 JSP ajax 请求

function requestByJson(bid) {
		//alert(bid);
		var stid=12345678911;
		var p = {'studentId':stid};
		$.ajax({
			type : 'post',
			url : "${pageContext.request.contextPath }/book/"+bid+"/appoint",
			//设置contentType类型为json
			contentType : 'application/json;charset=utf-8',
			//json数据
			data: {'studentId':stid},
			dataType: "json",
			//请求成功后的回调函数
			success : function(data) {
				alert(data);
			}
		});
	}

 json格式的参数是没写错的。 但就是请求错误。controller打断点,请求也没进去。

查到一个问题分析和解决办法,原回答如下:

400的错误表示,是请求参数错误。我们关注点就在请求参数那里。你ajax请求过去的参数是json格式的,springmvc接收的时候是想用key-value方式来接收,这样就出了问题。最简单的修改方式就是,去掉contentType的设置,使用默认contentType,参数这样子传:data:"longInstCode=" + longInstCode

我把 contentType : 'application/json;charset=utf-8', 注释掉。 参数格式还是json没改。

经测试总算跑通了。

但问题来了,参数格式没变,contentType也是说明前台传参类型为json。为什么报错呢。

查看官方文档说明,原文如下:

contentType (default:  'application/x-www-form-urlencoded; charset=UTF-8')
Type:  Boolean or  String
When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases. If you explicitly pass in a content-type to  $.ajax(), then it is always sent to the server (even if no data is sent). As of jQuery 1.6 you can pass  false to tell jQuery to not set any content type header.  Note: The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding.  Note: For cross-domain requests, setting the content type to anything other than  application/x-www-form-urlencodedmultipart/form-data, or  text/plain will trigger the browser to send a preflight OPTIONS request to the server.
还是不大理解。
preflight OPTIONS request
Tomcat的HttpServletRequest类的实现类为org.apache.catalina.connector.Request(实际上是org.apache.coyote.Request),而它对处理请求参数的方法为protected void parseParameters(),这个方法中对Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)的处理代码如下:
protectedvoid parseParameters() {  
           //省略部分代码......  
           parameters.handleQueryParameters();// 这里是处理url中的参数  
           //省略部分代码......  
           if ("multipart/form-data".equals(contentType)) { // 这里是处理文件上传请求  
                parseParts();  
                success = true;  
                return;  
           }  
   
           if(!("application/x-www-form-urlencoded".equals(contentType))) {// 这里如果是非POST请求直接返回,不再进行处理  
                success = true;  
                return;  
           }  
           //下面的代码才是处理POST请求参数  
           //省略部分代码......  
           try {  
                if (readPostBody(formData, len)!= len) { // 读取请求体数据  
                    return;  
                }  
           } catch (IOException e) {  
                // Client disconnect  
                if(context.getLogger().isDebugEnabled()) {  
                    context.getLogger().debug(  
                            sm.getString("coyoteRequest.parseParameters"),e);  
                }  
                return;  
           }  
           parameters.processParameters(formData, 0, len); // 处理POST请求参数,把它放到requestparameter map中(即request.getParameterMap获取到的Map,request.getParameter(name)也是从这个Map中获取的)  
           // 省略部分代码......  
}  
   
   protected int readPostBody(byte body[], int len)  
       throws IOException {  
   
       int offset = 0;  
       do {  
           int inputLen = getStream().read(body, offset, len - offset);  
           if (inputLen <= 0) {  
                return offset;  
           }  
           offset += inputLen;  
       } while ((len - offset) > 0);  
       return len;  
    }  
 
 
从上面代码可以看出,Content-Type不是application/x-www-form-urlencoded的POST请求是不会读取请求体数据和进行相应的参数处理的,即不会解析表单数据来放到request parameter map中。所以通过request.getParameter(name)是获取不到的。
 
 
 
 
 

猜你喜欢

转载自yhzhangdota.iteye.com/blog/2382844
今日推荐