SpringBoot前后端接口对接常见错误小结

目录
  • 前言
  • 开始
    • 1.实体嵌套List提交
    • 2.普通文件上传
    • 3.List提交
    • 4.数组Array提交
    • 前端
    • 后端

前言

SpringBoot前后端接口对接工作时,经常遇到请求500,400等问题,马虎大意经常导致时间浪费,为此总结了4个常见的复杂请求类型,以此为戒。

开始

1.实体嵌套List提交

例子:提交一个老师的实体Teacher,老师管理着不同的学生,还要传入学生实体List <Student>
常见问题:提交异常,会报400错误
️正确前端代码

<button onclick="f1();" class="btn btn-primary">f1提交测试</button>
<script src="https://code.jquery.com/jquery.js"></script>
<script>
  const students = [{
        name: "王小明",
        age: "15",
    },{
        name: "李小红",
        age: "15",
    }]
    const teacher = {
        name: "张老师",
        age: "40",
        students:students
    }
    // 实体嵌套List提交
    function f1(){
        // 关键逻辑,需要转化成JSON字符串
        let data = JSON.stringify(teacher)
        $.ajax({
            type : 'post',
            url : '/f1',
            data : data,
            contentType:'application/json',
            success : function(resData) {
                console.log("f1调用成功" + resData)
                alert("f1调用成功" + resData);
            },
        });
    }
</script>

️正确后台接收

    /**
     * @Description 实体嵌套List提交
     * @param teacher
     * @Return java.lang.String
     */
    @PostMapping("/f1")
    @ResponseBody
    public String f1(@RequestBody Teacher teacher){
        return teacher.toString();
    }

2.普通文件上传

例子:普通input 文件上传通过onchange事件进行数据组装后,提交后台
常见问题:提交后,后台接收到的MultipartFile为空
️正确前端代码

<input type="file" name="f2" id="f2" onchange="f2()" multiple="multiple"></input>
<script src="https://code.jquery.com/jquery.js"></script>
<script>
    // 文件上传
    function f2(){
        let file = event.target.files[0];
        let formData = new FormData();
        formData.append('file', file);
        $.ajax({
            url: '/f2',
            type: 'post',
            contentType: false,  // ContentType设置成false
            processData: false, // 不需要让浏览器对FormData进行转换
            data: formData
        }).done(function (resData) {
            console.log("f2调用成功:" + resData)
            alert("f2调用成功:" + resData)
        })
    }
</script>

️正确后台接收

    /**
     * @Description 文件上传
     * @param file
     * @Return java.lang.String
     */
    @PostMapping("/f2")
    @ResponseBody
    public String f2(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }
        String fileName = file.getOriginalFilename();
        return fileName;
    }

3.List提交

例子:提交时,传给后台一个List
常见问题:提交异常,会报400错误
️正确前端代码

 <button onclick="f3();" class="btn btn-primary">f3提交测试</button>
<script src="https://code.jquery.com/jquery.js"></script>
<script>
    const teachers = [{
        name: "张老师",
        age: "40"
    },{
        name: "李老师",
        age: "35"
    }]
    // 直接提交List
    function f3(){
        // 关键逻辑,需要转化成JSON字符串
        let data = JSON.stringify(teachers)
        $.ajax({
            type : 'post',
            url : '/f3',
            data : data,
            contentType:'application/json',
            success : function(resData) {
                console.log("f3调用成功" + resData)
                alert("f3调用成功" + resData);
            },
        });
    }
</script>

️正确后台接收

    /**
     * @Description List实体上传
     * @param teachers
     * @Return java.lang.String
     */
    @PostMapping("/f3")
    @ResponseBody
    public String f3(@RequestBody List<Teacher> teachers) {
        return teachers.toString();
    }

4.数组Array提交

例子:提交时,传给后台一个Array
常见问题:提交异常,会报500错误
️正确前端代码

<button onclick="f4();" class="btn btn-primary">提交f4测试</button>
<script src="https://code.jquery.com/jquery.js"></script>
<script>
const array = [1,2,3,4]
// 直接提交数组
function f4(){
    $.ajax({
        type : 'post',
        url : '/f4',
        data : {
            array:array
        },
        dataType: 'json',
        success : function(resData) {
            console.log("f4调用成功" + resData)
            alert("f4调用成功" + resData);
        },
    });
}
</script>

️正确后台接收

    /**
     * @Description 数组上传
     * @param array
     * @Return java.lang.String
     */
    @PostMapping("/f4")
    @ResponseBody
    public int[] f4(@RequestParam(value = "array[]")int[] array) {
        return array;
    }

