-
事情发生在昨天在和移动端交互的时候,突然移动端的大佬过来说,哎,你这个接口用不了,咋整,我好像拿不到数据,我说,不会吧,这些接口我都用postman·模拟通过了,你看不是能访问吗?说着我便翻出我postman的历史记录给他看,确实是可以访问的,然而他那边也确实收不到数据,不是我这边收不到他给我的数据,所有没法返回给他有效数据。
-
于是我花了点时间研究了一下
猜测我接不到数据的原因:
跨域访问,需要开启跨域访问
数据格式错误导致数据有但无法有效封装
- 其中数据格式错误分为移动端传输的错误,和后端的接收错误
对于跨域访问问题,我能想到也是靠学长提醒(事实上并不是这个问题)
- 由于之前在做地图实时更新点位的项目时,涉及到了AJAX 不能跨域访问的问题,所以经过学长的提醒我认为可能存在这种情况,于是我便做了尝试:
- 经过一番了解spring boot要开启跨域只需要在controller中的某个方法上加上 @CrossOrigin注解,该方法便,可以跨域访问。
- 但很遗憾最终不是这个原因。
第二种数据格式问题
- 由于我此前并没有过多接触过移动端的内容(倒是玩了几天flutter,也没深入),因此我要到了代码也看不出个所以然,于是我决定在Web端做一次尝试:
- 昨天大佬跟我解释说穿得是form表单,于是我在Web端模拟了一下
<script type="application/javascript">
function ajaxTest() {
alert($("#commentId").val())
$.ajax({
url:"http://192.168.43.158:8082/comment/likeOrDelete2",
datatype:"json",
data:{commentId:+$("#commentId").val(),status:$("status").val()},
type:"post",
headers : {
'Content-Type' : 'application/json;charset=utf-8'
},
error:function (data) {
alert("出错了!!"+data.msg);
},
success:function (data) {
$("result").html(data.msg);
}
});
}
</script>
</body>
<form action="http://192.168.43.158:8082/comment/likeOrDelete2" method="post" id="Form">
_commentId: <br><input type="text" name="commentId" id="commentId"/>
<br>
_status:<br> <input type="text" name="status" id="status"/><br>
<input type="submit" name="喜欢" onclick="ajaxTest()"/>
</form>
-
这段前端代码主要是用AJAX发一个Post请求带上一个表单,如下所示:
请原谅我的菜逼布局.png
提交结果是:
415错误.png
postman上的测试
- 事实上这在意料之中(哭),好吧,发现了自己无意间挖的一个坑
- 而原先我在postman上测试的结果是这样的:
- 发现好像数据格式不是一致的,并不是form表单
于是我换了form-data格式的试了一下
不幸命中.png- (哭)这锅哭着也得背
- 我有仔细琢磨琢磨controller中的代码
@PostMapping(value="/comment/likeOrDelete2")
public HashMap likeOrDelete2(@RequestBody HashMap<Object,Object> map) {
UserComment userComment = userCommentService.getUserCommentFromMap(map);
HashMap result = userCommentService.updateUser(userComment);
return result;
}
- 这段代码看起来还算比较标准(除了命名),能拦截请求(有打印log),但不能接收数据,于是我把注意力转到@RequestBody这个注解上,隐约记得@RequestParam好像也能接值(基础没打好的痛)
经过查证:
@RequestBody与@RequestParam
- @RequestBody接受的是一个json对象的字符串,而不是Json对象,在ajax请求时往往都是Json对象,用JSON.stringify(data)的方式就能将对象变成json字符串。@RequestBody接收的是一个字符串,返回的参数可以是一个Map对象。
- @RequestParam 底层是通过request.getParameter方式获得参数的,也就是说,@RequestParam 和request.getParameter是同一回事。因为使用request.getParameter()方式获取参数,可以处理get 方式中queryString的值,也可以处理post方式中 body data的值,所以,@RequestParam可以处理get 方式中queryString的值,也可以处理post方式中 body data的值。@RequestParam用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST。
案件告破
- 又又又是注解惹的祸(流下了没有技术的泪水),之前我用postman验证的时候采用的格式是JSON(application/json)也就是Json字符串,这个用@RequestBody正好可以,而表单则需要@RequestParam接收,为了验证于是我叫大佬写一个传字符串的,成功。。。。
- 背锅侠开始苦逼的填坑之路~~~
扩展
另外关于x-www-form-urlencoded
- 如果Content-Type设置为“application/x-www-form-urlencoded;charset=UTF-8”无论是POST请求还是GET请求都是可以通过这种方式成功获取参数,但是如果前端POST请求中的body是Json对象的话,会报上述错误。
application/json和text/json- 请求中传JSON时设置的Content-Type 如果是application/json或者text/json时,JAVA中request.getParameter("")怎么也接收不到数据。这是因为,Tomcat的HttpServletRequest类的实现类为org.apache.catalina.connector.Request(实际上是org.apache.coyote.Request)。
网友评论