基于Springboot用axiospost请求接收字符串参数为null的解决方案 ...

打印 上一主题 下一主题

主题 865|帖子 865|积分 2595

问题

本日在用前端 post 请求后端时发现,由于是以 Json对象的形式传输的,后端用两个字符串形参无法获取到对应的参数值
前端代码如下:
  1. axios.post('http://localhost:8083/test/postParams',{a: '1', b:'2'} ,{
  2.         'Content-Type': 'application/json'
  3.     }).then(response => {
  4.       console.log(response.data);
  5.     })
  6.     .catch(error => {
  7.       console.error('There was an error!', error);
  8. });
复制代码
后端代码如下:
  1. @RequestMapping("/test")
  2. @RestController
  3. @Slf4j
  4. public class TestController {
  5.     @PostMapping("/postParams")
  6.     public void postParams(String a, String b) {
  7.         log.info(String.valueOf(a));
  8.         log.info(b);
  9.     }
  10. }
复制代码

解决

在网上学习了一下,究其原因是Spring Boot 无法直接将 JSON 字符串转换为一个 String 变量, Spring Boot 必要通过相应的机制,将 JSON 字符串剖析成可用的 Java 对象或 Map,在学习了某位前辈的文章后,通过自定义注解的方式解决了问题:
​ 总的思路就是,getRequestBody()将请求的json对象字符串先缓存到cache中,然后将该字符串剖析成Json对象,在根据对应的方法形参的名字,将值注入进去。
自定义注解类

  1. /**
  2. * @author yamu
  3. * @version 1.0
  4. * @description: 接收前端传的 包装类数据 或 String 自定义注解
  5. * @date 2025/1/13 11:05
  6. */
  7. @Target(ElementType.PARAMETER)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface RequestJson {
  11.     //参数值(对应的键名)
  12.     String value() default "";
  13. }
复制代码
定义@RequestJson的方法形参剖析器

  1. /**
  2. * @author yamu
  3. * @version 1.0
  4. * @description: 自定义注解 RequestJson 方法形参解析器
  5. * @date 2025/1/13 11:07
  6. */
  7. @Component
  8. @Slf4j
  9. public class RequestJsonMethodArgumentResolver implements HandlerMethodArgumentResolver {
  10.     public static String cache = "";//缓存请求体
  11.     @Override
  12.     public boolean supportsParameter(MethodParameter parameter) {
  13.         return parameter.hasParameterAnnotation(RequestJson.class);
  14.     }
  15.     /**
  16.      * @description  String 参数注入
  17.      * @param: parameter
  18.      * @param: mavContainer
  19.      * @param: webRequest
  20.      * @param: binderFactory
  21.      * @returns Object
  22.      * @author yamu
  23.      * @date 2025/1/20 14:33
  24.      */
  25.     @Override
  26.     public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
  27.         RequestJson requestJson = parameter.getParameterAnnotation(RequestJson.class);
  28.         HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
  29.         //未指定映射的键时,默认值为形参名
  30.         String value = requestJson.value();
  31.         if (value.isEmpty()) {
  32.             value = parameter.getParameterName();
  33.         }
  34.         JSONObject jsonObject = getRequestBody(request);
  35.         //遍历完最后一个参数,则清理缓存
  36.         if (parameter.getMethod().getParameterCount() - 1 <= parameter.getParameterIndex()) {
  37.             cache = "";
  38.         }
  39.         //请求的参数为空,直接返回null
  40.         if (jsonObject == null) {
  41.             return null;
  42.         }
  43.         return jsonObject.get(value);
  44.     }
  45.     /**
  46.      * 获取参数列表
  47.      * @param request
  48.      * @return
  49.      */
  50.     private JSONObject getRequestBody(HttpServletRequest request) {
  51.         //cache不为空
  52.         if (!cache.isEmpty()) {
  53.             return JSONObject.parseObject(cache);
  54.         }
  55.         //字符串拼接成Json字符串
  56.         StringBuilder sb = new StringBuilder();
  57.         try {
  58.             BufferedReader reader = request.getReader();
  59.             char[] buf = new char[1024];
  60.             int rd;
  61.             while ((rd = reader.read(buf)) != -1) {
  62.                 sb.append(buf, 0, rd);
  63.             }
  64.         } catch (IOException ex) {
  65.             log.error(ex.getMessage());
  66.         }
  67.         cache = sb.toString();
  68.         return JSONObject.parseObject(sb.toString());
  69.     }
  70. }
复制代码
在WebConfig里注册剖析器

  1. @Configuration
  2. @Slf4j
  3. public class WebConfig extends WebMvcConfigurationSupport  {
  4.     @Autowired
  5.     private RequestJsonMethodArgumentResolver requestJsonMethodArgumentResolver;
  6.     /**
  7.      * @description 配置方法解析器
  8.      * @param: argumentResolvers
  9.      * @returns void
  10.      * @author yamu
  11.      * @date 2025/1/23 16:00
  12.      */
  13.     @Override
  14.     public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
  15.         argumentResolvers.add(requestJsonMethodArgumentResolver);
  16.     }
  17. }
复制代码
在方法形参上加上注解

  1. @RequestMapping("/test")
  2. @RestController
  3. @Slf4j
  4. public class TestController {
  5.     @PostMapping("/postParams")
  6.     public void postParams(@RequestJson String a, @RequestJson String b) {
  7.         log.info(a);
  8.         log.info(b);
  9.     }
  10. }
复制代码

上述方式存在几个问题:

  • 由于要缓存请求的 Json字符串,所以在每次请求完之后要清除cache,上述方法是在方法形参的最后一个并且加了@RequestJson注解的参数才可以清理
  • 由于必要对每个参数举行赋值,所以必要对每个要注入的参数都要加上@RequestJson注解
  • 处置惩罚包装类或字符串类时,形参类型必要强同等(不能用Stringl类型接收一个Integer的参数值),同时也无法处置惩罚复杂的对象类型
后续在渐渐的深入学习后我会优化上述方式。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表