前几篇已经展示了Hystrix+RestTemplate的方式调用服务,实际上在consumer的BookService里面,如果要挨个的去调用provider中的接口,BookService里面首先要注入RestTemplate,然后写相应的方法,每一个方法去调用provider中BookController中的接口,但是你会发现这些方法具有极大的相似性,你会发现这个BookService里面首先要注入RestTemplate,这是一个固定的操作,然后下面定义的方法名叫什么,无所谓,以下面的hello方法为例,在定义的方法中的返回值,restTemplate是不变的,
getForObject这个位置方法的选择:getForObject、putForObject、post、delete,具体看provider中BookController中的方法是什么。然后就是地址可能是会变化的,最后是响应类型,这边的相应类型就是BookController中方法的返回类型。所以你会发现这个BookServicer中的方法是一个固定的,它有一套固定的模板,不固定的只有方法的返回类型,getForObject处方法的选择,请求地址,响应类型。那么剩下的代码就可以自动生成。
@Autowired
@Qualifier("restTemplateTwo")
RestTemplate restTemplateTwo;
@HystrixCommand(fallbackMethod = "error",ignoreExceptions = ArithmeticException.class)
public String hello(){
return restTemplateTwo.getForObject("http://provider/hello",String.class);
}
首先创建一个新的Module: feign-consumer,并且加入如下依赖
feign-consumer的配置文件如下:
在启动类中使用@EnableFeignClients 注解开启Feign的客户端:
在pom.xml文件中加入Book的依赖:
然后再定义一个BookService接口,注意这个BookService无需添加@Service注解
声明这样一个方法即可,这个方法不需要去实现,方法名可以自定义,但最好和BookController中一致,一会儿直接调用这个方法,就相当于调用BookController中的接口中的以下方法:
通过注解中的provider加@getMapping中的请求路径,就可以自动拼接出http://provider/book,返回值就是Book。
然后在feign-consumer中创建一个BookCtroller来调用这个方法
@RestController
public class BookController {
@Autowired
BookService bookService;
@GetMapping("/test1")
public Book getBookById(){
return bookService.getBookById(99L);
}
}
测试结果如下:
传参问题
平时使用的传参方式大概就是四种,key-value的形式、放在请求体传参、放在请求路径中传参、放在请求头中传参,这四种方式在feign里面都是支持的。
下面来看看这四种传参方式,在provider中的BookController中有如下方法,get是key-value的方式、delete是请求路径的方式、put是请求体的方式,然后再创建一个名为updateBookById的put请求就是通过请求头的方式传参,如下:
然后在feign-consumer中的BookService中定义相关的接口,如下:
@FeignClient("provider")
//该注解表示这是一个Feign的客户端,绑定的provider表示要访问的服务提供者的名字叫provider
public interface BookService {
@GetMapping("/book")
//硬性要求,在这里面一定要加(@RequestParam("id")注解制定一个值
Book getBookById(@RequestParam("id") Long id);
@PostMapping("/book")
Book addBook(@RequestBody Book book);
@DeleteMapping("/book/{id}")
void deleteById(@PathVariable("id") Long id);
@PutMapping("/book2")
void updateBookId2(@RequestHeader("name") String name,@RequestHeader("id") Long id);
}
然后再去feign-consumer中的BookController中调用这些接口:
@RestController
public class BookController {
@Autowired
BookService bookService;
@GetMapping("/test1")
public Book getBookById() throws UnsupportedEncodingException {
//addBook
Book book = new Book();
book.setId(100L);
book.setName("三国演义");
book.setAuthor("罗贯中");
bookService.addBook(book);
//deleteById
bookService.deleteById(101L);
//updateBookById2
bookService.updateBookId2(URLEncoder.encode("三国演义222","UTF-8"),102L);
//getBookById
return bookService.getBookById(99L);
}
}
控制台输出效果如下: