使用Ajax向后台传参数

一般来讲传参数项目用到的是三种,一种是简单类型,一种是对象类型要转化成JSON字符串,一种是文件类型,后台如果不是特别注意的,不会在这里讲,因为接口写起来还是很简单的,@Controller,@RequestMapping,@ResponseBody,@RequestParam都很简单,唯一可能要注意的就是@RequestBody,但是其实用法也很简单,这里不细讲。

1. 简单类型

简单类型顾名思义就是number类型,String类型这样的,Boolean类型,这种在java和js里都是基本类型,而不是引用类型,使用也是最简单的

 function getData(uname, age) {
    return new Promise(((resolve, reject) => {
      $.ajax({
        url: "/myController/testAjax3",
        type: "GET",
        data: {
          "uname": uname,
          "age": age
        },
        /*success和error都是ajax的属性应该写在ajax里面*/
        success: function (result) {
          switch (result.code) {
            case 200:
              resolve(result.data);
              break;
            case 500:
              resolve("服务器错误");
              break;
          }
        },
        error:
            function () {
              reject("请求不成功");
            }
      });
      /*console应该写在Promise里面ajax外面*/
      console.log("limaosheng");
    }));
  }

 大部分都不需要设置,设置一下url,如果没有获取本机ip地址的方法,url得“/”开头,前台一定是跟后台接口对应好,比如我下面的后台接口,需要uname,age,那么我的前台传的data,是键值对方式对应好即可。其余的成功之后做什么操作,看项目要求,另外我前台使用了promise所以reslove(data)不可缺少,reject也不可缺少,这个对于结果没有任何影响,也可以不使用,如果是稍微大点的项目建议使用。

  @RequestMapping(value = "testAjax3")//这样的produces可以传中文
  public AjaxResult testAjax3(String uname, Integer age) {
    System.out.println("响应Ajax请求" + uname + ":" + age);
    return AjaxResult.ok("成功");
  }

 另外对于一个对象也可以这么传递,前提是这个对象的成员变量是基本类型,比如这样

下面是基本类型和对象一起传,肯定也可以分开

 function test1() {
      return new Promise(((resolve, reject) => {
        $.ajax({
          type: "get",
          /* url: "../../static/data.json",
           dataType: "json",*/
          url: "/factor/getParticleFlowByLimit1",
          data: {
            "filePath": `D:\\mydatabase\\copernicus\\2019\\01\\mercatorglorys12v1_gl12_mean_20190108_R20190109.nc`,
            "variableName": "current",
            "startLon": 180,
            "endLon": -165,
            "startLat": 23,
            "endLat": 52,
            "level": 0,
            "dilution": 10,
            "exaggerate": 100
          },
          success: function (response) {
            switch (response.code) {
              case 0:
                resolve(response.data);
                console.log("这是数据2");
                console.log(response);
                console.log(response.data);

              
              case 500:
                resolve("服务器错误");
                break;
            }
          },
          error: function () {
            reject("请求不成功");
          }
        });
      }));
    }

后台接口

可以看到传了FactorCondition对象和基本类型String,int,同样的在前台使用“键名”:值的方式可以传进来

 @RequestMapping(value = "getParticleFlowByLimit1")
  @ResponseBody
  public AjaxResult getParticleFlowByLimit1(@RequestParam("filePath") String filePath,
                                            FactorCondition factorCondition,
                                            int dilution,
                                            int exaggerate) {
    try (NetcdfFile ncFile = NetcdfFile.open(filePath)) {
      FlowData uu = factorService.getParticleFlowDataOfFlowByLimit1(ncFile, factorCondition.getStartLon(), factorCondition.getEndLon(),
          factorCondition.getStartLat(), factorCondition.getEndLat(), factorCondition.getLevel(), UU, dilution, exaggerate);
      FlowData vv = factorService.getParticleFlowDataOfFlowByLimit1(ncFile, factorCondition.getStartLon(), factorCondition.getEndLon(),
          factorCondition.getStartLat(), factorCondition.getEndLat(), factorCondition.getLevel(), VV, dilution, exaggerate);
      List<Float> data = new ArrayList<>();
      for (int i = 0; i < uu.getData().size(); i++) {
        if (uu.getData().get(i) != null || vv.getData().get(i) != null) {
          data.add((float) Arith.round(Math.sqrt(Math.pow(uu.getData().get(i), 2) + Math.pow(vv.getData().get(i), 2)), 4));
        } else {
          data.add(0f);
        }
      }

      Float[] floats = MathUtils.minAndMax(data);
      System.out.println("Arrays.toString(floats) = " + Arrays.toString(floats));
      Object[] objects = {uu, vv, data};
      return AjaxResult.success(objects);
    } catch (Exception e) {
      e.printStackTrace();
      return AjaxResult.error("获取nc文件失败");
    }
  }

 附上对象详细信息,使用了Lombok,如果没有Lombok也可以不使用,这完全不影响

@Data
@NoArgsConstructor
@AllArgsConstructor
public class FactorCondition {
  private String variableName;
  private Float startLon;
  private Float endLon;
  private Float startLat;
  private Float endLat;
  private Integer level;
}

