• 前后端请求参数



    #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 ;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    前端

          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)
            })
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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)
            })
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    前端需要使用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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    @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)
            })
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
        @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    我的疑问:不进行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)
            })
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
        @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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)
            })
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
        @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方式二:采用对象封装

    后台接收数组
    注意: 这里并没有进行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)
            })
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public class Test {
        private List<String> names;
        private List<Integer> age;
        ...
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
        @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    由于是发送 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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    ###如何既有@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);
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

                  
                    
                    
    将文件拖到此处,或点击上传
    上传Excel格式文件
    确认上传 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 },
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    文件+参数
    方式一: 文件,参数分开,参数一个一个接收

    后端 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);
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
          // 用表单来初始化
          const param = new FormData();
          param.append("sourceFile",this.uploadFileForm.files)
            param.append("testName", allData.testName)
            testFileData(param).then(res=> {
              console.log(res)
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    需要设置 ‘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'
        }
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    方式二: 将接受的文件封装在对象内部

    如对象的形式

        @ApiModelProperty("自变量名称")
        private String variableName;
    
        @ApiModelProperty("因变量名称")
        private String  dependentVariableName;
    
    // 上传的文件
        @ApiModelProperty("源数据文件")
        private MultipartFile sourceFile;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    controller层用实体对象接受

         @ApiOperation(value = "文件数据进行一元回归测试")
        @PostMapping("/testFileData")
         public Result doFileData(SingleRegressionVo singleRegressionVo){
             System.out.println(singleRegressionVo.getSourceFile().getName());
             System.out.println(singleRegressionVo);
            return Result.ok(null);
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
          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)
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    文件单独,其余参数封装实体对象
         @ApiOperation(value = "文件数据进行一元回归测试")
        @PostMapping("/testFileData")
         public Result doFileData(SingleRegressionVo singleRegressionVo, MultipartFile sourceFile){
             System.out.println(singleRegressionVo);
             System.out.println(sourceFile.getName());
            return Result.ok(null);
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
      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)
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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,"
    "
    ) // console.log(word) // console.log(typeof (word)) this.resultTxt += word },
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    后端

    @RequestMapping

    标志类、方法的请求路径

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

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

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

    如果请求地址与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}">测试路径中的占位符-->/testResta><br>
    
    • 1
    @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
    
    • 1
    • 2
    • 3
    • 4

    获取参数

    三种方式获取
    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";
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

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

    如何传递数组?

    @RequestParam

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

    @RequestMapping("/list1")
    public String test1(int userId) {
      return "list";
    }
    @RequestMapping("/list2")
    public String test2(@RequestParam int userId) {
      return "list";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    不加@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();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    传递的 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();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

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

    require('@/assets/home/imgName.png')
    
    • 1
        //     查看实验结果
        @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());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    前端

    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)
            })
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    错误原因及解决方法:

    @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    前端

          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)
            })
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
        @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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //    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 ;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ##传递数组

    <template>
      <div class="single-container">
    
        <div class="step">
            <el-steps :active="0" align-center>
    
              <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文件,且不超过500kbdiv>
            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>
    
    
    
    
    
    
        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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
  • 相关阅读:
    Ps:移动工具
    JDK17 比较实用的更新
    Spring MVC BeanNameUrlHandlerMapping原理解析
    面试:“谈谈ArrayList和LinkdeList之间的区别?”,究竟有多少人回答错了?该怎么回答?
    Java BigDecimal 类的创建对象方法以及常用的加减乘除、设置精度方法
    二叉查找树、平衡二叉树、红黑二叉树简单概念
    点云从入门到精通技术详解100篇-基于点云和图像的智能交通路侧感知(续)
    OpenMV与I2C二线串行协议
    实验八—基本统计分析(一)
    JavaScript -- 08. 数组介绍
  • 原文地址:https://blog.csdn.net/weixin_42382758/article/details/126297584