前后端请求参数


#pic_center =400x
系列文章:



get请求 普通参数
后端:

    @GetMapping("/testGet")
    @ResponseBody
    public Result testGet(String name, String  age) {
    
    
        System.out.println(name);

        System.out.println(age);
        Result result = new Result().setCode("200").setMsg("查询成功").setData(name);
        return result ;
    }

前端

      testGet() {
        const name="ds"
        const age="12"
        this.$axios({
            method: 'get',
            url: "http://localhost:8080/SingleRegression/testGet",
          params: {name, age}
        }
        ).then(res=> {
          console.log(res)
        })
      },

postman测试
在这里插入图片描述

post请求普通string

      testPost() {
        // let age = []
        // let names = []
        //
        // for(let i=0; i< 10; ++i) {
        //   age.push(i)
        //   names.push("aaa"+i)
        // }
        const age=12
        const names="zhuyuanzhang"
        this.$axios(
            {
               method: 'post',
              headers: {'Content-Type': 'application/x-www-form-urlencoded'},
              url: "http://localhost:8080/SingleRegression/testPost",
              data: this.$qs.stringify({
                 age:age, names: names
              })
            }
        ).then( res => {
          console.log(res)
        })
      }

前端需要使用qs.stringify并且设置Content-type.使得发送到后端的数据以键值对形式发送
axios发送post请求,默认请求头类型是content-type类型是’application/json;charset=utf-8’.发给后端是json形式
axios配置请求头content-type

在这里插入图片描述

qs序列化数组

    @GetMapping("/testGet")
    @ResponseBody
    public Result testGet(String name, String  age) {
    
    
        System.out.println(name);
        System.out.println(age);
        Result result = new Result().setCode("200").setMsg("查询成功").setData(name);
        return result ;
    }

在这里插入图片描述
@RequestBody接收前端传来的多个参数-map表单

post请求传递数组

方式一:将数组转换为字符串,后端在解析字符串

注意点:前端必须使用qs.stringify,否则就400或者无法接受到参数
一旦使用qs.stringify 请求的content-type就不是默认的json形式,而是application/x-www-form-urlencoded

      testPost() {
        let age = []
        let names = []

        for(let i=0; i< 10; ++i) {
          age.push(i)
          names.push("aaa"+i)
        }
        age = age.join()//,分割
        names = names.join();
        this.$axios(
            {
               method: 'post',
              url: "http://localhost:8080/SingleRegression/testPost",
              data:
              this.$qs.stringify(
                  { "age":age, "names": names}
              )
            }
        ).then( res => {
          console.log(res)
        })
      },
    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestParam String names, @RequestParam String age) {
    
    
        String nameArr[] = names.split(",");
        String ageArr[] = age.split(",");
//        aaa0 aaa1 aaa2 aaa3 aaa4 aaa5 aaa6 aaa7 aaa8 aaa9
        for(String i: nameArr) {
    
    
            System.out.print(i+" ");
        }
        System.out.println();
//        0 1 2 3 4 5 6 7 8 9
        for (String i : ageArr) {
    
    
            System.out.print(i+" ");
        }
         Result result = new Result().setCode("200").setMsg("查询成功").setData(names);

        return result ;
    }

在这里插入图片描述
我的疑问:不进行qs为什么就是400??
后端用 public Result testPost(@RequestParam String names, @RequestParam String age)
Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter ‘names’ is not present]

下面的方式并未获取成功(请求正常通过,后端接收数据为Null),可能不知道前端是如何传递以及前端的content-type

      testPost() {
        let age = []
        let names = []
        for(let i=0; i< 10; ++i) {
          age.push(i)
          names.push("aaa"+i)
        }
        this.$axios(
            {
               method: 'post',
              url: "http://localhost:8080/SingleRegression/testPost",
              data:
              this.$qs.stringify(
                  { age:age, names: names}
              )
            }
        ).then( res => {
          console.log(res)
        })
      },
    @PostMapping("/testPost")
    @ResponseBody
//    这样并不能接收到names[] age[]
    public Result testPost(@RequestParam(value = "names[]", required = false) List<String>names,@RequestParam(value = "age", required = false) List<Integer> age) {
// 两者都是空值null
        System.out.println(names);
        System.out.println(age);
         Result result = new Result().setCode("200").setMsg("查询成功").setData(names);

        return result ;
    }

springmvc @RequestParam 接收数组

下面方式也未成功,前端请求发送失败400/415。
进行qs.stringify415,不进行是400

      testPost() {
        let age = []
        let names = []
        for(let i=0; i< 10; ++i) {
          age.push(i)
          names.push("aaa"+i)
        }
        this.$axios(
            {
               method: 'post',
              url: "http://localhost:8080/SingleRegression/testPost",
              data:
              // this.$qs.stringify(
                  { age:age, names: names}
              // )
            }
        ).then( res => {
          console.log(res)
        })
      }
    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestBody String[] names,@RequestBody String[] age) {
        System.out.println(names);
        System.out.println(age);
         Result result = new Result().setCode("200").setMsg("查询成功").setData(names);

        return result ;
    }

方式二:采用对象封装

后台接收数组
注意: 这里并没有进行qs.stringify
因为@RequestyBody一般用于处理非Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。
详解get与post请求方式、content-type与responseType、@Requestbody与@Requestparam的使用场景

      testPost() {
        let age = []
        let names = []
        for(let i=0; i< 10; ++i) {
          age.push(i)
          names.push("aaa"+i)
        }
        this.$axios(
            {
               method: 'post',
              url: "http://localhost:8080/SingleRegression/testPost",
              data: { "age":age, "names":names}

            }
        ).then( res => {
          console.log(res)
        })
      },
public class Test {
    private List<String> names;
    private List<Integer> age;
    ...
    
    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestBody Test test) {
    
    
    //[aaa0, aaa1, aaa2, aaa3, aaa4, aaa5, aaa6, aaa7, aaa8, aaa9]
        System.out.println(test.getNames());
        //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        System.out.println(test.getAge());
         Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
        return result ;
    }

在这里插入图片描述
由于是发送 json 数据 后台封装到对象 所以采用 raw 类型
在这里插入图片描述

方式三
不建议,url长度是有限的,放数组会超过限制
前端目前不知道把参数放在url中

    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestParam("names")List<String>names, @RequestParam("age")List<Integer>age) {
        System.out.println(age.size());
         Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
        return result ;
    }

在这里插入图片描述

###如何既有@RequestBody 又有@RequestParmas
vue【axios】get/post请求params/data传参总结

文件类型

单文件

接受单个文件,使用@Request Parma

//    上传文件接受 
    @ApiOperation(value = "用户上传文件上传文件接收")
    @PostMapping("/uploadDataFile")
    public Result acceptDataFile(@RequestParam("file") MultipartFile file) {
    
    

         String filename = file.getOriginalFilename();
        System.out.println(filename);
        }
}

前端分为手动上传、自动上传
自动上传 this.$refs.upload.submit();实现上传

              <el-upload
                         ref="upload" :limit="1"
                         :auto-upload="false"
                         action="http://localhost:40822/api/xjtu/singleRegression/uploadDataFile"
                         drag :multiple="false"  :file-list="fileList"
                         :on-change="handleChange"  accept=".xlsx, .xls"
                          :on-exceed="handleFileCountExceed"
                         :before-remove="beforeRemoveFile"
                         :before-upload="handleBeforeUpload">
                <i class="el-icon-upload"></i>
                <div >将文件拖到此处,或<em>点击上传</em></div>
                <div  slot="tip">上传Excel格式文件</div>
              </el-upload>
              <el-button type="primary" @click="confirmUpload()">确认上传</el-button>


handleFileCountExceed(files, fileList) {
        this.$message.warning(
          `只能上传 1 个文件,本次选择了 ${files.length} 个文件`
        )
      },
      //移除文佳提示
      beforeRemoveFile(file, fileList) {
        return this.$confirm(`确定移除 ${file.name}?`);
      },
      handlePreview(file) {
        console.log(file);
      },
      handleBeforeUpload(file) {
        const uploadLimit = 1
	      const uploadTypes = ['xlsx', 'xlx', 'XLSX', 'XLX']
      const filetype = file.name.replace(/.+\./, '')
      const isRightSize = (file.size || 0) / 1024 / 1024 < uploadLimit
      if (!isRightSize) {
        this.$message.error('文件大小超过 ' + uploadLimit + 'MB')
        return false
      }
      if (uploadTypes.indexOf(filetype.toLowerCase()) === -1) {
        this.$message.warning({
          message: '请上传后缀名为 xlsx, xlx, XLSX, XLX 的文件'
        })
        return false
      }
      return true
      },
      // 文件上传
      submitUpload() {
        this.$refs.upload.submit();
      },
      //文件改变
      handleChange(file, fileList) {
        this.uploadFileForm.files = file.raw
        this.fileList = fileList;
      },

      // 确认上传
      confirmUpload() {
        if(this.fileList.length<1) {
          this.$message.error("你还没有选择文件!!")
          return false
        }
        let param = new FormData();
        param.append("file", this.uploadFileForm.files)

        // this.fileList.forEach(
        //     (val, index) => {
        //       param.append("file", val.raw);
        //     }
        // );
        // acceptDataFile(param).then(res => {
        //   if (res.code === 200) {
        //     this.$message.info({
        //       message: "上传成功!",
        //       duration: 1000
        //     })
        //   }
        // })
        console.log(FileList)
        this.$message.info("正在上传")
         this.$refs.upload.submit();
        this.submitUpload()
        this.stepActive = 1

      },

文件+参数

方式一: 文件,参数分开,参数一个一个接收

后端 MultipartFile sourceFile,String testName,这里的sourceFile,testName要与前端对应

     @ApiOperation(value = "文件数据进行一元回归测试")
    @PostMapping("/testFileData")
     public Result doFileData( MultipartFile sourceFile,String testName){
         System.out.println("*******************************************");
         System.out.println(sourceFile.getName());
         System.out.println(testName);
        return Result.ok(null);
     }
      // 用表单来初始化
      const param = new FormData();
      param.append("sourceFile",this.uploadFileForm.files)
        param.append("testName", allData.testName)
        testFileData(param).then(res=> {
          console.log(res)
        })

