最近在重写一个项目时遇到了许多奇葩问题,这个项目是一个简单的web后台项目,基本上全都是增删改查数据库的操作。这里面遇到几个用spring接收前端post请求的接口。
基本情况是post请求有四种data参数格式,这些基础知识在我另一片博文中提到过这里就不废话了。主要是因为前端有两个地方用到了这个接口,但是在用这个接口的时候两个地方用法都不同,奇葩的c++居然还都解析成功了(其实因为c++没有对请求参数格式和数据做检查所以一直没有问题)。
一个地方是发送的是application/json格式,发送了一个jsonArray数据(数据例子["abc", "bcd"])这个是没有问题的正确使用方式。(下面简称前者)
另一个地方是发送的application/x-www-form-urlencode格式,发送的也是一个jsonArray数据。(下面简称后者)
前者解析方式比较简单
@RequestMapping(value = "/check_apps_version",
method = RequestMethod.POST,
produces = {"application/json;charset=UTF-8"},
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public BaseResponse<List<AppListItem>> checkAppsVersion(ReqCheckAppsVersion requstParam,
@RequestBody List<String> apps) {
return new BaseResponse<>();
}
后者这个发送方式在spring用@RequestBody解析时就很怪异,但是前段是手机APP已经发布出去了没法修改,只能后端来修改满足这个奇怪的需求
通过调试发现后者前端的接口传过来的参数是"["abc","def"]="这样子的,本身x-www-form-urlencode是多个kev-value对
的数据格式,所以现在没有value只有key了,只能通过字符串处理来解决了。
@RequestMapping(value = "/check_apps_version",
method = RequestMethod.POST,
produces = {"application/json;charset=UTF-8"},
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public BaseResponse<List<AppListItem>> checkAppsVersionParams(HttpServletRequest request,
ReqCheckAppsVersion requstParam,
@RequestBody String apps) {
String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
return BaseResponse.success();
}
两种方式,一种是通过@RequestBody把post data解析成string格式,另一种是通过HttpServletRequest解析出整个原始post data。然后做字符串处理。
但是在做做这个测试时候我们想了一下会不会有只有value没有key的情况,也就是这样"=["abc","def"]"。
测试结果是用tomcat没法从HttpServletRequest到这个post data,但是用jetty可以从HttpServletRequest解析到post data。
这个可能是tomcat和jetty的区别吧,还没有弄清楚什么原因。但是我们的问题总算是解决了,最大感触就是前人挖坑后人埋啊。
希望以后能注意一下代码健壮性的问题,避免给别人或者自己挖坑。