可视化代码

前端

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>请求列表</title>
    <link rel="shortcut icon" href="/static/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <table class="table">
        <caption style="text-align: center;"> <h2>SpringBoot常见出错请求</h2></caption>
        <thead>
        <tr>
            <th style="min-width: 40px">No</th>
            <th style="min-width: 140px">类型</th>
            <th style="min-width: 180px">描述</th>
            <th style="min-width: 100px">常见问题</th>
            <th>参数Data</th>
            <th>请求代码</th>
            <th>后端代码</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <tr class="active">
            <td>f1</td>
            <td>实体嵌套List提交</td>
            <td>
                <div>
                    适用于请求时,一个实体嵌套这一个list。</br>
                    举例:提交一个老师的实体Teacher,老师管理着不同的学生,还要传入学生实体List &lt;Student&gt;
                </div>
            </td>
            <td>提交异常,会报400错误</td>
            <td>
               <pre id="f1Text">
{
  "name": "张老师",
  "age": "40",
  "students": [
    {
      "name": "王小明",
      "age": "15"
    },
    {
      "name": "李小红",
      "age": "15"
    }
  ]
}
               </pre>
            </td>
            <td>
                <pre id="f1Code">
 function f1(){
    // 关键逻辑,需要转化成JSON字符串
    let data = JSON.stringify(teacher)
    $.ajax({
        type : 'post',
        url : '/f1',
        data : data,
        contentType:'application/json',
        success : function(resData) {
            console.log("f1调用成功" + resData)
            alert("f1调用成功" + resData);
        },
    });
}
                </pre>
            </td>
            <td>
                <pre id="f1Java">
@PostMapping("/f1")
@ResponseBody
public String f1(@RequestBody Teacher teacher){
    return teacher.toString();
}
                </pre>
            </td>
            <td>
                <button onclick="f1();" class="btn btn-primary">f1提交测试</button>
            </td>
        </tr>
        <tr class="success">
            <td>f2</td>
            <td>文件上传</td>
            <td>适用于原生文件上传,onchange后数据组装</td>
            <td>提交时后台接收的MultipartFile为空</td>
            <td>
                <pre id="f2Text">file: (binary)</pre>
            </td>
            <td>
                <pre id="f2Code">
function f2(){
    let file = event.target.files[0];
    let formData = new FormData();
    formData.append('file', file);
    $.ajax({
        url: '/f2',
        type: 'post',
        contentType: false,  // ContentType设置成false
        processData: false, // 不需要让浏览器对FormData进行转换
        data: formData
    }).done(function (resData) {
        console.log("f2调用成功:" + resData)
        alert("f2调用成功:" + resData)
    })
}

                </pre>
            </td>
            <td>
                <pre id="f2Java">
@PostMapping("/f2")
@ResponseBody
public String f2(@RequestParam("file") MultipartFile file) {
    if (file.isEmpty()) {
        return "上传失败,请选择文件";
    }
    String fileName = file.getOriginalFilename();
    return fileName;
}
                </pre>
            </td>
            <td>
                <input type="file" name="f2" id="f2" onchange="f2()" multiple="multiple"></input>
            </td>
        </tr>

        <tr class="active">
            <td>f3</td>
            <td>上传List</td>
            <td>
                <div>
                    适用于请求时,直接传一个List实体。</br>
                </div>
            </td>
            <td>提交异常,会报400错误</td>
            <td>
               <pre id="f3Text">
[{
    name: "张老师",
    age: "40"
},{
    name: "李老师",
    age: "35"
}]
               </pre>
            </td>
            <td>
                <pre id="f3Code">
 function f3(){
    // 关键逻辑,需要转化成JSON字符串
    let data = JSON.stringify(teachers)
    $.ajax({
        type : 'post',
        url : '/f3',
        data : data,
        contentType:'application/json',
        success : function(resData) {
            console.log("f3调用成功" + resData)
            alert("f3调用成功" + resData);
        },
    });
}
                </pre>
            </td>
            <td>
                <pre id="f3Java">
@PostMapping("/f3")
@ResponseBody
public String f3(@RequestBody List&lt;Teacher&gt; teachers) {
    return teachers.toString();
}
                </pre>
            </td>
            <td>
                <button onclick="f3();" class="btn btn-primary">f3提交测试</button>
            </td>
        </tr>

        <tr class="success">
            <td>f4</td>
            <td>上传数组Array</td>
            <td>适用于请求时,直接传一个数组。</td>
            <td>提交异常,会报500错误</td>
            <td>
                <pre id="f4Text">[1,2,3,4]</pre>
            </td>
            <td>
                <pre id="f4Code">