需要设置 ‘content-type’: ‘multipart/form-data’

export function testFileData(dataInfo) {
  return request({
    url: `${BASE_URL}/singleRegression/testFileData`,
    method: 'post',
    data: dataInfo,
    headers: {
      'content-type': 'multipart/form-data'
    }
  })
}
方式二: 将接受的文件封装在对象内部

如对象的形式

    @ApiModelProperty("自变量名称")
    private String variableName;

    @ApiModelProperty("因变量名称")
    private String  dependentVariableName;

// 上传的文件
    @ApiModelProperty("源数据文件")
    private MultipartFile sourceFile;

controller层用实体对象接受

     @ApiOperation(value = "文件数据进行一元回归测试")
    @PostMapping("/testFileData")
     public Result doFileData(SingleRegressionVo singleRegressionVo){
    
    
         System.out.println(singleRegressionVo.getSourceFile().getName());
         System.out.println(singleRegressionVo);
        return Result.ok(null);
     }
      const param = new FormData();
      //这里只传递了实体部分参数testName, sourceFile
      param.append("sourceFile",this.uploadFileForm.files)
        param.append("testName", allData.testName)
        // 这里请求同方式一  设置 'content-type': 'multipart/form-data'
        testFileData(param).then(res=> {
    
    
          console.log(res)
        })
文件单独,其余参数封装实体对象
     @ApiOperation(value = "文件数据进行一元回归测试")
    @PostMapping("/testFileData")
     public Result doFileData(SingleRegressionVo singleRegressionVo, MultipartFile sourceFile){
    
    
         System.out.println(singleRegressionVo);
         System.out.println(sourceFile.getName());
        return Result.ok(null);
     }
  const param = new FormData();

      // param.append("allData", JSON.stringify(allData));
		// 名称前后端要对应
      param.append("sourceFile",this.uploadFileForm.files)
        param.append("testName", allData.testName)
        testFileData(param).then(res=> {
    
    
          console.log(res)
        })

Java 后端接收MultipartFile类型文件接口(带参与不带参)
前端文件上传及后端接收(el-upload标签的使用)

文件保存

SpringBoot上传文件并储存到本地(记录)

http请求参数方式类型Query String Parameters、Form Data、Request Payload的使用记录以及qs的使用

http请求参数方式类型Query String Parameters、Form Data、Request Payload的使用记录以及qs的使用

本地打开TXT加载

    <div >
      txt
      <input type="file" @change="loadTextFromFile">
      <div>
        <p v-html="resultTxt"></p>
      </div>
    </div>

       //txt文件读取
       loadTextFromFile: function(e) {
    
    
          const file = e.target.files[0];
          const reader = new FileReader();
          reader.onload = e => this.$emit("load", this.dealNum(e.target.result));
          reader.readAsText(file,"utf-8");
        },
        dealNum(item){
    
    
          let word = item.replace(/\n|\r\n/g,"<br/>")
          // console.log(word)
          // console.log(typeof (word))
          this.resultTxt += word
        },

后端

@RequestMapping

标志类、方法的请求路径

  • value属性:是个字符串数组,数组中每个字符串是请求地址,

如 @RequestMapping( value = {“/testRequestMapping”, “/test”} ) 表示/testRequestMapping以及/test都可以访问方法testRequestMapping()

@RequestMapping( value = {"/testRequestMapping", "/test"} )
public String testRequestMapping(){
 	return "success";
 }
  • method属性:是个RequestMethod类型数组,数组中每个元素是一种请求方式
    如下 请求方式get/post都可以
@RequestMapping( value = {"/testRequestMapping", "/test"}, method = {RequestMethod.GET, RequestMethod.POST} )
public String testRequestMapping(){
 	return "success";
  }

如果请求地址与value匹配,但是不与method匹配,会报错
405 Request method ‘XXXT’ not supported

  • 派生注解
    • get请求的映射–>@GetMapping
    • post请求的映射–>@PostMapping
    • put请求的映射–>@PutMapping
    • delete请求的映射–>@DeleteMapping
      备注:目前浏览器只支持 get、post,不支持put、delete
  • 路径参数
<a th:href="@{/testRest/1/admin}">测试路径中的占位符-->/testRest</a><br>
@RequestMapping("/testRest/{id}/{username}") 
public String testRest(@PathVariable("id") String id, @PathVariable("username")String username){ 
	System.out.println("id:"+id+",username:"+username); 
	return "success"; }//最终输出的内容为-->id:1,username:admin

获取参数

三种方式获取
HttpServletRequest
@RequestParam 只接受url里面的数据
@RequestBody 只接受body中数据

HttpServletRequest

封装了当前请求的请求报文对象

@RequestMapping("/testParam") public String testParam(HttpServletRequest request){ 						   									
	String username = request.getParameter("username"); 
	String password = request.getParameter("password");
	System.out.println("username:"+username+",password:"+password);
	return "success";
 }

通过控制器方法的形参获取请求参数

形参名称和前端参数名称相同,在DispatchServlet会将名称匹配的值赋值给形参

