zoukankan      html  css  js  c++  java
  • Feign进行文件上传+表单调用

    Feigin默认是不支持文件上传和表单提交的,需要做一些配置才能支持。

    1、feign依赖

     图中红色为form支持必须的jar。

    2、添加自定义Encoder类:

    import java.lang.reflect.Type;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    import org.springframework.web.multipart.MultipartFile;
    
    import feign.RequestTemplate;
    import feign.codec.EncodeException;
    import feign.form.spring.SpringFormEncoder;
    import lombok.val;
    import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
    
    import static java.util.Collections.singletonMap;
    
    /**
     * @author roger yang
     * @date 10/22/2019
     */
    public class MultipartEncoder extends SpringFormEncoder {
        
        @SuppressWarnings("unchecked")
        @Override
        public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
            if (bodyType.getClass().equals(ParameterizedTypeImpl.class) && ((ParameterizedTypeImpl) bodyType).getRawType().equals(Map.class)) {
                val data = (Map<String, Object>) object;
                Set<String> nullSet = new HashSet<>();
                for (Map.Entry<String, Object> entry : data.entrySet()) {
                    if (entry.getValue() == null) {
                        nullSet.add(entry.getKey());
                    }
                }
                for (String s : nullSet) {
                    data.remove(s);
                }
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            } else if (bodyType.equals(MultipartFile.class)) {
                val file = (MultipartFile) object;
                val data = singletonMap(file.getName(), object);
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            } else if (bodyType.equals(MultipartFile[].class)) {
                val file = (MultipartFile[]) object;
                if (file != null) {
                    val data = singletonMap(file.length == 0 ? "" : file[0].getName(), object);
                    super.encode(data, MAP_STRING_WILDCARD, template);
                    return;
                }
            }
            super.encode(object, bodyType, template);
        }
    }

    为什么要自定义呢?因为SpringFormEncoder这个类的源码里只对MultipartFile做了特殊处理,并未对MultipartFile[]数组进行处理,在传递多个文件时会报错。

      @Override
      public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        if (!bodyType.equals(MultipartFile.class)) {
          super.encode(object, bodyType, template);
          return;
        }
    
        val file = (MultipartFile) object;
        val data = singletonMap(file.getName(), object);
        super.encode(data, MAP_STRING_WILDCARD, template);
      }

    另外,我们为了让文件和表单一起在http的body里一起传输,所有我们将他们都封装到map里统一处理。

    3、feign接口类:

    import java.util.Map;
    
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import com.longge.common.GlobalResponse;
    
    /**
     * @author: yangzhilong
     * @description: Notification api
     * post with MULTIPART_FORM_DATA_VALUE
     * you client feign config:
     * -------------------------------------------------------------------
     *  import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.context.annotation.Bean;
        
        import com.longge.api.NotificationService;
        
        import feign.codec.Encoder;
        import com.longge.config.MultipartEncoder;
        
        @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
        public interface NotificationServiceFeign extends NotificationMultipartService {
            class FeignSimpleEncoderConfig {
                
                @Bean
                public Encoder encoder(){
                    return new MultipartEncoder();
                }
            }
        }
     * ---------------------------------------------------------------------
     * @date: 17:24 2019/7/3
     **/
    @RequestMapping(value = "/v1/api")
    public interface NotificationMultipartService {
    
        /**
         * common email channel ,use to send common email
         *
         * @param data
         *     map key have: 
         *          attachfile       -->          MultipartFile[]
         *          com.longge.dto.EmailDto.FieldName --- >   value
         *          
         * eg:
         *  Map<String, Object> data = new HashMap<>();
            data.put("attachfile", new MultipartFile[] {file});
            data.put("from", emailDto.getFrom());
            data.put("to", emailDto.getTo());
            data.put("bodyText", emailDto.getBodyText());
            data.put("subject", emailDto.getSubject());
         * @return GlobalResponse<Long>  email id
         */
        @RequestMapping(value = "/send_mail", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        GlobalResponse<String> sendMail(Map<String, Object> data);
    }

    其中为了支持 form请求,需要对此feign进行单独的配置:

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.context.annotation.Bean;
    
    import com.longge.api.NotificationMultipartService;
    
    import feign.codec.Encoder;
    
    @FeignClient(value = "notification-service", configuration = NotificationServiceFeign.FeignSimpleEncoderConfig.class)
    public interface NotificationServiceFeign extends NotificationMultipartService {
        class FeignSimpleEncoderConfig {
            @Bean
            public Encoder encoder() {
                return new MyEncoder();
            }
        }
    }

    4、服务实现类

    @RequestMapping(value = "/v1/api/send_mail", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = {MediaType.APPLICATION_JSON_VALUE})
    public GlobalResponse<String> sendMail(@RequestParam(value = "attachfile", required = false) MultipartFile[] attachfile, EmailDto emailDto) {
        // TODO
    }

    5、EmailDto属性

    private String from;
    private String to;
    private String subject;
    private String bodyText;
    private String bodyHtml;

    感谢:https://blog.csdn.net/ytzzh0726/article/details/79731343 

  • 相关阅读:
    python 函数
    python升级功能
    python3与c++的不同点(初学看重点~)
    python中的数据结构
    github超简单用法
    ListView
    线性代数(1)--方程组的同解变形
    C++基础学习
    C++多态
    PKU《程序设计》专项课程_递归汉诺塔问题
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/11714620.html
Copyright © 2011-2022 走看看