前端通过请求体传输json对象,后端无法直接转换成相应的数据类型,这时候需要单独处理这种情况
处理的逻辑是:
- 编写标记,用于在方法上获取字段名称,并且只处理添加标记的方法;
@Retention(RetentionPolicy.RUNTIME)
public @interfce CustomSignleParams{
/**
* 字段名称
*/
String name() default "";
}
2.编写自定义处理类,拦截请求,发现有标记的请求,则执行:
/**
* json参数解析
*/
public class JsonParamProvider implements HandlerMethodArgumentResolver {
/**
* 请求body格式
*/
private static final String CONTENT_TYPE = "application/json";
/**
* 判断是否是需要我们解析的参数类型
*/
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(CustomSignleParams.class);
}
/**
* 真正解析的方法
*/
@Override
public Object resolveArgument(@NonNull MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory) {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
if (request == null) {
return null;
}
String contentType = request.getContentType();
if (StringUtils.isEmpty(contentType) || !contentType.toLowerCase().contains(CONTENT_TYPE)) {
return null;
}
JSONObject jsonObject=new JSONObject();
try (BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(),
StandardCharsets.UTF_8))) {
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null) {
responseStrBuilder.append(inputStr);
}
jsonObject = JSON.parseObject(responseStrBuilder.toString());
} catch (Exception e) {
}
CustomSignleParams jsonParam = methodParameter.getParameterAnnotation(CustomSignleParams.class);
if (jsonParam == null) {
return null;
}
//获取参数名
String paramName = jsonParam.name();
String paramType = methodParameter.getParameter().getType().getSimpleName();
if (jsonObject != null && jsonObject.containsKey(paramName)) {
String data = String.valueOf(jsonObject.get(paramName));
return initValue(paramType, data);
}
return null;
}
/**
* 给基本类型参数注入值
*
* @param type 类型
* @param data 值
* @return java.lang.Object
*/
private Object initValue(String type, String data) {
try {
if ("int".equalsIgnoreCase(type) || "integer".equalsIgnoreCase(type)) {
return Integer.valueOf(data);
} else if ("double".equalsIgnoreCase(type)) {
return Double.valueOf(data);
} else if ("long".equalsIgnoreCase(type)) {
return Long.valueOf(data);
}
} catch (NumberFormatException e) {
}
return data;
}
}
上面的类用于处理请求中的数据,字段名称从CustomSignleParams字段获取,然后再赋值给controller中的字段;
3.接着,把处理类注册到处理链中:
@Configuration
public class WebMvcCustomConfigurer implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
JsonParamProvider jsonParamProvider=new JsonParamProvider ();
resolvers.add(jsonParamProvider);
}
}
注入之后,一旦有controller上添加了注解,会触发参数的处理;
这样会把json解析,然后把json中的value赋值给controller中的参数;
例子:
@CustomSignleParams(name = "id")String id
该类只能处理单值参数
有一个问题:为何springmvc不添加对单值的处理呢?????