定位:官網摘的html
Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign.前端
如何使用:git
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.2.RELEASE</version> </dependency>
@FeignClient(name = "suibian",url = "${suibian.request.url}", configuration = FeignClientConfiguration.class)
Spring Cloud creates a new ensemble as an ApplicationContext on demand for each named client using FeignClientsConfiguration. This contains (amongst other things) an feign.Decoder, a feign.Encoder, and a feign.Contract.github
自帶:FeignClientConfiguration.class,包含feign.Decoder, a feign.Encoder, and a feign.Contractweb
@Configuration public class FeignFileUploadConfig { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(new SpringEncoder(messageConverters)); } }
//寫configuration類 public class FeignConfig { @Bean public Logger.Level Logger() { return Logger.Level.FULL; } } //寫配置 logging: level: com.xxx.xxx.FeignAPI: DEBUG #須要將FeignClient接口全路徑寫上# 開啓日誌 格式爲logging.level.+Feign客戶端路徑
feign: client: config: #想要調用的微服務名稱 server-1: loggerLevel: FULL
調用client 被調用的項目server
client代碼分爲controller層 serice層 remote調用接口
server代碼展現controller層spring
1.import
spring-cloud-starter-openfeign不支持文件上傳,須要引入拓展的第三方包數組
<!-- feign file upload--> <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form-spring</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
2.代碼實現 使用@RequestPart
controller層服務器
@RequestMapping(value = "/addFile", method = RequestMethod.POST,consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public Result addFile( @RequestParam("id") Integer id, @RequestPart("file") MultipartFile multipartFile) { return bizSuibianService.addFile(id,multipartFile); }
serice層app
public Result addFile(Integer id, MultipartFile multipartFile){ try { return bizSuibianFileRemote.addFile(id,multipartFile); } catch (Exception e) { e.printStackTrace(); return Result.error("invalid param",e); } }
remoteide
@FeignClient(name = "suibian",url = "${suibian.request.url}",configuration = FeignFileUploadConfig.class) public interface BizSuibianFileRemote { @RequestMapping(value = "/addFile", method = RequestMethod.POST,consumes = MediaType.MULTIPART_FORM_DATA_VALUE) MimirResult addFile(@RequestParam("id") Integer dd, @RequestPart("file") MultipartFile file); }
FeignFileUploadConfig.class
放在主類以外,加了@Configuration
須要注意的是new SpringEncoder(messageConverters),這個部分的代碼邏輯不清楚。我的感受方法一是存在問題的,但事實是方法一work,方法二報錯。可能跟@Configuration有關。
//方法一 @Configuration public class FeignFileUploadConfig { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(new SpringEncoder(messageConverters)); } } //方法二 @Configuration public class FeignFileUploadConfig { @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(); } }
Tips:該方法不支持MultipartFile[] files
由於第三方的拓展中,源碼並無對MultipartFile[] 這種狀況進行處理。若是用這個類型的入參,請參考https://blog.csdn.net/qq_3295...
server代碼展現controller層
controller
@RequestMapping(value = "/xxxx",method = RequestMethod.GET) public void getImagesById( @RequestParam("id") Integer id, HttpServletResponse response){ InputStream inputStream = null; OutputStream outputStream=null; try { // feign文件下載 Response responseFromRemote = bizSuibianService.getImagesById(authCode, id); Response.Body body = responseFromRemote.body(); inputStream = body.asInputStream(); outputStream = response.getOutputStream(); byte[] b = new byte[inputStream.available()]; byte[] buffer = new byte[1024 * 8]; int count = 0; while ((count = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, count); outputStream.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null) { try { response.setContentType("image/*"); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
先用response去接remote返回的httpServletResponse(response From Server to client),而後讀取數據,寫給要返回前端的httpServletResponse(response From Client to front end)
service
@Override public Response getImagesById(Integer id){ try { return bizSuibianRemote.getImagesById(id); } catch (Exception e) { e.printStackTrace(); return null; } }
remote
@RequestMapping(value = "/xxxx/{id}",method = RequestMethod.GET) Response getImagesById(@PathVariable("id") Integer id);
server controller
@RequestMapping(value = "/xx/{id}",method = RequestMethod.GET) public void getImagesById(@PathVariable("id") Integer id, HttpServletResponse response) { InputStream fis = null; OutputStream os = null; try { //本地圖片 ClassPathResource resource = imageService.getImagePathById(id); fis = resource.getInputStream(); os = response.getOutputStream(); int count = 0; byte[] buffer = new byte[1024 * 8]; while ((count = fis.read(buffer)) != -1) { os.write(buffer, 0, count); os.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { try { response.setContentType("image/*"); fis.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } }
參考資料連接: