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

06-01 1316阅读

前后端分离: vue3+SpringBoot

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

        项目介绍

        🌟项目页面

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


        🌟技术栈:

        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类型, 就转为json
            if (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整合-前后端分离(实现增删改查)

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

        @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
             */
            @Bean
            public 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 {
            @Autowired
            private 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 page = sysUserService.page(new Page(pageNum, pageSize));
                //2.返回数据, 查询分页查询的数据结构
                return Result.success(page);
            }
        }
        

        3.vue分页组件

         
        

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

        配置Druid数据源

        参考整合Druid到SpringBoot

        带条件的分页查询

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

        后端校验

        /**
         * 验证表单
         */
        private Map validateForm(Errors errors) {
            Map errorMap = new HashMap();
            List 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 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 函数式接口
            //3. 查看 SFunction 源代码
            /**
             * @FunctionalInterface
             * public interface SFunction extends Function, Serializable {
             * }
             * 父接口
             *@FunctionalInterface
             * public interface Function {
             *      R apply(T t);//抽象方法, 表示根据类型T的参数, 获取类型R的结果
             *
             *      //这里有默认实现方法
             * }
             */
            //4.传入 SysUser::getUsername 后, 就相当于实现了 SFunction 的apply方法
            //5.底层会根据 传入的 SysUser:getUsername 去得到该方法的对应的属性映射的表的字段, 更加灵活
            //
            //        
            //创建lambdaQueryWrapper, 封装查询条件
            LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery();
            //判断
            if (StringUtils.hasText(sysUser.getUsername())) {
                //lambdaQueryWrapper.like(SysUser::getUsername, sysUser.getUsername());
                //换一个写法, 依然正确
                SFunction sf = SysUser::getUsername;;
                lambdaQueryWrapper.like(sf, sysUser.getUsername());
            }
            Page page = sysUserService.page(new Page(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 {
                 *     public Object apply (Aclass aclass) {
                 *          return "Aclass";
                 *     }
                 * }
                 * Test$1 test$1 = new Test$1();
                 * test$1.apply(new Aclass());
                 */
                //ZzwFunction zf = new ZzwFunction() {
                //    @Override
                //    public String apply(AClass aClass) {
                //        return "AClass";
                //    }
                //};
                //Object result = zf.apply(new AClass());
                //System.out.println("result=" + result);
                ZzwFunction zf2 = AClass::getBrand;
                Object result2 = zf2.apply(new AClass());
                System.out.println("result2=" + result2);
                //zf2.say();
            }
        }
        //定义一个函数式接口: 有且只有一个抽象方法的接口
        //可以使用@FunctionalInterface 来标识一个函数式接口
        //ZzwFunction是一个函数式接口(这个是一个自定义泛型接口)
        @FunctionalInterface
        interface ZzwFunction {
            R apply(T t);//抽象方法: 表示根据类型T的参数, 获取类型R的结果
            //函数式接口, 依然可以有多个默认是先方法
            default public void say() {
                System.out.println("hello");
            }
        }
        class AClass {//Bean
            private String name = "lambda AClass";
            private String brand = "奔驰品牌";
            public String getName() {
                return name;
            }
            public String getBrand() {
                return brand;
            }
        }
        
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码