SpringCloud 服务间表单数据请求(若干文件+若干参数)

该博客介绍了如何在SpringCloud项目中使用Feign进行文件和参数的表单请求。通过引入相关依赖,配置FeignSpringFormEncoder和MultipartSupportConfig,实现了在客户端Controller中接收前端上传的文件和参数,然后通过FeignClient转发到服务端Controller。服务端Controller接收到请求后,进行业务处理。这种方式允许在分布式系统中处理复杂表单数据的传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题背景

我们的后端原始项目是一个单体应用(springboot+shiro+mybatis),后来改为分布式服务。想保留shiro的细粒度的接口访问权限的控制。所以架构方面是采用单点登录的架构模型。用户都会通过一个main-service主服务进入,首先进行接口访问权限的判断(主服务中有shiro),然后通过zuul网关进行一个请求的转发到其它服务。
着中间的问题是,所有的接口访问都是通过主服务进行访问的。也就是说前端数据都是请求的主服务的接口。有部分接口需要form表单传一些文件和参数,这里记录以下实现步骤。

依赖

让Feign支持表单传输,最后一个(feign-core)要注意版本,版本过低不支持文件传输

		<dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>10.1.0</version>
        </dependency>

配置文件(放在客户端服务)2个文件

FeignSpringFormEncoder 文件

import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.form.ContentType;
import feign.form.FormEncoder;
import feign.form.MultipartFormContentProcessor;
import feign.form.spring.SpringManyMultipartFilesWriter;
import feign.form.spring.SpringSingleMultipartFileWriter;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
public class FeignSpringFormEncoder extends FormEncoder {
    public FeignSpringFormEncoder() {
        this(new Default());
    }
    public FeignSpringFormEncoder(Encoder delegate) {
        super(delegate);
        MultipartFormContentProcessor processor = (MultipartFormContentProcessor)this.getContentProcessor(ContentType.MULTIPART);
        processor.addFirstWriter(new SpringSingleMultipartFileWriter());
        processor.addFirstWriter(new SpringManyMultipartFilesWriter());
    }
    public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        if (bodyType.equals(MultipartFile.class)) {
            MultipartFile file = (MultipartFile) object;
            Map<String, Object> data = Collections.singletonMap(file.getName(), object);
            super.encode(data, MAP_STRING_WILDCARD, template);
            return;
        } else if (bodyType.equals(MultipartFile[].class)) {
            MultipartFile[] file = (MultipartFile[]) object;
            if(file != null) {
                Map<String, Object> data = Collections.singletonMap(file.length==0?"":file[0].getName(), object);
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            }
        }
        super.encode(object, bodyType, template);
    }
}

MultipartSupportConfig 文件

import feign.codec.Encoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public
class MultipartSupportConfig {
    @Bean
    public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
    }
}

实体类和客户端的Controller、FeignClient

实体类(试卷类,里面有试卷信息和试卷文件和若干试题图片)

public class PaperForm implements Serializable {
    private String modelId;
    private String paperCode;
    private String name;
    private MultipartFile file;
    private MultipartFile[] pictures;
    private String subjectId;
    private String subjectName;
    private String pageDate;
    private String description;
    private String createId;
    private String creator;
    private Integer createType;

    public String getPaperCode() {
        return paperCode;
    }

    public void setPaperCode(String paperCode) {
        this.paperCode = paperCode;
    }

    public MultipartFile[] getPictures() {
        return pictures;
    }

    public void setPictures(MultipartFile[] pictures) {
        this.pictures = pictures;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public MultipartFile getFile() {
        return file;
    }

    public void setFile(MultipartFile file) {
        this.file = file;
    }

    public String getSubjectId() {
        return subjectId;
    }

    public void setSubjectId(String subjectId) {
        this.subjectId = subjectId;
    }

    public String getSubjectName() {
        return subjectName;
    }

    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }

    public String getPageDate() {
        return pageDate;
    }

    public void setPageDate(String pageDate) {
        this.pageDate = pageDate;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getCreateId() {
        return createId;
    }

    public void setCreateId(String createId) {
        this.createId = createId;
    }

    public String getCreator() {
        return creator;
    }

    public void setCreator(String creator) {
        this.creator = creator;
    }

    public String getModelId() {
        return modelId;
    }

    public void setModelId(String modelId) {
        this.modelId = modelId;
    }

    public Integer getCreateType() {
        return createType;
    }

    public void setCreateType(Integer createType) {
        this.createType = createType;
    }

    @Override
    public String toString() {
        return "PaperForm{" +
                "modelId='" + modelId + '\'' +
                ", paperCode='" + paperCode + '\'' +
                ", name='" + name + '\'' +
                ", file=" + file +
                ", pictures=" + Arrays.toString(pictures) +
                ", subjectId='" + subjectId + '\'' +
                ", subjectName='" + subjectName + '\'' +
                ", pageDate='" + pageDate + '\'' +
                ", description='" + description + '\'' +
                ", createId='" + createId + '\'' +
                ", creator='" + creator + '\'' +
                ", createType=" + createType +
                '}';
    }
}

前端访问接口

@Controller
@RequestMapping("/paperFile")
public class FileUploadController {
    @Autowired
    PaperFileFeign paperFileFeign;

    @ResponseBody
    @PostMapping("/uploadPaper")
    public Result uploadPaper(@RequestParam("modelId") String modelId,
                                  @RequestParam("name") String name,
                                  @RequestParam("file") MultipartFile file,
                                  @RequestParam("pictures") MultipartFile[] pictures,
                                  @RequestParam("subjectId") String subjectId,
                                  @RequestParam("subjectName") String subjectName,
                                  @RequestParam("pageDate") String pageDate,
                                  @RequestParam("description") String description,
                                  @RequestParam("createType") Integer createType){
            //实体类  将表单请求转成json
            PaperForm paperForm=new PaperForm();
            paperForm.setModelId(modelId);
            paperForm.setName(name);
            paperForm.setFile(file);
            paperForm.setPictures(pictures);
            paperForm.setSubjectId(subjectId);
            paperForm.setSubjectName(subjectName);
            paperForm.setPageDate(pageDate);
            paperForm.setDescription(description);
            paperForm.setCreateType(createType);
            //获取当前登录用户
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            String createId =user.getId();
            String creator =user.getCode();
            paperForm.setCreateId(createId);
            paperForm.setCreator(creator);
            paperFileFeign.uploadPaper(paperForm);
            //这里我直接返回的成功,要调试不要这样搞。服务端异常也会返回成功
            return ResultUtil.createResult(200,"成功");
}

PaperFileFeign 通过feign进行请求转发。

import com.winfuture.config.MultipartSupportConfig;
import com.winfuture.data.Result;
import com.winfuture.model.bank.form.PaperForm;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;

//配置支持文件传输,configuration = MultipartSupportConfig.class
@FeignClient(value = "zuul",configuration = MultipartSupportConfig.class)
@Service
public interface PaperFileFeign {

     //配置支持文件传输 consumes = MediaType.MULTIPART_FORM_DATA_VALUE
    @PostMapping(value = "/bank/paper/uploadPaper", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    Result uploadPaper(PaperForm paperForm);
    }

服务端Controller

@Controller
@RequestMapping("/paper")
public class PapersController {

    //service层  自己的业务
    @Autowired
    PapersService papersService;


    /*上传试卷文件,管理员录入(基础题库,模拟题库)*/
    @PostMapping(value = "uploadPaper",produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result uploadPaper(PaperForm paperForm){
        try {
            String modelId = paperForm.getModelId();
            String name = paperForm.getName();
            MultipartFile file = paperForm.getFile();
            MultipartFile[] pictures =paperForm.getPictures();
            String subjectId=paperForm.getSubjectId();
            String subjectName=paperForm.getSubjectName();
            String pageDate = paperForm.getPageDate();
            String description =paperForm.getDescription();
            Integer createType = paperForm.getCreateType();
            String createId =paperForm.getCreateId();
            String creator =paperForm.getCreator();
            papersService.uploadPaper(modelId,name,file,pictures,subjectId,subjectName,pageDate,description,createType,createId,creator);
            return ResultUtil.createResult(200,"成功");
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.createResult(400,"异常");
        }
    }
}

记录一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值