定位:官网摘的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(); } } }
参考资料连接: