前后端分离: vue3+SpringBoot+ElementPlus+Axios+MyBatisPuls

前后端分离: vue3+SpringBoot

  • 项目介绍
  • 搭建Vue前端工程
    • axios请求响应拦截
    • 跨域
  • 搭建后端
    • @TableId,@TableName
    • 分页显示
    • 配置Druid数据源
    • 带条件的分页查询
    • 后端校验
    • lambda表达式说明

项目介绍

🌟项目页面

在这里插入图片描述


🌟技术栈:
1.前端技术栈: Vue3+Axios+ElementPlus
2.后端技术栈: SpringBoot+MyBatisPlus
3.数据库: MySQL
4.项目依赖管理: Maven
5.分页: MyBatisPlus的分页插件
6.切换数据源DruidDataSource
7.在LambdaQueryWrapper 引出知识点 lambda方法引用的 类名::实例方法
8.前端使用了axios关于request和respones的拦截器, 并且解决了跨域问题

gitee网址: https://gitee.com/zhao-zhiwei521/vue-springboot

搭建Vue前端工程

一,SSM整合-前后端分离(项目环境搭建)
二,SSM项目-前后端分离(搭建Vue前端工程)

vue create springboot_vue

axios请求响应拦截

//重要提示: 如果在启动前端项目时, 提示找不到axios, 把光标放在 import axios from "axios"的'axios', 会有一个修复提示, 导入axios, 导入即可正常使用.
import axios from 'axios'const axios_ = axios.create({timeout: 5000
})//添加请求拦截器
axios_.interceptors.request.use(config => {//在请求之前请求头转为json数据config.headers['Content-Type'] = 'application/json;charset=utf-8'return config
}, error => {return Promise.reject(error)
})//添加响应拦截器
axios_.interceptors.response.use(response => {console.log('response======>', JSON.stringify(response))let res = response.data;//如果返回的是文件if (response.config.responseType === 'blob') {return res;}//如果是string类型, 就转为jsonif (typeof res === 'string') {res = res ? JSON.parse(res) : res;}return res;
}, error => {return Promise.reject(error);
})export default axios_

跨域

