Spring boot + vue前后端数据传输的实现方法

后端解决跨域问题:

在项目中新建配置类文件:

//解决跨域问题
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry){
        registry.addMapping("/**")  //规定哪些目录可以跨域访问
                .allowedOrigins("http://localhost:5173", "http://localhost:8080") // 允许特定的源模式
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")           //允许哪些方法
                .allowCredentials(true);    //访问时需要验证
    }
}
这段代码是使用Java Spring框架中的WebMvcConfigurer接口来配置跨域资源共享(CORS)的一个例子。
 CORS是一个W3C标准,它允许或限制哪些源可以访问你的资源。
在前后端分离的开发模式中,前端应用可能需要从不同的源(域名、协议或端口)请求后端服务,这时就需要配置CORS。
这段代码的配置做了以下几件事情:
  1. addCorsMappings(CorsRegistry registry):这个方法用于添加CORS映射,即定义哪些路径可以被跨域访问。 registry.addMapping("/**"):这行代码指定了所有路径(/**)都可以被跨域访问。
  2. .allowedOrigins("http://localhost:5173", "http://localhost:8080"):这行代码设置了允许跨域请求的源,即只有来自http://localhost:5173和http://localhost:8080的请求才会被接受。
  3. .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS"):这行代码指定了允许的HTTP方法,包括GET、POST、PUT、DELETE和OPTIONS。 .allowCredentials(true):这行代码允许了凭证(如Cookies、HTTP认证等)在跨域请求中被发送。

后端默认端口号为8080,也可以在applocation.properties或者applpcation.yml文件中配置

后端controller层提供调用接口:

"/admin/login/status":是接口名称,前端只需发送http://localhost:8080/admin/login/status请求即可调用该接口

注解解释:

  1. @PostMapping 注解:用途:用于声明一个方法处理HTTP POST请求。
  2. @GetMapping:用于映射HTTP GET请求
  3. @PutMapping:用于映射HTTP PUT请求,通常用于更新资源。
  4. @DeleteMapping:用于映射HTTP DELETE请求,通常用于删除资源。
  5. @PatchMapping:用于映射HTTP PATCH请求,用于执行部分更新操作。
  6. @RequestBody:用于将HTTP请求体绑定到Controller方法的参数上。通常与@PostMapping@PutMapping@PatchMapping一起使用。
  7. @ResponseBody:用于将Controller方法的返回值作为HTTP响应体。在Spring 5之前,这个注解经常使用,但在Spring 5中,@RestController注解可以自动应用@ResponseBody到所有方法上,所以现在较少单独使用。
  8. @RestController:是一个组合注解,相当于@Controller@ResponseBody的组合。用于声明一个类,其所有方法的返回值都将作为HTTP响应体。

前端解决跨域问题:

前端解决跨域问题就是使用axios库来配置HTTP请求在我的这篇文章中有详细写道,里面使用的封装方法不太规范,只用于演示,大家可以根据自己需要进行更改。前端通过封装的方法就可以调用后端的接口

后端数据封装:

数据封装通常指的将接收到的数据(如前端传递的JSON对象)转换为后端可以处理的格式,比如Java对象(Java Bean)。这个过程通常涉及到以下几个步骤:

  1. 接收JSON数据:后端服务通过HTTP请求接收前端发送的JSON格式数据。

  2. 解析JSON:使用JSON解析器将JSON字符串转换为后端语言的数据结构,如在Java中通常转换为对象或Map。

  3. 数据封装:将解析后的数据封装成后端业务逻辑所需的格式,这可能涉及到创建对象、转换数据类型、验证数据完整性和正确性等。

  4. 处理业务逻辑:使用封装好的数据执行业务逻辑。

  5. 返回响应:将处理结果封装成JSON或其他格式,返回给前端。

比如说我要封装一个java的数据对象singer,那么就要求前端传递一个json对象

pojo层代码如下:

@TableName(value = "singer")
@Data
public class Singer {
       private Integer id;
       private String name;
       private Byte sex;
       /*头像*/
       private String pic;
       /*生日 。*/
       // 使用 @JsonFormat 解析 JSON 中的日期格式
//用于指定如何将 Java 对象的属性序列化成 JSON 字符串,以及如何从 JSON 字符串反序列化成 Java 对象的属性。
       @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
       private Date birth;
       /*地区*/
       private String location;
       /*简介*/
       private String introduction;
}

controller层代码如下:

/*添加歌手*/
    @PostMapping("/addSinger")
    public Result addSinger(@RequestBody Singer singer){
//注解RequestBody把前端输入数据存储到params数组中 
// 保存 singer 到数据库
        boolean flag=singerService.insert(singer);
        // 返回成功信息
        if(flag){
//            保存成功
            return Result.success(singer);
        }else {
            return Result.error("插入失败");
        }
    }
  • @RequestBody:这个注解告诉 Spring MVC,参数 singer 应该绑定到 HTTP 请求的 body 上。Spring 会自动将请求体中的 JSON、XML 或其他格式的数据转换成指定的对象类型。

  • Singer:这是要绑定的数据类型,表示请求体中的数据应该符合 Singer 类的属性结构。
    即前端传递的json对象的data中的属性名要与Singer对象中的属性名一一对应。
    Singer 常包含一些属性,如姓名、年龄、地区等,这些属性与请求体中的数据结构相匹配。

  • singer:这是方法参数的名称,它将接收转换后的 Singer 对象。