<a th:href="@{/testParam(username='admin',password=123456)}">测试获取请求参数-- >/testParam</a><br>
@RequestMapping("/testParam") 
public String testParam(String username, String password){
    
    
 	System.out.println("username:"+username+",password:"+password); 
 	return "success";
}

如何传递数组?

@RequestParam

参数来自url,一般用于get请求

@RequestMapping("/list1")
public String test1(int userId) {
    
    
  return "list";
}
@RequestMapping("/list2")
public String test2(@RequestParam int userId) {
    
    
  return "list";
}

不加@RequestParam

  • 要求前端参数和后端控制器的形参名相同
  • 改参数不是非必传
    加@RequestParam
  • 通过@RequestParam(“userId”) 或 @RequestParam(value=“userId”)使得前端参数和后端形参名称可以不一致
  • 参数是必传的, 可以通过@RequestParam(required=false)设置为非必传
  • @RequestParam(defaultValue = “0”)指定参数默认值

@RequestBody

@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。通常用于接收POST、DELETE等类型的请求数据,GET类型也可以适用。

@RequestBody 接收数组、List 参数

application/x-www-form-urlencoded与application/json

application/x-www-form-urlencoded:
这个是表单默认的编码方式,当请求方式为get时候,浏览器用x-www-form-urlencoded的编码方式把表单数据转换成一个字串(key=value),然后把这个字串append到url后面,用?分割,加载这个新的url。 当请求方式为post时候,浏览器把表单数据封装到http body中,然后发送到server

数据以键值对形式存在,键与值使用=连接,键值对之间使用&连接。不支持非字母数字(即不支持二进制数据,二进制数据应该使用multipart/form-data代替)
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST

application/json
这个编码方式就是将数据转换成json格式(json字符串),所以这就是为什么HttpServletRequest拿值为null、用@RequestParam获取为null的真凶

contentType:"application/x-www-form-urlencoded;charset=utf-8"你可以通过key去取value,就不会出现HttpServletRequest拿值为null、用@RequestParam获取为null的问题了。

前端传过给后台的数据是一个对象,那我们还是使用application/json传递,用@RequestBody获取,然后再用map对json数据进行一个拆分存储,方标使用

关于springmvc controller 获取前端转过来的值为null的那些坑

后端向前端传输文件

response.setContentType("text/html;charset=“utf-8”); 览器会将文件解析为text文件,
response.setContentType(“application/vnd.ms-excel”); 返回文件类型为Excel表格时
如果仅设置这一项就开始向前端返回文件时,文件名则为当前发送数据的Java类+setContentType(“”)中对应的文件后缀名,所以我们还需要设置发送时的文件名称:
response.setHeader(“content-disposition”,“attachment;filename=” + fileName);

        FileInputStream in = null;
        ServletOutputStream out = null;
//        in = new FileInputStream(picPath + "/result.png");
        in = new FileInputStream("E:\\code\\experiment\\back\\formal\\data\\statisticalAnalysis\\singleRegression\\target\\6\\2022-08-22-21-05-33"+"\\result.png");
        System.out.println(picPath);
        response.setContentType("application/octet-stream;charset=utf-8");

        response.setHeader("Content-disposition", "attachment;filename=result.png");
        out = response.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[2 * 1024];
        while ((len = in.read(buffer)) > 0) {
    
    
            out.write(buffer, 0, len);
        }
        out.flush();
        if(in!=null){
    
    
            in.close();
        }

传递的 responseType要是blob类型responseType: ‘blob’,
然后走window.URL.createObjectURL将其返回的数据处理一下window.URL.createObjectURL(res),
将处理好的数据放在img便签里面就成功了。

    //     查看实验结果
    @GetMapping("/getResultPic")
    public void getTestResult(HttpServletResponse response, @RequestParam(value = "picPath") String picPath) throws Exception {
    
    
        System.out.println(picPath);
        String fileUrl = picPath;
//        读取路径下的文件
        File file = new File(fileUrl);
        if (!file.exists()) {
    
    
            throw new Exception("文件不存在");
        }
        File picFile = null;
        for (File f : file.listFiles()) {
    
    
            //根据路径获取文件
            picFile = new File(f.getPath());
            //获取文件后缀名格式
            String ext = picFile.getName().substring(picFile.getName().indexOf("."));
            //判断图片格式,设置相应的输出文件格式
            if (ext.equals("jpg")) {
    
    
                response.setContentType("image/jpeg");
            } else if (ext.equals("JPG")) {
    
    
                response.setContentType("image/jpeg");
            } else if (ext.equals("png")) {
    
    
                response.setContentType("image/png");
            } else if (ext.equals("PNG")) {
    
    
                response.setContentType("image/png");
            }
        }
        //读取指定路径下面的文件
        InputStream in = new FileInputStream(picFile);
        OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
        //创建存放文件内容的数组
        byte[] buff = new byte[1024];
        //所读取的内容使用n来接收
        int n;
        //当没有读取完时,继续读取,循环
        while ((n = in.read(buff)) != -1) {
    
    
            //将字节数组的数据全部写入到输出流中
            outputStream.write(buff, 0, n);
        }
        //强制将缓存区的数据进行输出
        outputStream.flush();
        //关流
        outputStream.close();
        in.close();
    }

在这里插入图片描述

js代码里面 或者 html里面用"v-bind:“或”:属性名"绑定路径的时候使用

require('@/assets/home/imgName.png')
    //     查看实验结果
    @GetMapping("/getResultPic")

    public void getTestResult(HttpServletResponse response, @RequestParam(value = "picPath") String picPath) throws Exception {
    
    
        System.out.println(picPath);

        FileInputStream in = null;
        ServletOutputStream out = null;
        String filePath = picPath+"/result.png";
        in = new FileInputStream(filePath);

        response.setContentType(MediaType.IMAGE_PNG_VALUE);

        response.setHeader("Content-disposition", "attachment;filename=result.png");
         IOUtils.copy(in, response.getOutputStream());
    }

springboot实战代码之如何优雅地返回图片
在这里插入图片描述

postman

在postman中通过post方式请求需要关注的四要素包含:请求地址(url)+请求方法(post)+请求头域(Headers)+参数

请求地址的组成:http(协议类型)+服务器地址(域名)+接口地址(存放文件路径)+请求参数(手动在params中填写时,会自动填充这里)
请求方法选:post
请求头域:选择接口文档中Content-Type类型
参数填写:填写接口文档中的参数值

原文链接:https://blog.csdn.net/weixin_49044678/article/details/117030810

form-data

等价于http请求中的content-type=multipart/form-data,可以上传多文件,键值对。文件可以上传多个

x-www-form-urlencoded

等价于http请求中的content-type=application/x-www-from-urlencoded
会将表单内的数据转换为键值对
会隐藏url

raw

可以上传任意格式的文本,如txt, json,xml,html

binary

相当于Content-Type:application/octet-stream
只能上传二进制数据,通常上传文件,无键值对所以只能上传一个文件

传递参数的错误

Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported]

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported]