module.exports = {devServer: {port: 10000, // 前端开发服务器运行端口(通过 http://localhost:10000 访问)proxy: {      // 代理配置(用于解决开发环境跨域问题)'/api': {   // 拦截所有以 /api 开头的请求target: 'http://localhost:9090/', // 后端服务地址(对应您的 Spring Boot 应用)changeOrigin: true, // 修改请求头中的 Origin 为目标地址(模拟同源请求)pathRewrite: {'^/api': '' // 路径重写:移除请求路径中的 /api 前缀}}}}
}

搭建后端

SSM整合-前后端分离(实现增删改查)

在这里插入图片描述

@TableId,@TableName

//如果SysUser实体类名和数据库表名一致,或者经过驼峰换转后一致, 则不需要加@TableName注解
@Data
//@TableName("sys_user")
public class SysUser {//这里我们使用@TableId, 表主键标识//当我们在private Integer id上标识了@TableId, 说明id对应的就是表的id字段, 而且是主键@TableId(value = "id", type = IdType.AUTO)private Integer id;
}

分页显示

思路:
1.后台使用mybatis-plus分页插件
2.前端使用vue分页组件

实现
1.src/main/java/com/zzw/springboot/config/MybatisPlusConfig.java

@Configuration
public class MybatisPlusConfig {/*** 1.注入MybatisPlusInterceptor 对象/bean* 2.在MybatisPlusInterceptor bean 加入分页插件 PaginationInnerInterceptor*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//这里的分页要指定数据库的类型,因为不同的数据库,分页的sql语句不一样mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
}

2.SysUserController 分页查询

//前后端分离, 前端发出请求, 后端返回json数据
@Slf4j
@RestController
@RequestMapping("/sysUser")
public class SysUserController {@Autowiredprivate SysUserService sysUserService;/**** @param pageNum 显示第几页, 默认为 1* @param pageSize 每页有多少条 默认为10* @return*/@GetMapping("listByPage")public Result listByPage(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {//1.在javaweb中, 分页查询已经学过Page<SysUser> page = sysUserService.page(new Page<>(pageNum, pageSize));//2.返回数据, 查询分页查询的数据结构return Result.success(page);}
}

3.vue分页组件

<el-paginationv-model:current-page="searchForm.currentPage"v-model:page-size="searchForm.pageSize":total="total":page-sizes="[10, 20, 50, 100]"layout="total, sizes, prev, pager, next, jumper"@size-change="handleSizeChange"@current-change="handleCurrentChange"
/>

在这里插入图片描述

配置Druid数据源

参考整合Druid到SpringBoot

带条件的分页查询

@GetMapping("listByCondition")
public Result listByCondition(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize,SysUser sysUser) {//1.先床啊进QueryWrapper, 可以将我们的检索条件封装进QueryWrapperQueryWrapper<SysUser> wrapper = new QueryWrapper<>();// 根据用户名模糊查询if (StringUtils.hasText(sysUser.getUsername()) ) {wrapper.like("username", sysUser.getUsername());}Page<SysUser> page = sysUserService.page(new Page<>(pageNum, pageSize), wrapper);return Result.success(page);
}

后端校验

/*** 验证表单*/
private Map<String, Object> validateForm(Errors errors) {Map<String, Object> errorMap = new HashMap<>();List<FieldError> fieldErrors = errors.getFieldErrors();for (FieldError fieldError : fieldErrors) {errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());}return errorMap;
}
}@PostMapping("/save")public Result save(@RequestBody @Validated SysUser sysUser, Errors errors) {Map<String, Object> map = validateForm(errors);if (!map.isEmpty()) {return Result.error(map, "数据校验失败");}boolean save = sysUserService.save(sysUser);if (save) {return Result.success("添加成功");}return Result.error("添加失败");}

lambda表达式说明

https://baijiahao.baidu.com/s?id=1652786021461159890&wfr=spider&for=pc

https://blog.csdn.net/hjl21/article/details/102702934

解读

//编写方法,使用lambdaQueryWrapper封装查询条件, 完成检索
@GetMapping("listByCondition2")
public Result listByCondition2(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize,SysUser sysUser) {//说明: 关于lambda表达式, 我们这里使用的是 类名::实例方法//是lambda方法引用中不太好理解的//解读//1. SysUser::getUsername 通过lambda表达式 引用实例方法 getUsername//2. 这里就是把 SysUser::getUsername 赋给 SFunction<T,R> 函数式接口//3. 查看 SFunction<T,R> 源代码/*** @FunctionalInterface* public interface SFunction<T, R> extends Function<T, R>, Serializable {* }* 父接口*@FunctionalInterface* public interface Function<T, R> {*      R apply(T t);//抽象方法, 表示根据类型T的参数, 获取类型R的结果**      //这里有默认实现方法* }*///4.传入 SysUser::getUsername 后, 就相当于实现了 SFunction<T,R> 的apply方法//5.底层会根据 传入的 SysUser:getUsername 去得到该方法的对应的属性映射的表的字段, 更加灵活//<resultMap id="BaseResultMap" type="com.zzw.springboot.bean.SysMenu">//        <id column="id" jdbcType="INTEGER" property="id"/>//创建lambdaQueryWrapper, 封装查询条件LambdaQueryWrapper<SysUser> lambdaQueryWrapper = Wrappers.<SysUser>lambdaQuery();//判断if (StringUtils.hasText(sysUser.getUsername())) {//lambdaQueryWrapper.like(SysUser::getUsername, sysUser.getUsername());//换一个写法, 依然正确SFunction<SysUser, Object> sf = SysUser::getUsername;;lambdaQueryWrapper.like(sf, sysUser.getUsername());}Page<SysUser> page = sysUserService.page(new Page<SysUser>(pageNum, pageSize), lambdaQueryWrapper);log.info("page={}", page);return Result.success(page);
}

模拟实现src/main/java/com/zzw/springboot/lambda/Test.java

public class Test {public static void main(String[] args) {//传统的方法来实现ZzwFuntcion接口, 使用匿名内部类, 得到一个实现接口的对象/*** class Test$1 implements ZzwFunction<AClass, Object> {*     public Object apply (Aclass aclass) {*          return "Aclass";*     }* }* Test$1 test$1 = new Test$1();* test$1.apply(new Aclass());*///ZzwFunction<AClass, String> zf = new ZzwFunction<AClass, String>() {//    @Override//    public String apply(AClass aClass) {//        return "AClass";//    }//};//Object result = zf.apply(new AClass());//System.out.println("result=" + result);ZzwFunction<AClass, String> zf2 = AClass::getBrand;Object result2 = zf2.apply(new AClass());System.out.println("result2=" + result2);//zf2.say();}
}//定义一个函数式接口: 有且只有一个抽象方法的接口
//可以使用@FunctionalInterface 来标识一个函数式接口
//ZzwFunction是一个函数式接口(这个是一个自定义泛型接口)
@FunctionalInterface
interface ZzwFunction<T,R> {R apply(T t);//抽象方法: 表示根据类型T的参数, 获取类型R的结果//函数式接口, 依然可以有多个默认是先方法default public void say() {System.out.println("hello");}
}class AClass {//Beanprivate String name = "lambda AClass";private String brand = "奔驰品牌";public String getName() {return name;}public String getBrand() {return brand;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/80849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

序列密码算法ShanLooog512设计原理详解

序列密码算法ShanLooog512设计原理详解 ShanLooog512(闪龙512)为序列密码算法&#xff0c;内部状态为512比特&#xff0c;密钥长度为128或256比特&#xff0c;轮函数为FFFFFFFF&#xff0c;循环轮数为24轮&#xff0c;输出密钥流为512比特的状态。与Salsa20类似&#xff0c;内…

Matplotlib可视化基础

1. 折线图 matplotlib.pyplot.plot() # 主要参数&#xff1a; x,y -- 接收array&#xff0c;表示X轴和Y轴对应的数据&#xff0c;无默认 color -- 接收特定string&#xff0c;指定线条的颜色&#xff0c;默认为None linestyle -- 接收特定string&#xff0c;指定线条的类型…

阿里云直接对系统云盘扩容

阿里云直接对系统云盘扩容 登录阿里云控制台&#xff0c;进入ECS实例管理页面&#xff0c;检查目标磁盘的容量是否已更新为扩容后的数值。通过SSH远程连接服务器&#xff0c;使用命令 lsblk 或 fdisk -l 查看当前磁盘分区和容量&#xff0c;确认扩容后的物理磁盘已被系统识别。…

OpenResty深度解析:从卓伊凡的”隐形主流”论看其深度原理与应用生态-卓伊凡

OpenResty深度解析:从卓伊凡的”隐形主流”论看其深度原理与应用生态-卓伊凡 一、OpenResty技术概述:悄然成为基础设施的”隐形冠军” 1.1 OpenResty的”附带安装”现象 正如技术观察者卓伊凡在其《现代Web基础设施的隐形架构》一文中首次提出的观点:”OpenResty正在以一…

健康养生:开启品质生活的密钥

健康是人生最宝贵的财富&#xff0c;养生则是守护这份财富的关键。科学合理的养生方式&#xff0c;能让我们以更饱满的状态拥抱生活。 合理饮食是健康养生的基石。遵循 “食物多样、谷类为主” 的原则&#xff0c;保证每日摄入足够的蛋白质、碳水化合物、脂肪、维生素和矿物质。…

湖北理元理律师事务所:债务优化的法律机制与民生实践

在债务纠纷日益增多的社会背景下&#xff0c;合法、规范的债务管理服务成为民生需求的重要环节。湖北理元理律师事务所作为经国家司法局注册登记的债事服务机构&#xff0c;以法律为工具&#xff0c;探索出一套覆盖债务咨询、规划与风险防控的服务体系。 1.法律服务的专业化框…

AI日报 - 2025年04月29日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; AGI突破 | 巨头CEO预测AGI时间线&#xff0c;5年内或达人类认知水平&#xff1b;Yann LeCun强调多模态训练重要性。 关于AGI定义和实现时间的讨论升温&#xff0c;对超越纯文本训练的需求成为共识。 ▎&#x1f4bc; 商业动向…

【C++】类和对象(4)

目录 1. 类型转换 非explicit的单参数构造函数 示例 explicit的单参数构造函数 示例 不同版本的行为 示例 &#xff08;单参数&#xff09; 示例&#xff08;多参数且其余参数有默认值 &#xff09; 示例&#xff08;多参数且无默认值&#xff09; 2. static成员变量…

苍穹外卖10

WebSocket WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信----浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并进行双向数据传输。 HTTP协议和WebSocket协议对比&#xff1a; HTTP是短链接 WebSocke…

STM32的Flash映射双重机制

在STM32微控制器中&#xff0c;存在一个重要的内存映射特性&#xff1a;Flash存储器可以同时出现在两个不同的地址区域&#xff0c;而且可以通过重映射功能改变CPU启动时从哪个地址获取初始指令。 STM32的Flash映射双重机制 当描述"通常起始于地址0x00000000&#xff0c…

在 Spring Boot 中实现异常处理的全面指南

在现代 Web 应用开发中&#xff0c;异常处理是确保系统健壮性和用户体验的关键环节。Spring Boot 作为一个功能强大的 Java 框架&#xff0c;提供了灵活的异常处理机制&#xff0c;能够统一管理应用程序中的错误&#xff0c;提升代码可维护性和响应一致性。2025 年&#xff0c;…

学习记录:DAY19

Docker 部署与项目需求分析 前言 人总是本能地恐惧未知&#xff0c;令生活陷入到经验主义的循环之中。但我们终将面对。今天的目标是把 Docker 部署学完&#xff0c;然后对项目进行需求分析。 日程 下午 4:30&#xff1a;Docker 部署项目部分学完了&#xff0c;做下笔记。晚…

Jackson 使用方法详解

Jackson 是 Java 生态中最流行的 JSON 处理库&#xff0c;也是 Spring Boot 的默认 JSON 解析器。它提供了高性能的 JSON 序列化&#xff08;对象 → JSON&#xff09;和反序列化&#xff08;JSON → 对象&#xff09;功能。以下是 Jackson 的全面使用指南。 1. 基础依赖 Mave…

【网络入侵检测】基于源码分析Suricata的统计模块

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 在 Suricata 的配置文件中,stats 节点用于配置统计信息相关的参数,它的主要作用是控制 Suricata 如何收集和输出统计数据,帮助用户了解 Suricata 的运行状态和…

回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测,作者:机器学习之心

回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测&#xff0c;作者&#xff1a;机器学习之心 目录 回归预测 | Matlab实现DBO-LightGBM蜣螂算法优化轻量级梯度提升机多输入单输出回归预测&#xff0c;作者&#xff1a;机器学习之心预测效果…

风力发电领域canopen转Profinet网关的应用

在风力发电领域&#xff0c;开疆canopen转Profinet网关KJ-PNG-205的应用案例通常涉及将风力涡轮机内部的CANopen网络与外部的Profinet工业以太网连接起来。这种转换网关允许风力发电场的控制系统通过Profinet协议收集和监控涡轮机的状态信息&#xff0c;同时发送控制命令。 风力…

因特网和万维网

本文来源 &#xff1a;腾讯元宝 因特网&#xff08;Internet&#xff09;和万维网&#xff08;World Wide Web&#xff0c;简称WWW&#xff09;是紧密相关但完全不同的两个概念&#xff0c;它们的核心区别如下&#xff1a; 本质不同​​ ​​因特网&#xff08;Internet&#…

Visual Studio 技能:调整软件界面布局

专栏导航 本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏&#xff0c;故划分为两个专栏导航。读者可以自行选择前往哪个专栏。 &#xff08;一&#xff09;WIn32 专栏导航 上一篇&#xff1a;Windows编程&#xff1a;在VS2019里面&#xff0c;调整代码字体大…

LeetCode 热题 100_最小路径和(92_64_中等_C++)(多维动态规划)

LeetCode 热题 100_最小路径和&#xff08;92_64&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;多维动态规划&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;多维动态规划&…

Sql刷题日志(day6)

一、笔试 1、insert ignore&#xff1a;在插入数据时忽略主键冲突或其他唯一性约束冲突。 如果插入的记录会导致主键冲突&#xff08;如 actor_id 已存在&#xff09;&#xff0c;该语句不会报错&#xff0c;而是直接忽略插入操作 语法&#xff1a; INSERT IGNORE INTO tab…