返回响应:将处理结果封装成JSON或其他格式,返回给前端。Result方法如下:

//pojo层
//统一响应结果
@NoArgsConstructor  //无参数的构造方法
@AllArgsConstructor //全参的构造方法
@Data
public class Result<T> {
    private Integer code;//业务状态码 1-成功 0-失败
    private String message;//提示信息
    private T data;//响应数据
    //快速返回操作成功响应结果(带响应数据)
    public static <E> Result<E> success(E data){
        return new Result<>(1,"操作成功",data);
    }
    //快速返回操作成功响应结果
    public static Result success(){
        return new Result(1,"操作成功",null);
    }

    public static Result error(String message){
        return new Result(0,message,null);
    }
}

前端发送的JSON格式数据:

本片文章第二节前端解决跨域问题中我们在http文件中定义了post请求,但是我们默认的axios请求头有些问题无法直接传输json对象,后端无法接收这个请求头。

我们需要把默认请求头改为headers = {'Content-Type': 'application/json'}

  • Content-Type:这是一个HTTP请求头字段,用于指定发送给服务器的内容的媒体类型(也称为MIME类型)。

  • application/json:这是一个媒体类型,表示发送给服务器的内容格式为JSON。当你的请求体中包含JSON格式的数据时,应该设置这个值。这告诉服务器,你正在发送的数据是JSON格式的,服务器应该相应地解析它。

//封装post方法
export function post2json(url,data={},headers = {'Content-Type': 'application/json'}){
    return new Promise((resolve,reject)=> {
        axios.post(url,data,{ headers })
        .then(response=>{
            //成功的回调
            //response是一个名字,随便起,它代表了服务器响应的所有数据,包含响应头,响应体.response.data代表的是接口响应的核心数据
            resolve(response.data);
        })
        .catch(err=>{
            //失败的回调
            reject(err);
        })

    });
}

定义接口:

//添加歌手
export const addSinger=(params)=>post2json(`singer/addSinger`,params);

前端实现:

//双向绑定示例
<template>
  <!-- 使用表单数据 -->
  <form @submit.prevent="handleSubmit">
    <input v-model="registerForm.name" type="text" placeholder="Name" />
    <input v-model="registerForm.sex" type="text" placeholder="Sex" />
    <!-- 其他表单字段 -->
    <button type="submit" @click="addSingerbt">Register</button>
  </form>
</template>

<script setup>
import { reactive, ref } from "vue";
import { addSinger } from "@/api";
import { ElMessage } from "element-plus";


//双向绑定
//在 Vue 3 中,reactive 是一个用于创建响应式对象的函数,这意味着当对象的属性发生变化时,Vue 会自动更新与这些属性绑定的 DOM。
let registerForm = reactive({
  name: "",
  sex: "",
  birth: "",
  location: "",
  introduction: "",
});


const registerForms = ref(null);
const addSingerbt = () => {
  if (registerForms.value) {//表单验证,防止空数据传输
    registerForms.value.validate((valid) => {
      if (valid) {
        let d = registerForm.birth;
//获取当前日期对象 d 的年份、月份和日期。
//将月份加1,以得到正确的月份表示。
//将年、月、日拼接成一个字符串,格式为“年-月-日”。
        const datetime = `${d.getFullYear()} - ${d.getMonth() + 1}- ${d.getDate()}`;
       
     //   构建参数为JSON对象,参数名与后端保持一致。从双向绑定的表单中获取数据
        const params = {
          name: registerForm.name,
          sex: Number(registerForm.sex),
          pic: "/img/singerPic/txdefault.jpg", // 使用默认头像
          birth: datetime,
          location: registerForm.location,
          introduction: registerForm.introduction,
        };
        // 调用 API 添加歌手
        addSinger(params)
          .then((res) => { //添加成功响应
            if (res.code == 1) {
              ElMessage({
                message: "添加成功",
                type: "success",
                plain: true,
              });
            } else {
                ElMessage({
                message: "添加失败",
                type: "error",
                plain: true,
              });
            }
          })
          .catch((err) => {//添加失败响应
            ElMessage({
                message: "添加失败",
                type: "error",
                plain: true,
              });
            console.log(err);
          }); 
      } else {//表单验证失败
        ElMessage({
                message: "表单验证失败,请补全信息",
                type: "error",
                plain: true,
                offset:90,
              });
        console.error("表单验证失败,请补全信息");
        return false;
      }
    });
  } else {
    console.error("表单没有找到");
  }
};
</script>

 补充:

同样的我们还有其他的注解来获取前端传递的单一的属性值:

/*根据主键查询整个对象*/
    @GetMapping("/selectByPrimarykey")
    public Result selectByPrimarykey(@RequestParam("id") Integer id){
     // 从前端传入的 JSON 中获取 id
        if (id == null) {
            return Result.error("查询失败,ID 为空");
        }
        // 调用服务层的查询方法
        try {
            // 调用服务层的查询方法
            return Result.success(singerService.selectByPrimaryKey(id));
        } catch (Exception e) {
            return Result.error("查询失败,原因:" + e.getMessage());
        }
    }
  • @RequestParam:这个注解表明后面的参数应该从HTTP请求的参数中获取值。

  • "id":这是请求参数的名称。在这个例子中,它告诉Spring MVC,我们希望获取名为id的请求参数。

如果请求的URL包含像?id=123这样的查询参数,那么id参数的值(在这个例子中是123)将被自动解析并绑定到方法的id参数上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值