这是一个很好的问题。如果我了解Spring MVC如何在幕后工作,则不使用HTTP转换器 @ModelAttribute 驱动的。当您从中获取异常时,可以轻松检查它 ExampleParam 构造函数或 ExampleParam.setCamelCase 方法(de-Lombok first) - Spring使用它的bean实用程序 public (!) ExampleParam.setCamelCase 设置DTO值。另一个证明是没有 Gson.fromJson 无论您的Gson转换器配置如何,都不会调用。所以,你的 camelCase 让你感到困惑,因为默认的Gson实例和Spring一样使用这个策略 - 所以这只是一个混乱的问题。
@ModelAttribute
ExampleParam
ExampleParam.setCamelCase
public
Gson.fromJson
camelCase
为了使其工作,您必须创建自定义Gson感知 HandlerMethodArgumentResolver 实现。假设我们只支持POJO(不是列表,地图或基元)。
HandlerMethodArgumentResolver
@Configuration @EnableWebMvc class WebMvcConfiguration extends WebMvcConfigurerAdapter { private static final Gson gson = new GsonBuilder() .setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES) .create(); @Override public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new HandlerMethodArgumentResolver() { @Override public boolean supportsParameter(final MethodParameter parameter) { // It must be never a primitive, array, string, boxed number, map or list -- and whatever you configure ;) final Class<?> parameterType = parameter.getParameterType(); return !parameterType.isPrimitive() && !parameterType.isArray() && parameterType != String.class && !Number.class.isAssignableFrom(parameterType) && !Map.class.isAssignableFrom(parameterType) && !List.class.isAssignableFrom(parameterType); } @Override public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer, final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) { // Now we're deconstructing the request parameters creating a JSON tree, because Gson can convert from JSON trees to POJOs transparently // Also note parameter.getGenericParameterType() -- it's better that Class<?> that cannot hold generic types parameterization return gson.fromJson( parameterMapToJsonElement(webRequest.getParameterMap()), parameter.getGenericParameterType() ); } }); } ... private static JsonElement parameterMapToJsonElement(final Map<String, String[]> parameters) { final JsonObject jsonObject = new JsonObject(); for ( final Entry<String, String[]> e : parameters.entrySet() ) { final String key = e.getKey(); final String[] value = e.getValue(); final JsonElement jsonValue; switch ( value.length ) { case 0: // As far as I understand, this must never happen, but I'm not sure jsonValue = JsonNull.INSTANCE; break; case 1: // If there's a single value only, let's convert it to a string literal // Gson is good at "weak typing": strings can be parsed automatically to numbers and booleans jsonValue = new JsonPrimitive(value[0]); break; default: // If there are more than 1 element -- make it an array final JsonArray jsonArray = new JsonArray(); for ( int i = 0; i < value.length; i++ ) { jsonArray.add(value[i]); } jsonValue = jsonArray; break; } jsonObject.add(key, jsonValue); } return jsonObject; } }
那么,结果如下:
http://localhost:8080/?camelCase=hello
http://localhost:8080/?camel_case=hello
"hello"