2. 传递对象

这里指的对象是指对象里面不是基本类型而是其他各种引用类型,对于这种只能转换成JSON字符串格式进行传递,

前台

$('#btn1').click(function () {
    return new Promise(((resolve, reject) => {
          let ncData = {
            dataType: 'BOOLEAN',
            dimensions: 1

          };
          console.log(getContextPath());
          $.ajax({
            type: "post",
            url: "/testLee/url",
            data: JSON.stringify(ncData),
            contentType: "application/json;charset=utf-8",
            success: function (result) {
              switch (result.code) {
                case 200:
                  resolve(result.data);
                  break;
                case 500:
                  resolve("服务器错误");
                  break;
              }
            },
            error:
                function () {
                  reject("请求不成功");
                }
          });
          console.log("zao");
        }
    ));
  });

先自己把对象封装好,然后使用

JSON.stringify(ncData)方法将对象转化成字符串,注意要写contenttype,我这里写的是
"application/json;charset=utf-8",用于传递对象

后台

@RequestMapping("/url")
  @ResponseBody
  public AjaxResult getUrl(
                           @RequestBody NcData ncData) throws InterruptedException {
    System.out.println("ncData = " + ncData);

    System.out.println("ncData.getDataType() = " + ncData.getDataType());
    //System.out.println("ncData.getData1D().length = " + ncData.getData1D().length);
    Thread.sleep(2 * 1000);
    return AjaxResult.ok("成功");
  }

唯一要注意的要使用注解@RequestBody

NcData成员变量

@Data
@NoArgsConstructor
@AllArgsConstructor
public class NcData {

  /**
   * 维度
   * 指决定该变量数据的维度
   * 维度为 1,data1D 有值,data2D 为 null
   * 维度不为 1(>= 2),data1D 为 null,data2D 有值(务必遵循)
   */
  private int dimensions;

  /**
   * 数据类型
   * nc基本数据类型有六种:boolean,byte,char,short,int,long,float,double
   * 用的是{@link DataType}
   */
  private DataType dataType;

  private float[] data1D;    //float类型的一维数组

  private float[][] data2D;    //float类型的二维数组

Datatype是一个引用类型,不是基本类型

更麻烦一点一个复杂对象和基本类型掺和起来

前台

 $('#btn1').click(function () {
    return new Promise(((resolve, reject) => {
          let ncData = {
            dataType: 'BOOLEAN',
            dimensions: 1

          };
          console.log(getContextPath());
          $.ajax({
            type: "post",
            url: "/testLee/url?a=10&b=20",
            data: JSON.stringify(ncData),
            contentType: "application/json;charset=utf-8",
            success: function (result) {
              switch (result.code) {
                case 200:
                  resolve(result.data);
                  break;
                case 500:
                  resolve("服务器错误");
                  break;
              }
            },
            error:
                function () {
                  reject("请求不成功");
                }
          });
          console.log("zao");
        }
    ));
  });

就改了url,因为不能json字符串和基本类型掺和,所以只能将基本类型写在url里面去传参,至于为什么这么写,他也是键值对,url后面接一个?再接键值对,键是a和b值分别是10,20,一个键值对用等号连接,多个键值对之间用“&”连接,

后台还是很简单的

  @RequestMapping("/url")
  @ResponseBody
  public AjaxResult getUrl(@RequestParam("a") String a,
                           @RequestParam("b") int b,
                           @RequestBody NcData ncData) throws InterruptedException {
    System.out.println("ncData = " + ncData);

    System.out.println("ncData.getDataType() = " + ncData.getDataType());
    //System.out.println("ncData.getData1D().length = " + ncData.getData1D().length);
    Thread.sleep(2 * 1000);
    return AjaxResult.ok(a + b);
  }

 对象如果是个数组

function getEddyCenter() {
  let filePath = [];
  filePath.push("D:\\mydatabase\\change-Anticyclonic_20160515.nc");
  filePath.push("D:\\mydatabase\\change-Cyclonic_20160515.nc");
  return new Promise(((resolve, reject) => {
    $.ajax({
      type: "POST",
      url: "/featureVisual/getEddyOfGlobe",
      data: {
        "filePath": filePath
      },
      datatype: "json",
      traditional: true,// 必须指定为true
      success: function (response) {
        switch (response.code) {
          case 0:
            resolve(response.data);
            break;
          case 500:
            console.log(("服务器错误"));
            alert("文件可能不存在");
        }
      },
      error: function (error) {
        reject("请求不成功");
      }
    });
  }));
}

 注意还是“键”:值的方式,

但是注意datatype和traditional要设置

后台很简单就用数组接收就可以了

@RequestMapping(value = "/getEddyOfPet")
  @ResponseBody
  @RequestBody
public AjaxResult getArrays(String[] arrays){
    //这个时候已经得到了arrays数组值
    //利用Array类中的toString方法
	//调用Array.toString(a),返回一个包含数组元素的字符串,这些元素被放置在括号内,并用逗号分开
   System.out.println(Arrays.toString(arrays));
	//输出:[1, 2, 3]
    return AjaxResult.ok(arrays[0]) ;
}

3. 文件传递

文件传递要注意的是html和js和后台,都不太一样

