Vue3环境搭建+Mybatis-plus的使用
文章目录
- 一、Vue简介
- 二、Vue 3安装
- 三、使用Vite构建工具创建Vue 3项目
- 创建项目
- 配置 vite.config.js,添加server配置项。
- 四、快速上手:Axios发送异步请求
- 五、关于Mybatis-plus
- 六、前后端分离项目常见问题:禁止跨域:
一、Vue简介
vue是前端知识,是前端框架,单页应用,他只有一个首页,其他都放在js里面,需要的时候js在页面中画出来应用。无需直接操作Dom元素。
二、Vue 3安装
安装node.js: 帮助我们编译vue里面的组件。
官网下载长期支持版本即可,傻瓜式安装,全部下一步即可。
安装pnmp:
npm install -g pnpm #命令窗口以管理员的身份运行
三、使用Vite构建工具创建Vue 3项目
创建项目
cd d:/vue3 //切换到创建项目的路径
pnpm create vite@latest demo1 //在项目创建向导中,需要手动选择使用的技术栈
项目创建完成。
注:创建demo1目录时,必须在拥有文件写操作权限的位置,
尽量不要选择在C 盘,也不建议在根目录下。
cd demo1 #进入到demo1目录
pnpm install #在项目目录下,执行此指令安装Vue项目所有依赖
使用cd指令进入到项目目录下 必须是在包含package.json所在目录下 ,使用pnpm install安装Vue 3项目依赖包。
创建成功后会多出来两个文件:
输入pnpm dev
进行项目测试 :
成功,使用IDEA打开
配置 vite.config.js,添加server配置项。
import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import {resolve} from "path";// https://vite.dev/config/
export default defineConfig({plugins: [vue()],server: {host: "localhost",port: 3000,//启动后自动打开浏览器open: true},resolve: {alias: [{find: "@",replacement: resolve(__dirname, "src")//把项目中的@符换成src路径}]}
})
退出终端的方式:Ctrl+C
进入到项目目录下,安装vue-router和axios
写程序这两个是不可或缺的:
pnpm install vue-router
pnpm install axios
四、快速上手:Axios发送异步请求
安装:pnpm install axios
我们的当前页面是客户管理页面,客户管理页面这种 通常是需要显示相关的数据的,相关数据就来自后端响应给我们
前端向后端发送一个get请求 。请求的路径如上。并携带着分页参数。所以会去查找这个路径,对应的方法就要做出响应,所以接下来要写后端部分。我们使用这个Vue是做前后端分离的项目。在前后端分离的项目中,我们前端负责响应页面,后端只需要响应数据即可。
我们后端使用:Mybatis-plus。如下介绍。
五、关于Mybatis-plus
引入依赖:pom.xml
<!-- mybatis-plus--><!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.12</version></dependency>
以及:
<!-- 自动分页插件https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-jsqlparser -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-jsqlparser</artifactId><version>3.5.12</version>
</dependency>
其他层次的后端写法是一样的,这项技术是用来改造Dao
层的:
关于Mybatis-plus的使用,首先需要我们Dao层这个接口去继承BaseMapper<具体的模型类>
然后将自定义的查询接口改成默认方法:default
修饰
Mybatis-plus能够根据查询条件的对象自动组装条件
(前端传递的参数哪个不为空就根据哪个查询,但是全是=判断的,不提供范围的查询方式,范围查询需要我们在Dao层代码中自己实现):前提得去实体类里面配置
:在实体类加:
(1)必做项:在类的上面加上@TableName("对应的数据库表名")//指定模型类对应哪个表
(2)必做项:在主键 上面加上@TableId(type = IdType.AUTO)//指定表的主键
(3)可选项:如果属性名和数据库表中的列名不一致,我们需要在字段上面添加 @TableField("数据库中实际的列名")
(4)可选项:参数的自动查询是依照=进行的,但是比如我们想要模糊查询:名字、电话这种等等,可以在对应的字段上面加上 @TableField(condition = SqlCondition.LIKE)
(5)比如根据范围查询,这种mybatis-plus没有提供,需我们手写。
所以实体类代码示例 :
package com.stedu.model;import com.baomidou.mybatisplus.annotation.*;
import com.stedu.util.AuditEntity;
import lombok.*;import java.time.LocalDate;@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString@TableName("t_member")//指定模型类对应哪个表
public class Member extends AuditEntity {@TableId(type = IdType.AUTO)//指定表的主键private Integer id;@TableField(condition = SqlCondition.LIKE)private String phone;private String username;private String password;@TableField(condition = SqlCondition.LIKE)private String name;private String pinyin;private String sex;private LocalDate birthday;@TableField(condition = SqlCondition.LIKE)private String wechat;@TableField(condition = SqlCondition.LIKE)private String email;private String description;}
Dao层代码 示例:
package com.stedu.dao;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stedu.model.Member;
import com.stedu.model.search.MemberSearchBean;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface MemberMapper extends BaseMapper<Member> {//查询全部default Page<Member> findAll(Page<Member> page, MemberSearchBean msb) {//能够根据查询条件的对象自动组装条件:前提得配置:去实体类里面LambdaQueryWrapper<Member> queryWrapper = Wrappers.lambdaQuery(msb);//关于查询范围的条件查询:只能手写,mybatis-plus没有提供范围的查询,手写 :if (msb.getBirthdayFrom() != null) {//拼一个条件:大于等于:ge他的条件queryWrapper.ge(Member::getBirthday, msb.getBirthdayFrom());}if (msb.getBirthdayTo() != null) {//拼一个条件:小于等于:lt他的条件queryWrapper.lt(Member::getBirthday, msb.getBirthdayTo());}return selectPage(page, queryWrapper);//返回页,在baseMapper里面。分页查询,包装器。}
}
其他层次相关调用汇总如下:
模型类另外的::
MemberSearchBean
封装查询对象
package com.stedu.model.search;import com.stedu.model.Member;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.time.LocalDate;@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor//假设有查询需求是:查询出生日期在这个范围内的人:在业务类中不可能有,但是还需要查询。封装成查询对象
public class MemberSearchBean extends Member {private LocalDate birthdayFrom;private LocalDate birthdayTo;}
service层:
MemberService
package com.stedu.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stedu.model.Member;
import com.stedu.model.search.MemberSearchBean;public interface MemberService {
//查询全部会员:多条件组合分页查询page:分页对象,msb:查询条件Page<Member> findAll(Page<Member> page, MemberSearchBean msb);}
MemberServiceImpl
package com.stedu.service.impl;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stedu.dao.MemberMapper;
import com.stedu.model.Member;
import com.stedu.model.search.MemberSearchBean;
import com.stedu.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MemberServiceImpl implements MemberService {private MemberMapper memberMapper;//控制反转:依赖注入,将创建对象的权限反转。@Autowiredpublic void setMemberMapper(MemberMapper memberMapper) {this.memberMapper = memberMapper;}@Overridepublic Page<Member> findAll(Page<Member> page, MemberSearchBean msb) {return memberMapper.findAll(page,msb);}
}
util层:
AuditEntity
package com.stedu.util;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDate;@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
//审计字段:
public abstract class AuditEntity {private String createdBy;private LocalDate createdTime;private String updatedBy;private LocalDate updatedTime;
}
JsonResult
package com.stedu.util;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
@AllArgsConstructor//返回响应格式是Json的工具类:
public class JsonResult<T> {private int code;//错误码,有规范private boolean success;private String msg;//错误提示信息private T data;//日期//提供相关正确和错误信息的返回方法public static JsonResult<?> success() {return success(null);}public static <T> JsonResult<T> success(T data) {return new JsonResult<>(200, true, "操作成功", data);}public static JsonResult<?> fail(int code, String msg) {return new JsonResult<>(code, false, msg, null);}public static JsonResult<?> fail(String msg) {return fail(500, msg);}
}
MemberApi
package com.stedu.api;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stedu.model.Member;
import com.stedu.model.search.MemberSearchBean;
import com.stedu.service.MemberService;
import com.stedu.service.impl.MemberServiceImpl;
import com.stedu.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController//既包含了@Controller也包含了@ResponseBody
//设置路径以及响应格式:
@RequestMapping(value = "/api/v1/members",produces = MediaType.APPLICATION_JSON_VALUE)
public class MemberApi {//依赖注入:用于自动创建对象,有对象了直接调用方法就行了private MemberService memberService;@Autowiredpublic void setMemberService(MemberService memberService) {this.memberService = memberService;}//查询全部的方法:关于传参 ,肯定有分页参数:分别是页码和页面大小,设置默认的参数1和20。并传入查询条件(封装成对象了)@GetMappingpublic ResponseEntity<JsonResult<?>> findAll(@RequestParam(defaultValue = "1") Integer pageNo,@RequestParam(defaultValue = "20") Integer pageSize,MemberSearchBean msb){//创建分页对象new Page:mybatis-plus自带的Page<Member> page = new Page<>(pageNo, pageSize);//查询全部Page<Member> serviceAll = memberService.findAll(page, msb);return ResponseEntity.ok(JsonResult.success(serviceAll));}
}
六、前后端分离项目常见问题:禁止跨域:
进入到项目目录下,执行指令pnpm install axios,如已安装,则忽略此步。
在项目根目录下创建utils目录,在其下创建api.js,编写内容如下:
import axios from "axios";const api = axios.create({baseURL: "/api",timeout: 3000
});api.interceptors.response.use(resp => resp.data,error => Promise.reject(error || "接口调用异常"));
export default api;
在Customer.vue下,编写内容如下:
<template><h1>客户列表页</h1>
</template><script setup>
import {onMounted} from "vue";
import api from "@/utils/api.js";onMounted(async () => {let resp = await api({url: "http://localhost:8080/api/v1/customers",method: "get",params: {page: 1,limit: 10}});console.log(resp);
});
</script>
此时,控制台会提示错误:禁止跨域。
跨域解决方案:
1.后端配置:在Controller类上添加@CrossOrigin注解。不推荐
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
@RestController
@RequestMapping(value = "/api/v1/customers", produces = MediaType.APPLICATION_JSON_VALUE)
public class CustomerApi {
2.前端配置:在vite.config.js中配置跨域。此时,axios发送请求时,可使用相对路径,会被自动代理为后端服务器路径。(推荐使用)
import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
// 导入resolve函数
import {resolve} from "path";// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],// 服务器端配置server: {open: true,host: "localhost",port: 3000,// 开发时配置代理proxy: {// "/api"对应于util目录下的api.js中配置的baseUrl"/api": {//路径必须以http://开头,不能省略协议名称target: "http://localhost:8080",changeOrigin: true,// 第一个参数是正则表达式,使用/xxx/,双斜线表示正则表达式,xxx是正则表达式内容,没有双引号rewrite: url => url.replace(/^\/api/, "/api/v1")}}},// 配置路径别名,使用@代替src目录resolve: {alias: {"@": resolve(__dirname, "src")}}
})
还有注意修正方式:
如果只想拿到data而不想要其他的信息,解决方案:
写个工具类:
import axios from "axios";//创建一个axios实例
let api = axios.create({baseURL: "/api",timeout: 3000
});//配置响应拦截器
api.interceptors.response.use(resp => {//成功的操作:只显示数据return resp.data;
}, resp => {//出现错误的时候return Promise.reject(resp.data.msg || "后台服务异常");
});export default api;//导出api
然后修改前端vue组件: