摘要:前言在開發(fā)應(yīng)用中,作為聲明式調(diào)用的事實標(biāo)準(zhǔn)極大的簡化了遠程調(diào)用,提供了類本地化的調(diào)用方式。本文介紹一種通過動態(tài)代理的方式無需直接暴露接口。后語關(guān)于這個框架的介紹,后續(xù)詳細的給大家進行介紹。
前言
在開發(fā)SpringCloud應(yīng)用中,F(xiàn)eign作為聲明式調(diào)用的事實標(biāo)準(zhǔn)極大的簡化了Rest遠程調(diào)用,提供了類本地化的調(diào)用方式。服務(wù)提供方的接口暴露方式是通過Controller暴露Restful,而在這個Controller的代碼現(xiàn)實中大部分都是處理請求然后再調(diào)用Service中的方法,是一個比較模板化的功能,但是工作量確不少。本文介紹一種通過動態(tài)代理的方式無需Controller直接暴露Restful接口。
本文中使用筆者在Github開源的框架來實現(xiàn),本文的講解也在這個框架基礎(chǔ)之上來說明
Git路徑:https://github.com/leecho/spr...
實現(xiàn) 定義Service Interfacecom.github.leecho spring-cloud-starter-feign-proxy {last-version}
首先定義服務(wù)接口,使用@FeignClient標(biāo)示是一個Feign接口,在這個示例Sevice中定義了CURD和文件上傳方法,并使用了一些常用參數(shù)注解
@Api(tags = "DemoService", description = "Demo Feign Client") @FeignClient("demo-service") public interface DemoService { /** * create demo * * @param demo * @return */ @ApiOperation(value = "Create demo") @PostMapping(value = "/demo") Demo create(@RequestBody @Valid @ApiParam Demo demo); /** * update demo * * @param demo * @return */ @PutMapping(value = "/demo") Demo update(@RequestBody @Valid Demo demo); /** * delete demo * * @param id * @return */ @DeleteMapping(value = "/demo/{id}") Demo delete(@PathVariable(name = "id") String id); /** * list demo * * @param id * @param headerValue test header value * @return */ @GetMapping(value = "/demo/{id}") Demo get(@PathVariable(name = "id") String id, @RequestHeader(name = "header") String headerValue); /** * list demos * * @return */ @GetMapping(value = "/demos") List實現(xiàn)Servicelist(); /** * upload file * * @param file * @return */ @PostMapping(value = "/demo/upload") String upload(@RequestPart(name = "file") MultipartFile file); }
在實現(xiàn)類中簡單的實現(xiàn)了CURD和上傳文件的方法
@Slf4j @Primary @Service public class DemoServiceImpl implements DemoService { @Override public Demo create(Demo demo) { log.info("Create executed : " + demo); return demo; } @Override public Demo update(Demo demo) { log.info("Update execute :" + demo); return demo; } @Override public Demo delete(String id) { log.info("Delete execute : " + id); return Demo.builder().name("demo-" + id).data("data-" + id).build(); } @Override public Demo get(String id, String header) { Demo demo = Demo.builder() .name(header) .data(header).build(); System.out.println("Get execute : " + id + "," + header); return demo; } @Override public Listlist() { System.out.println("List execute"); List demos = new ArrayList<>(); for (int i = 0; i < 5; i++) { Demo demo = Demo.builder() .name("demo-" + i) .data("data" + i).build(); demos.add(demo); } return demos; } @Override public String upload(MultipartFile file) { return file.getOriginalFilename(); } }
動態(tài)生成Restful接口的原理是動態(tài)生成Controller類實現(xiàn)ServiceInterface,如果真正的實現(xiàn)類會被其他BEAN依賴,需要通過注解@Primary來方式來防止依賴沖突配置應(yīng)用
在應(yīng)用中通過@EnableFeignProxies來標(biāo)示應(yīng)用在啟動的過程中會掃描所有的FeignClients并暴露Restful接口
@EnableFeignProxies(basePackages = "com.github.leecho") @ComponentScan("com.github.leecho") @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }測試用例
在測試用例中對Service的接口進行測試
@SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration public class DemoApplicationTest { @Autowired private WebApplicationContext context; private MockMvc mvc; @Before public void setUp() { mvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test public void create() throws Exception { mvc.perform(MockMvcRequestBuilders.post("/demo") .contentType(MediaType.APPLICATION_JSON_UTF8) .content(new ObjectMapper().writeValueAsString(Demo.builder().name("create").data("data").build())) .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void update() throws Exception { mvc.perform(MockMvcRequestBuilders.put("/demo") .contentType(MediaType.APPLICATION_JSON_UTF8) .content(new ObjectMapper().writeValueAsString(Demo.builder().name("update").data("data").build())) .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void delete() throws Exception { mvc.perform(MockMvcRequestBuilders.delete("/demo/{id}", "1") .contentType(MediaType.APPLICATION_JSON_UTF8) .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void get() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/demo/{id}", "1") .contentType(MediaType.APPLICATION_JSON_UTF8) .header("header", "header-value") .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void list() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/demos") .contentType(MediaType.APPLICATION_JSON_UTF8) .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } @Test public void upload() throws Exception { mvc.perform(MockMvcRequestBuilders.multipart("/demo/upload").file(new MockMultipartFile("file", "test.txt", ",multipart/form-data", "upload test".getBytes())) .accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } }
在啟動日志中也可以看到Restful接口已經(jīng)暴露成功。
后語關(guān)于這個框架的介紹,后續(xù)詳細的給大家進行介紹。文中所涉及到的代碼也在Git中:spring-cloud-feign-proxy-sample
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/72096.html
摘要:不過,我們搭建好框架就是為了消費它使用它,那么這篇文章就來看看如何去消費使用我們之前搭建起來的服務(wù)吧首先本文是基于上一篇文章進行的。代碼如下啟動程序,多次訪問,瀏覽器顯示內(nèi)容為至此我們這個服務(wù)消費的框架就搭建完畢了。。。 上一篇文章主要介紹了如何搭建一個簡單的springcloud框架。不過,我們搭建好框架就是為了消費它使用它,那么這篇文章就來看看如何去消費使用我們之前搭建起來的服務(wù)吧...
摘要:在服務(wù)架構(gòu)中,業(yè)務(wù)都會被拆分成一個獨立的服務(wù),服務(wù)與服務(wù)的通訊是基于的。配置文件如下在工程的啟動類中通過向服務(wù)中心注冊并且注冊了一個通過注冊表明,這個是負載均衡的。 轉(zhuǎn)載請標(biāo)明出處: http://blog.csdn.net/forezp/a...本文出自方志朋的博客 在上一篇文章,講了服務(wù)的注冊和發(fā)現(xiàn)。在服務(wù)架構(gòu)中,業(yè)務(wù)都會被拆分成一個獨立的服務(wù),服務(wù)與服務(wù)的通訊是基于http re...
摘要:服務(wù)消費者可以使用多種模型來發(fā)現(xiàn)服務(wù)。客戶端將定期與服務(wù)發(fā)現(xiàn)層進行通信,并刷新服務(wù)實例的緩存。為了達成目的,我們將要學(xué)習(xí)使用個不同的客戶端庫,服務(wù)消費者可以使用它們來和進行交互。 本篇代碼存放于:github 一、服務(wù)發(fā)現(xiàn)架構(gòu) ??服務(wù)發(fā)現(xiàn)架構(gòu)通常具有下面 4 個概念: 服務(wù)注冊:服務(wù)如何使用服務(wù)發(fā)現(xiàn)代理進行注冊? 服務(wù)地址的客戶端查找:服務(wù)客戶端查找服務(wù)信息的方法是什么? 信息共享...
摘要:此為的結(jié)構(gòu)圖上篇已注冊了,的服務(wù),接下來用,實現(xiàn)負載均衡和的簡單客戶端,讓消費者調(diào)用服務(wù)。是發(fā)布的云中間層服務(wù)開源項目,其主要功能是提供客戶側(cè)軟件負載均衡算法,將的中間層服務(wù)連接在一起。對選定的負載均衡策略機上重試機制。 ??????????上篇已經(jīng)搭建好基礎(chǔ)demo,接下來繼續(xù)構(gòu)建項目并對spring cloud組件介紹描述。 showImg(https://segmentfault...
閱讀 1135·2021-10-27 14:15
閱讀 2843·2021-10-25 09:45
閱讀 2026·2021-09-02 09:45
閱讀 3414·2019-08-30 15:55
閱讀 1884·2019-08-29 16:05
閱讀 3292·2019-08-28 18:13
閱讀 3159·2019-08-26 13:58
閱讀 502·2019-08-26 12:01