function f4(){
    $.ajax({
        type : 'post',
        url : '/f4',
        data : {
            array:array
        },
        dataType: 'json',
        success : function(resData) {
            console.log("f4调用成功" + resData)
            alert("f4调用成功" + resData);
        },
    });
}
                </pre>
            </td>
            <td>
                <pre id="f4Java">
@PostMapping("/f4")
@ResponseBody
public int[] f4(@RequestParam(value = "array[]")int[] array) {
    return array;
}
                </pre>
            </td>
            <td>
                <button onclick="f4();" class="btn btn-primary">提交测试</button>
            </td>
        </tr>
        </tbody>
    </table>
</div>
<!-- jQuery (Bootstrap 的 JavaScript 插件需要引入 jQuery) -->
<script src="https://code.jquery.com/jquery.js"></script>
<script>
    const students = [{
        name: "王小明",
        age: "15",
    },{
        name: "李小红",
        age: "15",
    }]
    const teacher = {
        name: "张老师",
        age: "40",
        students:students
    }
    // F1 Json数据格式化
    $('#f1Text').html(JsonFormat(teacher));

    // 实体嵌套List提交
    function f1(){
        // 关键逻辑,需要转化成JSON字符串
        let data = JSON.stringify(teacher)
        $.ajax({
            type : 'post',
            url : '/f1',
            data : data,
            contentType:'application/json',
            success : function(resData) {
                console.log("f1调用成功" + resData)
                alert("f1调用成功" + resData);
            },
        });
    }
    // 文件上传
    function f2(){
        let file = event.target.files[0];
        let formData = new FormData();
        formData.append('file', file);
        $.ajax({
            url: '/f2',
            type: 'post',
            contentType: false,  // ContentType设置成false
            processData: false, // 不需要让浏览器对FormData进行转换
            data: formData
        }).done(function (resData) {
            console.log("f2调用成功:" + resData)
            alert("f2调用成功:" + resData)
        })
    }

    const teachers = [{
        name: "张老师",
        age: "40"
    },{
        name: "李老师",
        age: "35"
    }]
    // 直接提交List
    function f3(){
        // 关键逻辑,需要转化成JSON字符串
        let data = JSON.stringify(teachers)
        $.ajax({
            type : 'post',
            url : '/f3',
            data : data,
            contentType:'application/json',
            success : function(resData) {
                console.log("f3调用成功" + resData)
                alert("f3调用成功" + resData);
            },
        });
    }
    const array = [1,2,3,4]
    // 直接提交数组
    function f4(){
        $.ajax({
            type : 'post',
            url : '/f4',
            data : {
                array:array
            },
            dataType: 'json',
            success : function(resData) {
                console.log("f4调用成功" + resData)
                alert("f4调用成功" + resData);
            },
        });
    }

    // Json格式化工具
    function JsonFormat(json) {
        if (typeof json != 'string') {
            json = JSON.stringify(json, undefined, 2);
        }
        json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
        return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
            var cls = 'number';
            if (/^"/.test(match)) {
                if (/:$/.test(match)) {
                    cls = 'key';
                } else {
                    cls = 'string';
                }
            } else if (/true|false/.test(match)) {
                cls = 'boolean';
            } else if (/null/.test(match)) {
                cls = 'null';
            }
            return '<span class="' + cls + '">' + match + '</span>';
        });
    }
</script>
<style>
    pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
    .string { color: green; }
    .number { color: darkorange; }
    .boolean { color: blue; }
    .null { color: magenta; }
    .key { color: red; }
    .container{
        width: 1900px;
    }
</style>
</body>
</html>

后端

package net.javadog.requestdemo.controller;

import net.javadog.requestdemo.entity.Teacher;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 请求管理
 *
 * @author hdx
 * @version V1.0
 * @date 2021年10月18日
 */
@Controller
public class RequestController {
    @GetMapping("/request")
    public String request(){
        return "request/index";
    }

    /**
     * @Description 实体嵌套List提交
     * @param teacher
     * @Return java.lang.String
     */
    @PostMapping("/f1")
    @ResponseBody
    public String f1(@RequestBody Teacher teacher){
        return teacher.toString();
    }

    /**
     * @Description 文件上传
     * @param file
     * @Return java.lang.String
     */
    @PostMapping("/f2")
    @ResponseBody
    public String f2(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }
        String fileName = file.getOriginalFilename();
        return fileName;
    }

    /**
     * @Description List实体上传
     * @param teachers
     * @Return java.lang.String
     */
    @PostMapping("/f3")
    @ResponseBody
    public String f3(@RequestBody List<Teacher> teachers) {
        return teachers.toString();
    }

    /**
     * @Description 数组上传
     * @param array
     * @Return java.lang.String
     */
    @PostMapping("/f4")
    @ResponseBody
    public int[] f4(@RequestParam(value = "array[]")int[] array) {
        return array;
    }
}