参考博客
错误的代码:
后端

    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestBody String[] names, @RequestBody String[] age) {
    
    
//        String names = request.getParameter("names");
//        String age = request.getParameter("age");
        System.out.println();
        System.out.println(names);

        System.out.println(age);

        Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
        return result ;
    }

前端

testPost() {
        let age = []
        let names = []

        for(let i=0; i< 10; ++i) {
          age.push(i)
          names.push("aaa"+i)
        }

        this.$axios(
            {
               method: 'post',
              // headers: {'Content-Type': 'application/x-www-form-urlencoded'},
              url: "http://localhost:8080/SingleRegression/testPost",
              data: 
                  { "age":age, "names": names}
            
            }
        ).then( res => {
          console.log(res)
        })
      }

错误原因及解决方法:

@RequestBody注解后 ,只能解析json类型的数据,而我的前后端传递的是数组,应该无法解析数组形式。

当把参数改成非数组形式的,如下正常的字符串,可以正常解析
默认情况下,使用axios请求默认数据类型是json,而使用@requestBody注解只解析json,这里把age和names进行了封装我后端使用两个@requestBody解析,得到的结果一样(age=12&names=zhuyuanzhang),都是封装后的

    @PostMapping("/testPost")
    @ResponseBody
    public Result testPost(@RequestBody String names, @RequestBody String age) {
//        String names = request.getParameter("names");
//        String age = request.getParameter("age");
        System.out.println();
        //输出结果相同
        System.out.println(names);// age=12&names=zhuyuanzhang
        System.out.println(age);// age=12&names=zhuyuanzhang
        Result result = new Result().setCode("200").setMsg("查询成功").setData(names);
        return result ;
    }

前端

      testPost() {
        const age="12"
        const names="zhuyuanzhang"
        this.$axios(
            {
               method: 'post',
              // headers: {'Content-Type': 'application/x-www-form-urlencoded'},
              url: "http://localhost:8080/SingleRegression/testPost",
              data: this.$qs.stringify(
                  { "age":age, "names": names}
              )
            }
        ).then( res => {
          console.log(res)
        })
      }
    @PostMapping("/testPost")
    @ResponseBody
//    自动封装对象,对象中的属性如age会自动赋值
//    Test{names='zhuyuanzhang', age=12}
    public Result testPost(@RequestBody Test test) {
    
    
         Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
        System.out.println(test);
        return result ;
    }
//    Test{names='null', age=0}
    public Result testPost( Test test) {
    
    
         Result result = new Result().setCode("200").setMsg("查询成功").setData(test);
        System.out.println(test);
        return result ;
    }

##传递数组

<template>
  <div class="single-container">

    <div class="step">
        <el-steps :active="0" align-center>
<!--          <el-step title="+新增实验"   finish-status="success"></el-step>-->
          <el-step title="导入数据" description="输入数据或者导入文件"></el-step>
          <el-step title="进行回归测试" description=""></el-step>
          <el-step title="结果可视化" description=""></el-step>
          <el-step title="导入数据库" description="选择是否保留到数据库"></el-step>

        </el-steps>
      </div>
    <div class="header">

      <div class="left">
        <el-input v-model="experimentName" placeholder="搜索实验名称" clearable prefix-icon="el-icon-search"
                  @keyup.enter="searchExperiment">
        </el-input>
      </div>

      <div class="right">
        <el-button type="primary" icon="el-icon-plus" @click="addExperiment">新增实验</el-button>
      </div>
    </div>



