Feign Client请求参数编码异常求助:Long类型参数解析错误
解决Feign Client中Map参数Long类型序列化问题
问题根源
Feign默认的SpringFormEncoder处理@RequestParam修饰的Map<String, Object>参数时,会对Map内的Object值直接调用toString()方法。对于Long类型来说,toString()会返回带L后缀的字符串(比如1234567893L),导致服务端解析时将其识别为字符串类型,而非预期的数字类型。
解决方案
1. 配置Jackson ObjectMapper,让Long序列化输出纯数字
先定义自定义ObjectMapper,配置Long类型的序列化规则,避免输出L后缀:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public ObjectMapper customObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 配置Long及基本类型long序列化为纯数字格式 module.addSerializer(Long.class, ToStringSerializer.instance); module.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(module); return objectMapper; } }
2. 自定义Feign Encoder,结合ObjectMapper处理Map参数
默认的SpringFormEncoder不会用Jackson处理Map参数,需要自定义Encoder,利用上面的ObjectMapper序列化Map中的值:
import feign.RequestTemplate; import feign.codec.EncodeException; import feign.codec.Encoder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.openfeign.support.SpringFormEncoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.MultiValueMap; import java.lang.reflect.Type; import java.util.Map; @Configuration public class FeignConfig { @Autowired private ObjectMapper objectMapper; @Bean public Encoder feignEncoder() { return new SpringFormEncoder() { @Override public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { if (object instanceof Map) { Map<String, Object> map = (Map<String, Object>) object; MultiValueMap<String, String> multiValueMap = new org.springframework.util.LinkedMultiValueMap<>(); map.forEach((key, value) -> { try { // 用自定义ObjectMapper序列化值,避免Long带L后缀 String serializedValue = objectMapper.writeValueAsString(value); // 移除Jackson序列化基本类型时添加的引号 serializedValue = serializedValue.replace("\"", ""); multiValueMap.add(key, serializedValue); } catch (Exception e) { throw new EncodeException("序列化Map值失败", e); } }); super.encode(multiValueMap, bodyType, template); } else { super.encode(object, bodyType, template); } } }; } }
3. 给Feign Client指定配置类
在Feign Client接口上通过@FeignClient注解关联上述配置类:
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; @FeignClient(name = "your-service-name", configuration = FeignConfig.class) public interface YourFeignClient { @GetMapping("/api/getResult") Result getResult(@RequestParam String id, @RequestParam Map<String, Object> params); }
补充说明
- 服务端基于Spring MVC接收参数时,纯数字格式的字符串会自动转换为对应数字类型(如Long),符合预期需求。
- 该方案对Map中包含的自定义对象同样生效,ObjectMapper会正确序列化对象字段,同时处理数字类型的输出格式。
内容的提问来源于stack exchange,提问作者user5735224
相关产品推荐
相关产品推荐

