场景:
通常会遇到写接口时仅需要传入单个参数的情况,但是spring自带的参数解析器不支持解析这种传参,导致接收到的参数始终为null。
解决方案:
1、使用JSONObject与@RequestBody注解配合接收参数;
@PostMapping("/getSingleParam")
public void getSingleParam(@RequestBody JSONObject object){
System.out.println(object.getString("name"));
}
2、使用Map与@RequestBody注解配合接收参数;
@PostMapping("/getSingleParam")
public void getSingleParam(@RequestBody Map<String, Object> map){
System.out.println(map.get("name").toString());
}
3、以json字符串形式接收参数再通过JSONObject将json字符串转为对象,与方案1类似;
@PostMapping("/getSingleParam")
public void getSingleParam(@RequestBody String name){
JSONObject object = JSONObject.parseObject(name);
System.out.println(object.getString("name"));
}
最佳解决方案:
4、模仿@RequestParam自定义@RequestSingleParam注解来解析参数,@RequestParam从请求路径获取参数,自定义注解从request body中获取参数;
第一步:自定义@RequestSingleParam注解
package com.blog.utils.aop;
import org.springframework.web.bind.annotation.ValueConstants;
import java.lang.annotation.*;
/**
* 自定义注解接收单个参数
* @author created by wutong li on 2021/04/29
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestSingleParam {
String value();
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
第二步:实现HandlerMethodArgumentResolver接口,配置参数解析器
package com.blog.utils.aop;
import com.alibaba.fastjson.JSONObject;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
/**
* RequestStringParam参数解析器 实现 HandlerMethodArgumentResolver 接口
* @author created by wutong li on 2021/04/29
*/
public class RequestStringParamHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestSingleParam.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
RequestSingleParam requestSingleParam = parameter.getParameterAnnotation(RequestSingleParam.class);
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
char[] buf = new char[1024];
int rd;
while ((rd = reader.read(buf)) != -1) {
sb.append(buf, 0, rd);
}
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
String value = requestSingleParam.value();
return jsonObject.get(value);
}
}
第三步:配置WebMvcConfigurer注册自定义的参数解析器
package com.blog.config;
import com.blog.utils.aop.RequestStringParamHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* 配置WebMvcConfigurer
* @author created by wutong li on 2021/04/29
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 注册自定义的参数解析器
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers){
argumentResolvers.add(new RequestStringParamHandlerMethodArgumentResolver());
WebMvcConfigurer.super.addArgumentResolvers(argumentResolvers);
}
}
第四步:在Controller中接收参数处加上@RequestSingleParam注解,再调一下接口就可以接收到单个的入参了
@PostMapping("/getSingleParam")
public void getSingleParam(@RequestSingleParam(value = "name") String name){
System.out.println(name);
}