<!--    进行回归测试的界面-->
    <div class="test-contain" >
        <el-row >
          <el-col :span="12" :offset="2" style="color: #20a0ff">
            <el-form  label-width="350px" style="padding-top: 50px" >
            <el-form-item label="数据上传方式">
              <el-switch @change="uploadMethodRadioChange()" v-model="this.uploadMethodRadio"
                          active-color="#409EFF" inactive-color="#C0CCDA"
                         active-text="人工输入" inactive-text="文件上传" :active-value=true :inactive-value=false>
              </el-switch>
            </el-form-item>
          </el-form>
          </el-col>
        </el-row>

       <el-row style="height: 100%">

           <el-col  :span="12" :offset="2" >
           <el-form label-width="350px" style="padding-top: 50px"
                    v-show="this.uploadMethodRadio" :model="formData">
          <el-form-item label="实验名称" >
            <el-input placeholder="请输入实验名称" v-model="experimentName" ></el-input>
          </el-form-item>

          <el-form-item label="自变量名称">
            <el-input  placeholder="输入自变量名称" v-model="formData.variableName"></el-input>
          </el-form-item>

          <el-form-item label="因变量名称">
            <el-input placeholder="输入因变量名称" v-model="formData.dependentVariableName"></el-input>
          </el-form-item>

           <el-form-item label="测试数据量">
            <el-select  placeholder="请选择测试数据量"  v-model="formData.experimentDataCount"
                        @change ="onSelectChange">
             <el-option v-for="(item) in selectCount.experimentData" :key="item" :label="item" :value="item">
             </el-option>
            </el-select>
          </el-form-item>
           <el-form-item>
            <el-button type="primary" >下一步</el-button>
            <el-button>取消</el-button>
          </el-form-item>
         </el-form>
         </el-col>



       </el-row>

      <el-row style="height: 100%">

        <el-col :span="10" :offset="7" >
           <el-form  label-width="100px" style="padding-top: 50px" >
                <el-upload v-show="!this.uploadMethodRadio"
          class="upload-demo"
          action="https://jsonplaceholder.typicode.com/posts/"
          :on-preview="handlePreview"
          :on-remove="handleRemove"
          :before-remove="beforeRemove"
          multiple
          :limit="3"
          :on-exceed="handleExceed"
          :file-list="fileList">
          <el-button size="small" type="primary">点击上传</el-button>
          <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
        </el-upload>
        </el-form>
        </el-col>


      </el-row>




<!--      表单数据选择-->

    </div>

    <div class="data-contain">
      <el-row>
        <el-form>
          <el-form-iteml v-for="(item, index) in experimentDataArray" :key="index">
            <el-col :span="5" :offset="6"><el-input placeholder="输入因变" ></el-input> </el-col>
            <el-col :span="5"  > <el-input placeholder="输名称"></el-input></el-col>
          </el-form-iteml>
        </el-form>
      </el-row>
    </div>