 <input id="dataRestor" accept=".sql" type="file" onchange=fileUpload()>

先得有上传文件的输入框

这是最基本的样式,然后不好看,我一般使用button按钮或者其他的去联动,因为原生的input实在太丑,思路就是input隐藏,当点击按钮的时候去触发input即可。

 <a class="btn btn-success" id="btn-upload">
        <i class="fa fa-upload"></i> 上传
      </a>

<form enctype="multipart/form-data" style="display: none">
        <input type="file" id="file-input" name="file" style="display: none" multiple="multiple"/>
      </form>

multiple是设置上传一个还是允许多个,也可以设置上传整个文件夹,大差不差就是个参数问题

js部分

function uploadFile(file) {
  return new Promise((resolve, reject) => {
    $.ajax({
      type: 'POST',
      url: '/fileManage/esa/uploadMultiFile',
      data: file,
      contentType: false,
      processData: false,
      success(result) {
        switch (result.code) {
          case 0:
            alert("上传成功");
            resolve(result.data);
            console.log(result.data);
            break;
          case 301:
            alert("因为存在同名文件所以上传部分成功");
            resolve(result.data);
            console.log(result.data);
            break;
          case 500:
            console.log(result.data);
            reject(result.message);
            alert(`Fail Insert file!`);
            break;
        }
      }
    });
  });
}

//  进行上传
$('#btn-upload').click(function () {
  $('#file-input').trigger('click');
});

$('#file-input').change(() => {
  let file = new FormData();
  console.log($('#file-input')[0].files.length);
  for (let i = 0; i < $('#file-input')[0].files.length; i++) {
    file.append("file", $('#file-input')[0].files[i]);
  }
  /*console.log(file);
   file.append('file', $('#file-input')[0].files[0]);*/
  uploadFile(file).then(() => {
    clearInputFile(document.getElementById('file-input'));
  });
});

/**
 * 用于清除上传文件缓存
 * @param dom 必须传原生获取的dom,用于清除input的缓存,触发change事件
 */

function clearInputFile(dom) {
  let form = document.createElement('form');
  document.body.appendChild(form);
  let pos = dom.nextSibling;
  form.appendChild(dom);
  form.reset();
  pos.parentNode.insertBefore(dom, pos);
  document.body.removeChild(form);
}

使用formdata对象通过键值对方式将文件信息存入对象中,

data里面千万别加{},因为formdata已经是一个对象了,在加{},会有问题,clearInputFile用于清缓存,可以两次上传一样的文件,我这个是允许上传多个文件,用的for循环,文件有多个但是键值只有一个,只不过value是一个文件数组。

后台

/**
   * 上传多个文件
   *
   * @param file 文件
   * @return
   */
  @ResponseBody
  @RequestMapping("/uploadMultiFile")
  @Log(title = "上传ECMWF文件", businessType = BusinessType.OTHER, isSaveRequestData = false)
  public AjaxResult uploadMultiFile(MultipartFile[] file) {
    try {
      int success = 0;
      for (MultipartFile multipartFile : file) {
        if (Objects.requireNonNull(multipartFile.getOriginalFilename()).contains(".nc")) {
          String times = StringUtils.getContinuityNum(Objects.requireNonNull(multipartFile.getOriginalFilename()), 8);
          String year = times.substring(0, 4);
          String month = times.substring(4, 6);
          String destFile = String.join(File.separator, applicationProperties.getDataDir(), ECMWF, year, month);
          int i = ncUploadService.ncFileUpload(multipartFile, destFile);
          User sysUser = ShiroUtils.getSysUser();
          if (i == 1) {
            String filPath = String.join(File.separator, destFile, multipartFile.getOriginalFilename());
            Upload ncUploadFile = ncUploadService.getNcUpload(filPath,sysUser.getUserName(),Integer.valueOf(String.valueOf(sysUser.getUserId())));
            uploadService.insertUpload(ncUploadFile);
          }
          success = success + i;
        } else {
          multipartFile.transferTo(Paths.get(String.join(File.separator, applicationProperties.getDataDir(), multipartFile.getOriginalFilename())));
          success++;
        }
      }
      if (success == file.length) {
        return AjaxResult.success("上传成功");
      } else {
        return AjaxResult.warn("部分数据未上传成功或者本地有缓存数据!");
      }
    } catch (Exception e) {
      e.printStackTrace();
      return AjaxResult.error("上传失败");
    }
  }

具体的逻辑就不用看了,主要看参数名是file要和formdata的键一样,另外可能input的name也要一样,这个没有试验过,如果有试验的可以告诉我一下,是否input的name要一样才行,另外@Log是我自己定义的也跟能否传进来无关

最后

我现在常用的是这几个,然后我看网上还有很多组合,文件加对象再加基本类型,或者文件加一个成员变量不是基本类型的对象比如Date类型,上面的可能是不够的,然后好像大多数都是用formdata一个一个传,再统一传给后台。

另外希望这篇博客可以帮到你!

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值