到此这篇关于SpringBoot前后端接口对接常见错误小结的文章就介绍到这了,更多相关SpringBoot前后端接口对接 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot连接MySQL获取数据写后端接口的操作方法

    1.新建项目 2.添加依赖 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> <dependency> <groupId>org.springframework</groupId>

  • SpringBoot实现接口等幂次校验的示例代码

    目录 主流的实现方案如下: 第一步:书写redis工具类 第二步.书写token工具类 第三步:定义注解,使用在方法上,当控制层的方法上被注释时,表示该请求为等幂性请求 第四步:拦截器配置.选择前置拦截器,每次请求都校验到达的方法上是否有等幂性注解,如果有则进行token校验 第五步:对拦截器进行url模式匹配,并注入spring容器 第六步:控制层 接口等幂性通俗的来说就是同一时间内,发起多次请求只有一次请求成功:其目的时防止多次提交,数据重复入库,表单验证网络延迟重复提交等问题. 比如: 订

  • SpringBoot实现文件上传接口

    摘要 公司都是采用SpringBoot作为项目框架,其实SpringBoot和SSM框架很接近,基本上只是将SSM的一些配置项修改为自动配置或者简单的注解配置就可以了,建议不了解的SpringBoot的朋友们可以了解一下,上手很快,其实文件上传框架根本没有多大关系.我只是顺便帮SpringBoot打个广告罢了. 正题 需求:需要实现一个文件上传的web接口. 1.先实现一个Controller接口,如下: package com.lanxuewei.utils.aspect; import co

  • springboot利用aop实现接口异步(进度条)的全过程

    目录 一.前言 二.时序图 三.功能演示 四.关键代码 Controller AsyncAop AsyncService 五.源码地址 总结 一.前言 在项目中发现有接口(excel导入数据)处理数据需要耗时比较长的时间,是因为数据量比较大,同时数据的校验需要耗费一定时间,决定使用一种通用的方法解决这个问题. 解决方案:通过aop使接口异步处理,前端轮询另外一个接口查询进度. 目标: 1接口上一个注解即可实现接口异步(优化:可以通过header参数动态控制是否异步) 2一个方法实现进度条的更新

  • SpringBoot微信消息接口配置详解

    1.申请测试号,并记录appID和appsecret 2.关注测试号 3.添加消息模板 {{topic.DATA}} 用户名: {{user.DATA}} 单车编号:{{car.DATA}} 锁定时间:{{date.DATA}} {{remark.DATA}} 微信接口配置和代码 1.添加微信配置文件 import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframe

  • SpringBoot接口接收json参数解析

    目录 SpringBoot接口接收json参数 前言 前提 一.GET 二.DELETE 三.POST/PUT/PATCH Springboot restFul 参数检验 概述 常用注解 简单应用举例 自定义校验 抛出BindException而非MethodArgumentNotValidException SpringBoot接口接收json参数 前言 通常来讲,HTTP 方法会映射为 CRUD 动作,但这并不是严格的限制,有时候 PUT 也可以用来创建新的资源,POST 也可以用来更新资源

  • SpringBoot设置接口超时时间的方法

    SpringBoot设置接口访问超时时间有两种方式 一.在配置文件application.properties中加了spring.mvc.async.request-timeout=20000,意思是设置超时时间为20000ms即20s, 二.还有一种就是在config配置类中加入: public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configureAsyncSupport(fin

  • springboot post接口接受json时,转换为对象时,属性都为null的解决

    目录 背景 解决心路历程 背景 在接口请求过程中,传递json对象,springboot转换为实体VO对象后,所有属性都为null. post请求: 后台接收请求: 当时就懵逼了- 解决心路历程 查看springboot默认的HttpMessageConverter @Configuration @Component public class AppWebConfiguration implements WebMvcConfigurer { /** * 重写添加拦截器方法并添加配置拦截器 * *

  • SpringBoot前后端接口对接常见错误小结

    目录 前言 开始 1.实体嵌套List提交 2.普通文件上传 3.List提交 4.数组Array提交 前端 后端 前言 SpringBoot前后端接口对接工作时,经常遇到请求500,400等问题,马虎大意经常导致时间浪费,为此总结了4个常见的复杂请求类型,以此为戒. 开始 1.实体嵌套List提交 例子:提交一个老师的实体Teacher,老师管理着不同的学生,还要传入学生实体List <Student>常见问题:提交异常,会报400错误️正确前端代码 <button onclick=&

  • 部署vue+Springboot前后端分离项目的步骤实现

    单页应用 vue经常被用来开发单页应用(SinglePage Web Application,SPA),什么叫做单页应用呢,也就是只有一张web页面的应用,单页应用的跳转只需要刷新局部资源,大大加快的了我们页面的响应速度 前端页面打包 打开vue工程,在项目根目录下创建一个配置文件:vue.config.js,然后在里面写入以下内容: module.exports = { assetsDir: 'static', // 静态资源保存路径 outputDir: 'dist', // 打包后生成的文

  • Vue+SpringBoot前后端分离中的跨域问题

    在前后端分离开发中,需要前端调用后端api并进行内容显示,如果前后端开发都在一台主机上,则会由于浏览器的同源策略限制,出现跨域问题(协议.域名.端口号不同等),导致不能正常调用api接口,给开发带来不便. 封装api请求 import axios from 'axios' //axios.create创建一个axios实例,并对该实例编写配置,后续所有通过实例发送的请求都受当前配置约束 const $http = axios.create({ baseURL: '', timeout: 1000

  • SpringBoot前后端json数据交互的全过程记录

    目录 一.参考文献 二.勇敢尝试 三.最终选择交互方式 总结 一.参考文献 原生Ajax与JQuery Ajax SpringMVC接受JSON参数详解及常见错误总结 提交方式为 POST 时, JQuery Ajax 以 application/x-www-form-urlencoded 上传 JSON对象 , 后端用 @RequestParam 或者Servlet 获取参数. JQuery Ajax 以 application/json 上传 JSON字符串, 后端用 @RquestBody

  • SpringBoot前后端分离实现验证码操作

    目录 1.SpringBoot版本 2.引入依赖 3.实现思路 新建验证码枚举类 定义验证码配置信息 定义验证逻辑生成类 在控制层上定义验证码生成接口 效果体验 在前端调用接口 1.SpringBoot版本 本文基于的Spring Boot的版本是2.6.7 . 2.引入依赖 captcha一款超简单的验证码生成,还挺好玩的.还有中文验证码,动态验证码. .在项目中pom.xml配置文件中添加依赖,如下: <!--验证码--> <dependency> <groupId>

  • SpringBoot前后端分离解决跨域问题的3种解决方案总结

    目录 什么是跨域 跨域问题的解决策略 三种解决方法 总结 什么是跨域 想要知道什么是跨域的话,我们可以通过一个小案例简单了解一下跨域的概念:在项目代码编写的时候,我们将前端项目代码和后端的项目代码相分离开,一个运行在本地的8080端口一个运行在本地的8888端口,这也就是我们常说的前后端分离项目.现在使用前端的请求去调用后端的接口,就会产生以下的错误 Access to XMLHttpRequest at 'http://localhost:8888/请求名' from origin ‘http

  • vue+springboot前后端分离实现单点登录跨域问题解决方法

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘. 刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)...,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑. 我面临的第一个问题是跨域,浏览器控制台直接报CORS,

  • shiro整合springboot前后端分离

    本文实例为大家分享了shiro整合springboot前后端分离的具体代码,供大家参考,具体内容如下 1.shiro整合springboot的配置 package com.hisi.config; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.session.mgt.eis.MemorySessionDAO; import org

  • springBoot前后端分离项目中shiro的302跳转问题

    springBoot前后端分离项目shiro的302跳转 项目是使用的springboot ,使用的shiro做的用户鉴权.在前端请求时当用户信息失效,session失效的时候,shiro会重定向到配置的login.jsp 页面,或者是自己配置的logUrl. 因是前后端分离项目,与静态资源文件分离,固重定向后,接着会404. 经过查找网上配置资料,发现302原因是 FormAuthenticationFilter中onAccessDenied 方法做了相应处理.那知道问题所在,就可以有解决方了

  • AJAX SpringBoot 前后端数据交互的项目实现

    目录 1.Ajax概述 2.基于JQuery的AJAX语法 1. Ajax 概述 Ajax 的英文全称是 ”Asynchronous JavaScript and XML“,即 ”异步的 JavaScript 和 XML“.其核心是通过 JavaScript 的 XMLHttpRequest 对象,以一种异步的方式,向服务器发送数据请求,并且通过该对象接收请求返回的数据,从而实现客户端与服务器端的数据交互. 优点:Ajax 能够刷新指定的页面区域(局部刷新),而不是刷新整个页面,从而减少客户端和

随机推荐