<!--测试历史记录列表-->

    <div class="table-container" v-show="false">
      <el-table :data="testRecordData" style="width: 100%">
        <el-table-column prop="id" label="实验ID">
          <template slot-scope="scope">
            <span style="margin-left: 10px">{
   
   { scope.row.id }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="id" label="实验时间">
          <template slot-scope="scope">
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{
   
   { scope.row.testTime }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="实验名称">
          <template slot-scope="scope">
            <span style="margin-left: 10px">{
   
   { scope.row.testName }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="实验状态">
          <template slot-scope="scope">
            <el-tag v-show="scope.row.testStatus ===0 ">未开始</el-tag>
            <el-tag type="success" v-show="scope.row.testStatus ===1 ">已完成</el-tag>
            <el-tag type="warning" v-show="scope.row.testStatus ===2 ">进行中</el-tag>
            <el-tag type="danger" v-show="scope.row.testStatus ===3 ">失败</el-tag>

          </template>
        </el-table-column>
        <el-table-column label="操作" width="300">
          <template slot-scope="scope">
            <el-button type="primary" plain icon="el-icon-search" size="small"
                       @click="openDetail(scope.row)">
              查看
            </el-button>
            <el-popconfirm title="确定删除吗?" @onConfirm="deleteExperiment(scope.row)">
              <el-button type="danger" plain icon="el-icon-delete" slot="reference" size="small">
                删除
              </el-button>
            </el-popconfirm>
            <el-button plain icon="el-icon-document" size="small" @click="outData(scope.row)">导出
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination-container">
        <el-pagination background layout="total, prev, pager, next, jumper" :total="tableDataInfo.tableData.length"
                       :current-page.sync="paginationOptions.currentPage" :page-size="paginationOptions.pageSize">
        </el-pagination>
      </div>
    </div>

    <el-dialog title="一元回归实验参数" :visible.sync="formDialogVisible" width="70%" top="50px"
               custom-class="form-dialog-container" @close="clearOptions">
      <div class="form-dialog">
        <div class="left">
          <div class="experiment-name item">
            <div class="label">实验名称:</div>
            <div class="value">
              <el-input v-model="formData.experimentName" placeholder="输入实验名称" size="small">
              </el-input>
            </div>
          </div>
          <div class="experiment-name item">
            <div class="label">自变量名称:</div>
            <div class="value">
              <el-input v-model="formData.variableName" placeholder="输入自变量名称" size="small">
              </el-input>
            </div>
          </div>

          <div class="experiment-name item">
            <div class="label">因变量名称:</div>
            <div class="value">
              <el-input v-model="formData.dependentVariableName" placeholder="输入因变量名称" size="small">
              </el-input>
            </div>
          </div>

          <div class="res-count item">
            <div class="label">测试数据量:</div>
            <div class="value">
              <el-select v-model="formData.experimentDataCount" placeholder="测试数据量" size="small"
              @change ="onSelectChange" >
                <el-option v-for="(item) in selectCount.experimentData" :key="item" :label="item" :value="item">
                </el-option>
              </el-select>
            </div>
          </div>

          <div class="factor-level-table">

            <div class="right">
              <div class="top">
                <div style="width: 320px">
                  <div style="width: 160px; float:left;"><input type="text" v-model.number="this.formData.variableName"></div>
                <div style="width: 160px; float:right; "><input type="text" v-model.number="this.formData.dependentVariableName"></div>
                  <div style="width: 100%; height: 15px; margin: 5px; float:right;"></div>
                </div>
              </div>
              <div class="list" v-for="(item, index) in experimentDataArray" :key="index">
                <div class="list-item" v-for="(val, index) in item" :key="index">
                  <input type="number" v-model.number="val.value">
                </div>
              </div>
            </div>
          </div>
          <div class="create-table item">
            <div class="label"></div>
            <div class="value">
              <el-button type="primary" @click="createTable">进行一元回归
              </el-button>
            </div>
          </div>
        </div>
      </div>
<!--      <span slot="footer" class="dialog-footer">-->
<!--                <el-button @click="cancel">-->
<!--                    取 消</el-button>-->
<!--                <el-button type="primary" @click="handleSure">确 定-->
<!--                </el-button>-->
<!--      </span>-->
    </el-dialog>


  </div>

</template>

<script>
const letterMap = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'];

  export default {
      
      
    data() {
      
      
      return {
      
      
        //用户信息
        userInfo: {
      
      
          userId: '1'
        },
        //输入上传方式
        uploadMethodRadio: true,

        //测试状态 0尚未开始,1进行中,2已完成 3失败'
        testStatusList: [
          {
      
      type: 'success', label: '已完成'},
          {
      
      type: 'info', label: '未开始'},
          {
      
      type: 'warning', label: '失败'}
        ],
        //测试记录表数据
        testRecordData: [
          {
      
      
            testTime: '2022-5-9',
            testName: '温度湿度一元回归',

          }
        ],
        // 搜索实验名称
        experimentName: '',
        // 新增弹窗visible
        formDialogVisible: false,
        // 实验表弹窗
        experimentResultVisible: false,
        //下拉列表实验数据量
        selectCount: {
      
      
          experimentData: 10
        },
        formData: {
      
      
          //  实验名称
          experimentName: '',
          //  数据量数
          experimentDataCount: 10,
          //  自变量
          variableCount: 1,
          variableName: '自变量1',
          //  因变量
          dependentVariableName: '因变量'
        },
        //测试数据
         experimentDataArray:[],
        sampleData:{
      
      },
        //  实验表单数据
        tableDataInfo: {
      
      
          tableHeader: [
            'id', '自变量', '因变量'
          ],
          tableData: [
            [
              "1",
              "1",
              "8",
            ],
            [
              "2",
              "2",
              "16"
            ],
          ]
        },
        // 当前选择的实验数据
        currentExperimentData: {
      
      
          name: '',
          id: '',
          tableDataInfo: {
      
      
            tableHeader: [],
            tableData: []
          }
        },
        // 分页配置
        paginationOptions: {
      
      
          // 每页条数
          pageSize: 10,
          currentPage: 1,
        },
      }
    },
    created() {
      
      
      this.getRecordData()


    },
    computed: {
      
      

      // 当前页的表格数据
      currentPageData() {
      
      
        const {
      
      currentPage, pageSize} = this.paginationOptions;
        const start = (currentPage - 1) * pageSize;
        const end = (currentPage) * pageSize;
        const result = this.tableDataInfo.tableData.slice(start, end)
        return result
      },

    // // 因子映射
        factorMap() {
      
      
            return letterMap.map(item => {
      
      
                return {
      
       label: item }
            })
        },
   // 因子列表
        factorList() {
      
      
            return this.factorMap.slice(0, Number(this.formData.experimentDataCount))
        },
    },

    methods: {
      
      
      getRecordData() {
      
      
        this.$http({
      
      
          method: 'get',
          url: 'SingleRegression/find',
          params: {
      
      
            userId: this.userInfo.userId,
            offset: (this.paginationOptions.currentPage - 1) * (this.paginationOptions.pageSize),
            limit: this.paginationOptions.pageSize
          }

        }).then(res => {
      
      
          if (res.data.code != 200) {
      
      
            this.$message.error('出错啦')
          } else {
      
      
            this.testRecordData = res.data.data
            // console.log(this.testRecordData)
          }
        })
      },
      uploadMethodRadioChange() {
      
      
        this.uploadMethodRadio = !this.uploadMethodRadio
      },

      // 点击新增实验
      addExperiment() {
      
      
        this.formDialogVisible = true;
      },

      // 监听实验数据量变化
       onSelectChange(val) {
      
      
        const  result = [];
        const rowCount = this.formData.experimentDataCount;
        const arrRow = this.factorList.slice(0, rowCount);
        const colCount = this.formData.variableCount + 1;
        const arrCol = this.factorList.slice(0, colCount);
        console.log(arrRow)
        for (let i = 0; i < rowCount; ++ i) {
      
      
          if(!result[i]){
      
      
            result[i]=[]
          }
          for(let j = 0; j < colCount; ++ j){
      
      
            result[i].push(
                {
      
      
                  index: arrRow[i].label + arrCol[j].label,
                  value: '',
                }
            )
          }
        }
        this.experimentDataArray = result;
      },
      createTable() {
      
      

        const dataRow = this.experimentDataArray.length;
        const dataCol = this.formData.variableCount  +1
        const  xData = [];
        const yData = [];
        for (let i = 0 ; i < dataRow ; ++ i){
      
      
          for (let j = 0; j< dataCol -1  ; ++ j) {
      
      
            xData.push(this.experimentDataArray[i][j].value);
          }
          yData.push(this.experimentDataArray[i][dataCol-1].value)
        }
        const allData = {
      
      
          variableNameArray: [],
          dependentVariableName: this.formData.dependentVariableName,
          xData: xData,
          yData: yData
        }
        this.sampleData = allData;
         this.$message('正在进行测试');
         console.log(this.sampleData)

      },
// 清空配置
        clearOptions() {
      
      
        },
 // 查看按钮
        openDetail(row) {
      
      
            // this.experimentResultVisible = true;
            // this.currentExperimentData = Object.assign({}, row)
        },
        // 删除实验
        deleteExperiment(row) {
      
      
        },
        // 修改后的保存
        saveTable() {
      
      
        },
        // 导出
        outData(row) {
      
      
        },

      handleEdit(index, row) {
      
      
        console.log(index, row);
      },
      handleDelete(index, row) {
      
      
        console.log(index, row);
      }
    }
  }


</script>

<style lang='less' scoped>
  .step {
      
      
        width: 100%;
        align-content: center;
        padding: 20px;
        height: auto;
      }
.single-container {
      
      
    width: 100%;
    padding: 20px;
    background: #f3f4f6;

    .header {
      
      
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 20px;
        background: #fff;
    }

    .table-container {
      
      
        margin-top: 20px;
        padding: 20px;
        background: #fff;

        .el-table {
      
      
            height: 50vh;
            overflow: auto;

            /deep/ .el-button {
      
      
                margin-left: 8px;
            }
        }


        .test-contain {
      
      
          display: flex;
          padding: 20px;
          margin-top: 50px;
          background: #ffffff;
          margin-bottom: 20px;
          justify-content: space-between;

        }

        .pagination-container {
      
      
            margin-top: 20px;
            text-align: right;
        }
    }
}

</style>

<style lang="less">
.form-dialog-container {
      
      
    .el-dialog__body {
      
      
        paddin-top: 0;

        .form-dialog {
      
      
            display: flex;

            .left {
      
      
                flex: 0 0 50%;

                .item {
      
      
                    display: flex;
                    align-items: center;
                    margin-top: 14px;

                    .label {
      
      
                        width: 100px;
                        text-align: right;
                    }

                    .value {
      
      
                        width: 160px;
                        margin-left: 20px;
                    }
                }

                .factor-level-table {
      
      
                    display: flex;
                    margin-top: 14px;

                    .left {
      
      
                        flex: 0 0 60px;
                        margin-left: 54px;

                        .top {
      
      
                            // border-bottom: 1px solid rgb(118, 118, 118);
                            margin-bottom: 14px;
                        }

                        .list {
      
      
                            input {
      
      
                                width: 60px;
                            }
                        }
                    }

                    .right {
      
      
                        flex: 1 1 200px;
                        overflow: auto;
                        margin-right: 10px;

                        .top {
      
      
                            margin-bottom: 14px;
                        }

                        .list {
      
      
                            display: flex;

                            .list-item {
      
      
                                input {
      
      
                                    width: 160px;
                                }
                            }
                        }
                    }
                }
            }

            .right {
      
      
                flex: 1 1 50%;
                max-height: 50vh;
                overflow: auto;

                .right-table {
      
      
                    .table-row {
      
      
                        display: flex;

                        .table-cell {
      
      
                            width: 60px;
                            border: 1px solid #000;

                            input {
      
      
                                width: 60px;
                                border: none;
                                border-right: 1px solid #000;
                            }
                        }
                    }
                }
            }
        }
    }
}

.detail-dialog-container {
      
      
    .result-table {
      
      
        .table-row {
      
      
            display: flex;

            .table-cell {
      
      
                width: 60px;
                border: 1px solid #000;

                input {
      
      
                    width: 60px;
                    border: none;
                    border-right: 1px solid #000;
                }
            }
        }
    }
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_42382758/article/details/126297584