背景
最近转java,背靠公司java大神,利用spring cloud框架重构现有业务,新手遇坑是常事,也是喜闻乐见的,趟坑能让自己快速的学习成长。
Feign是一个声明式的Web服务客户端,使用Feign可使得Web服务客户端的写入更加方便。
具体的介绍就不多说了,直接看github就好,这里写链接内容
这里主要记录一下利用feign发送post请求时遇到的问题。
问题重现
public interface MessageCenterInterface {
@RequestLine("POST /v3/bbs/BatchAttention")
@Headers("Content-Type: application/json")
NetResult batchAttention(BatchAttentionVO batchAttentionVO);
}
// 参数实体
public class BatchAttentionVO {
private Integer ewtUserId;
private Integer devicetype;
private String attentionIds;
private String attentionTitles;
public Integer getEwtUserId() {
return ewtUserId;
}
public void setEwtUserId(Integer ewtUserId) {
this.ewtUserId = ewtUserId;
}
public Integer getDevicetype() {
return devicetype;
}
public void setDevicetype(Integer devicetype) {
this.devicetype = devicetype;
}
public String getAttentionIds() {
return attentionIds;
}
public void setAttentionIds(String attentionIds) {
this.attentionIds = attentionIds;
}
public String getAttentionTitles() {
return attentionTitles;
}
public void setAttentionTitles(String attentionTitles) {
this.attentionTitles = attentionTitles;
}
}
@Component
@Slf4j
public class HttpManager {
private MessageCenterInterface messageCenterInterface;
@Autowired
private AppConfig appConfig;
@PostConstruct
private void initFeign(){
messageCenterInterface =
Feign.builder()
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.target(MessageCenterInterface.class,"http://messagecenter.233.mistong.com");
}
public MessageCenterInterface getMessageCenterInterface() {
return messageCenterInterface;
}
}
嗯,很神奇,对方拿不到请求的参数,本以为是封装成实体类BatchAttentionVO不行,看着github上的示例,他是封装成了type-safe类,试了下,也不行,改成string类型,还是不行,有点抓瞎了
妈蛋,用PHP自己搭了个服务来调试参数看看。
public function test(Request $request){
var_dump($_POST, $_REQUEST);
//larvel对请求参数的封装,包括所有类型的
var_dump($request->input());
}
调试结果
array(0) {
}
array(0) {
}
array(4) {
["ewtUserId"]=>
int(501398)
["devicetype"]=>
int(2)
["attentionIds"]=>
string(11) "39,90,65,97"
["attentionTitles"]=>
string(45) "大课间,充电站,卧谈会,男神女神秀"
}
大爷的,总算知道怎么回事了,肯定是参数传输方式跟服务端没对上,Content-Type改成application/x-www-form-urlencoded试试,结果
array(1) {
["{
__"ewtUserId":_501398,
__"devicetype":_2,
__"attentionIds":_"39,90,65,97",
__"attentionTitles":_"大课间,充电站,卧谈会,男神女神秀"
}"]=>
string(0) ""
}
array(1) {
["{
__"ewtUserId":_501398,
__"devicetype":_2,
__"attentionIds":_"39,90,65,97",
__"attentionTitles":_"大课间,充电站,卧谈会,男神女神秀"
}"]=>
string(0) ""
}
array(1) {
["{
__"ewtUserId":_501398,
__"devicetype":_2,
__"attentionIds":_"39,90,65,97",
__"attentionTitles":_"大课间,充电站,卧谈会,男神女神秀"
}"]=>
string(0) ""
}
还是不太对,参数收到了,但是格式不对
解决办法
自定义encoder类QueryPostMapEncoder,将参数全部拼进body里面去,不采用Content-Type: application/json 参数的形式,顺带还进行了下加密串的拼接
public interface MessageCenterInterface {
@RequestLine("POST /v3/bbs/BatchAttention")
NetResult batchAttention(BatchAttentionVO batchAttentionVO);
}
@Component
@Slf4j
public class HttpManager {
private MessageCenterInterface messageCenterInterface;
@Autowired
private AppConfig appConfig;
@PostConstruct
private void initFeign(){
messageCenterInterface =
Feign.builder()
.decoder(new CustomDecoder())
.encoder(new QueryPostMapEncoder(appConfig.getMessageCenter().getSignkey()))
.logLevel(Logger.Level.FULL)
.logger(new Slf4jLogger(MessageCenterInterface.class))
.target(MessageCenterInterface.class,appConfig.getMessageCenter().getDomain());
}
public MessageCenterInterface getMessageCenterInterface() {
return messageCenterInterface;
}
}
public class QueryPostMapEncoder implements Encoder {
private String secret;
public QueryPostMapEncoder(String secret) {
this.secret = secret;
}
@Override
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
try {
Map<String,String> params = ObjectUtils.objectToMapString(o);;
String sign = SignUtil.sign(params,this.secret);
requestTemplate.query("sign",sign);
StringBuilder sb = new StringBuilder();
sb.append("sign=");
sb.append(sign);
for (Map.Entry<String,String> param:params.entrySet()){
if (param.getValue()!=null) {
sb.append("&");
sb.append(param.getKey());
sb.append("=");
sb.append(param.getValue());
}
}
requestTemplate.body(sb.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
调试一下
array(5) {
["sign"]=>
string(32) "60162f112394550a87675ca8e0b9d061"
["attentionIds"]=>
string(11) "39,90,65,97"
["attentionTitles"]=>
string(45) "大课间,充电站,卧谈会,男神女神秀"
["ewtUserId"]=>
string(6) "501398"
["devicetype"]=>
string(1) "2"
}
array(5) {
["sign"]=>
string(32) "60162f112394550a87675ca8e0b9d061"
["attentionIds"]=>
string(11) "39,90,65,97"
["attentionTitles"]=>
string(45) "大课间,充电站,卧谈会,男神女神秀"
["ewtUserId"]=>
string(6) "501398"
["devicetype"]=>
string(1) "2"
}
array(5) {
["sign"]=>
string(32) "60162f112394550a87675ca8e0b9d061"
["attentionIds"]=>
string(11) "39,90,65,97"
["attentionTitles"]=>
string(45) "大课间,充电站,卧谈会,男神女神秀"
["ewtUserId"]=>
string(6) "501398"
["devicetype"]=>
string(1) "2"
}
完美解决