目录
在正式讲解HTTP远程调用时,我们先来了解一下缺省方法的定义。
写在前面:
- 缺省参数可传可不传,可以传多个但他们必须是相同的类型
- 每个方法中缺省参数只能定义一个,并且只能在参数的最后定义;
- 缺省参数可读性比较差,而且它还可以被数组代替,开发中不建议使用,这里遇到了就简单来了解一下;
缺省方法:定义N个相同类型的参数值,N >= 0;命名方式就是在参数前增加三个点省略符,如下例子可以帮我们更好的理解这一概念:
public class Student{
public static void getStudent(int age, String name, String ...strB ){
...
}
}
我们可以采用如下方式对缺省方法进行调用:
public static void main(String[] args) {
Student.getStudent(22,"Jimmy"); // 没有
Student.getStudent(22,"Jimmy","strB1"); // 1个
Student.getStudent(22,"Jimmy","strB1","strB2"); // 多个
}
缺省参数值的遍历(foreach),比较简单就不过多阐述,直接看一下例子:
public class Student{
public static void getStudent(int age, String name, String ...strB ){
System.out.println("参数数量:" + strB.length);
for (String str : strB) {
System.out.println("参数值:" + str);
}
}
}
feign实现http远程调用(正文)
首先我们需要引入所需要的依赖,这里值得注意的是,我们在引入依赖时所选用的springboot版本必须和springcloud保持对应,这里我是用的是springboot【2.2.6.RELEASE】+springcloud【Hoxton.SR12】进行演示操作。
<dependencyManagement>
<dependencies>
<!--SpringCloud依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--openfeign跨服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--openfeign底层使用ApacheHttpClient调用-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
</dependencies>
Feign支持通过GET和POST方法向服务传递参数,我们先来简单看一个例子:
这里@FeignClient中的name代表的是微服务名称标识,path是Spring Boot配置环境中的server.servlet.context-path=/test,用来标明是哪个应用下的微服务。
当然这里也可以直接通过value来定义http://xx.xx.xxx.xx:xxxx来进行远程调用。
@FeignClient(name = "service", path = "/test")
public interface Service {
@GetMapping(value = "/get")
TestMode echoGet(@RequestParam("parameter") String parameter);
@PostMapping(value = "/post")
TestMode echoPost(@RequestParam("parameter") String parameter);
}
头疼的是我在采用上述@RequestParam("parameter")方式的时候,出现了下面的报错:
GET "/test/post?parameter=POST%20%3A%20++%20plus%20sign%20contained%2C%20but%20it's%20gone%20unexpectedly."
刚开始我对这个报错比较迷惑,经过查阅资料发现这种URL传参的方式存在一定的风险,因为它的URL长度是有限制的,如果我们传递的数据量很大,这时候就会出现上述错误。
解决方案:
针对上述情况,我通过feign客户端以form表单形式提交(POST
)参数的方式进行解决。
将某个feign
客户端方法定义如下 :
@Component
@FeignClient(value = "http://xx.xx.xxx.xx:xxxx")
public interface TestPaperClient {
@RequestMapping(value = "/xxx",method = RequestMethod.POST,consumes = {"application/x-www-form-urlencoded"})
TestPaper paperGeneration(Map<String, ?> map);
}
注意:
- 使用注解 @RequestMapping 表明要使用POST方法,当然这里也可以直接使用@PostMapping更加方便。
- 注解中要添加属性consumes = {"application/x-www-form-urlencoded"}。
- 参数使用Map<String, ?>形式 (不再是@RequestParam("parameter"))。
- Map<String, ?>中的
key
要和远程服务器端要求的参数名称一致,value
的类型要和远程服务器端要求的类型一致(可以借助下面serviceImpl中的代码进行理解),否则会出现HTTP 400 BAD_REQUEST
错误。
如下代码可以辅助理解上面的文字说明:
注意:下面例子中有一个自己封装的ApiResponse类,用来返回状态码和相关信息,大家可以根据自己的需求进行封装。
远程服务器返回的内容封装为实体类:
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestPaper {
private String text;//服务器端要返回的内容
}
Controller层代码:
@RestController
@RequestMapping(value = "/feign")
public class TestPaperController {
@Autowired
TestPaperService testPaperService;
@PostMapping("/DKQA")
public ApiResponse<TestPaper> testPaper(@RequestParam("msg") String msg){
return testPaperService.testPaper(msg);
}
}
Service接口代码:
public interface TestPaperService {
ApiResponse<TestPaper> testPaper(String testPaper);
}
service接口实现类代码:
@Service
public class TestPaperServiceImpl implements TestPaperService {
@Autowired
private TestPaperClient testPaperClient;
@Override
public ApiResponse<TestPaper> testPaper(String testPaper) {
Map<String,Object> map = new HashMap<>();
map.put("msg",testPaper);
return ApiResponse.data(testPaperClient.paperGeneration(map));
}
}
基于这种方式传递参数,我们就不用太担心参数数据量过大。至此,遇到的问题已经解决,后续有相关问题会再加以补充。