想做一个简单的Java前后端分离的项目,不知如何下手,利用闲暇时间将学习的SpringBoot和Vue做一次简单的小整合,从而实现简单的前后端分离,帮助理清前后端思路。
该文档的目的就是为了帮助你理清前后端分离,并将对应的数据进行简单的CRUD,希望对你有所帮助。
使用的工具:
IntelliJ IDEA 2021.2.1,Maven,Navicat Premium 16,
前端
Vue:3.2.38
axios:1.1.3
ElementUI Plus 2.2.17
后端
SpringBoot 2.7.4
MySQL 5.7.36
Mybatis Plus
IDEA创建一个SpringBoot项目,然后修改pom.xml文件添加相关依赖。
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
5.1.47
com.baomidou
mybatis-plus-boot-starter
3.4.2
com.alibaba
druid
1.2.13-SNSAPSHOT
org.projectlombok
lombok
true
推荐一个网站可以快速创建数据库。https://www.sqlfather.com/
-- 用户表信息
create table if not exists vaccine_system.`user`
(
`id` bigint not null auto_increment comment '主键' primary key,
`username` varchar(256) not null comment '用户名',
`password` varchar(256) not null comment '密码',
`id_card` varchar(256) null comment '身份证号',
`real_name` varchar(256) not null comment '真实姓名',
`gender` varchar(256) not null comment '性别',
`address` varchar(256) not null comment '地址',
`phone` varchar(256) not null comment '手机号',
`role` varchar(256) default '0' not null comment '角色',
`age` varchar(256) not null comment '年龄',
`user_status` varchar(256) default '0' not null comment '状态',
`update_time` datetime default 'CURRENT_TIMESTAMP' not null on update CURRENT_TIMESTAMP comment '更新时间',
`create_time` datetime default 'CURRENT_TIMESTAMP' not null comment '创建时间',
`is_deleted` tinyint default 0 not null comment '是否删除(0-未删, 1-已删)'
) comment '用户表信息';
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('藤森里穂', 'password', '田振家', '女', '宜城市', '13884310615', '87');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('末広純', 'password', '钟博文', '女', '泰州市', '14577692413', '92');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('櫻空桃', 'password', '陆梓晨', '女', '崇左市', '17010768373', '36');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('西田那津', 'password', '萧浩', '女', '诸城市', '17179533521', '95');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('蓮實克蕾兒', 'password', '吕天宇', '女', '江油市', '15190645338', '97');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('藤森里穂', 'password', '高擎苍', '女', '巴彦淖尔市', '17300534915', '45');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('三上悠亜', 'password', '杨智宸', '男', '峨眉山市', '15834255560', '32');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('葵司', 'password', '贾鹏煊', '男', '茂名市', '15042781120', '100');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('伊藤舞雪', 'password', '廖耀杰', '男', '临清市', '17127846009', '65');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('櫻空桃', 'password', '廖雨泽', '男', '淮北市', '17814700078', '92');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('松本一香', 'password', '崔修杰', '女', '新泰市', '15832830726', '53');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('七澤美亞', 'password', '顾泽洋', '女', '瑞丽市', '15984970745', '93');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('七森莉莉', 'password', '董浩宇', '男', '平湖市', '15227610271', '40');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('櫻空桃', 'password', '黎语堂', '女', '武夷山市', '17121546218', '74');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('石原希望', 'password', '莫智宸', '女', '南京市', '15147185954', '85');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('小宵虎南', 'password', '龚立轩', '男', '图木舒克市', '14508002887', '70');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('夢乃愛華', 'password', '冯天磊', '男', '郑州市', '17517334820', '43');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('七澤美亞', 'password', '阎振家', '男', '诸城市', '17182063425', '12');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('蕾', 'password', '袁烨磊', '男', '福安市', '18288482422', '46');
insert into vaccine_system.`user` (`username`, `password`, `real_name`, `gender`, `address`, `phone`, `age`) values ('河北彩花', 'password', '夏懿轩', '女', '沅江市', '17134097852', '94');
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/iw?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#单个文件大小,默认1MB
spring.servlet.multipart.max-file-size=10MB
#每次请求文件的大小
spring.servlet.multipart.max-request-size=10MB
需要使用到的几个注解。简单举例:
@RestController
@RequestMapping(value=“/login”,method = RequestMethod.GET) //该写法等同于GetMapping@RequestMapping(value=“/login”,method = RequestMethod.POST) //该写法等同于PostMapping
@GetMapping(“/login”)//RESTful风格要求尽量用该注解进行获取资源
@PostMapping(“/login”)//RESTful风格要求尽量用该注解进行新建资源
@PutMapping(“”) //RESTful风格要求尽量用该注解进行更新资源
@DeleteMapping(“”) //RESTful风格要求尽量用该注解进行删除资源
@PathMapping() //RESTful风格要求尽量用该注解进行部分资源更新
@RequestParam 参数传递时,参数名称和方法中的名称不一致时可以使用。被该注解标记的参数必须有值。添加属性required=false可更改不必须有值。
@PathVariable 动态获取一个值。注意:@GetMapping(“/login/{id}”)要加上{}
@RequestBody 接收json类型的注解
@TableLogic 逻辑删除,添加到属性名上。例如:@TableLogic private Integer isDeleted;
Mybatis Plus中的一些注解
@TableId(type = IdType.AUTO) 设置到实体类的主键上,自动填充值。
@TableField(“”) 数据库中的名称和实体类中属性的名称不一致时可以使用。实体类中有数据库中不存在的字段时,可以使用exist=false属性设置为该字段为非数据库字段。
@RestController
public class UserController {
//查询全部
@GetMapping("/user/findAll")
public List<User> findAll(){
return "查询全部人员";
}
}
运行SpringBoot启动类并在浏览器中访问localhost:8080/user/findAll。
编写配置类MybatisPlusConfig
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
简单使用
//分页查询
@GetMapping("/user/findByPage")
public IPage<User> findByPage(){
//设置查询的起始值及每页条数
Page<User> page = new Page<>(0,5);
//将查询的结果封装成了一个新的对象
IPage<User> iPage = userMapper.selectPage(page, null);
return iPage;
}
https://cn.vuejs.org/
使用node.js下载Vue3,并创建一个项目。
npm init vue@latest
可供选用的功能
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in ./<your-project-name>...
Done.
https://element-plus.gitee.io/zh-CN/
使用组件快速开发。
npm install element-plus --save
main.js中添加以下内容
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)
https://www.axios-http.cn/
第一步:安装
npm install axios
第二步:main.js文件中添加
import axios from 'axios'
第三步:main.js文件中注册
//将axios作为全局的自定义属性,每个组件可以在内部直接访问
app.config.globalProperties.$http=axios
第四步:main.js文件中指定请求头
//配置请求根路径
axios.defaults.baseURL = 'http://localhost:8080';
1、@CrossOrigin 在controller包下需要跨域的类添加注解。
2、编写跨域配置文件,允许全部跨域。
之后可以在前端界面中添加一个ElementUI Plus的表格,启动前端项目和后端项目,使用axios将后端数据加载到前端。
main.js文件:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './assets/main.css'
import axios from 'axios'
//配置请求根路径
axios.defaults.baseURL = 'http://localhost:8080';
const app = createApp(App)
app.use(ElementPlus)
app.use(router)
//将axios作为全局的自定义属性,每个组件可以在内部直接访问
app.config.globalProperties.$http=axios
app.mount('#app')
前端页面的代码:
这里我是使用的AboutView.vue文件,我将其内容全部重写了。
@Configuration
@MapperScan("com.f.iw.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
UserController
@CrossOrigin
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
//查询全部
@GetMapping("/user/findAll")
public List<User> findAll(){
List<User> list = userMapper.selectList(null);
System.out.println(list);
return list;
}
//分页查询
@GetMapping("/user/findByPage")
public IPage<User> findByPage(){
//设置查询的起始值及每页条数
Page<User> page = new Page<>(0,5);
//将查询的结果封装成了一个新的对象
IPage<User> iPage = userMapper.selectPage(page, null);
return iPage;
}
}
User
/**
* 用户表信息
* @TableName user
*/
@Data
public class User implements Serializable {
/**
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 身份证号
*/
private String idCard;
/**
* 真实姓名
*/
private String realName;
/**
* 性别
*/
private String gender;
/**
* 地址
*/
private String address;
/**
* 手机号
*/
private String phone;
/**
* 角色
*/
private String role;
/**
* 年龄
*/
private String age;
/**
* 状态
*/
private String userStatus;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private Date updateTime;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private Date createTime;
/**
* 是否删除(0-未删, 1-已删)
*/
private Integer isDeleted;
private static final long serialVersionUID = 1L;
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
User other = (User) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
&& (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
&& (this.getIdCard() == null ? other.getIdCard() == null : this.getIdCard().equals(other.getIdCard()))
&& (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
&& (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
&& (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
&& (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
&& (this.getRole() == null ? other.getRole() == null : this.getRole().equals(other.getRole()))
&& (this.getAge() == null ? other.getAge() == null : this.getAge().equals(other.getAge()))
&& (this.getUserStatus() == null ? other.getUserStatus() == null : this.getUserStatus().equals(other.getUserStatus()))
&& (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
&& (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
&& (this.getIsDeleted() == null ? other.getIsDeleted() == null : this.getIsDeleted().equals(other.getIsDeleted()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
result = prime * result + ((getIdCard() == null) ? 0 : getIdCard().hashCode());
result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
result = prime * result + ((getRole() == null) ? 0 : getRole().hashCode());
result = prime * result + ((getAge() == null) ? 0 : getAge().hashCode());
result = prime * result + ((getUserStatus() == null) ? 0 : getUserStatus().hashCode());
result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
result = prime * result + ((getIsDeleted() == null) ? 0 : getIsDeleted().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", username=").append(username);
sb.append(", password=").append(password);
sb.append(", idCard=").append(idCard);
sb.append(", realName=").append(realName);
sb.append(", gender=").append(gender);
sb.append(", address=").append(address);
sb.append(", phone=").append(phone);
sb.append(", role=").append(role);
sb.append(", age=").append(age);
sb.append(", userStatus=").append(userStatus);
sb.append(", updateTime=").append(updateTime);
sb.append(", createTime=").append(createTime);
sb.append(", isDeleted=").append(isDeleted);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}
UserMapper
public interface UserMapper extends BaseMapper<User> {
}
IwApplication
@SpringBootApplication
@MapperScan("com.f.iw.mapper")
public class IwApplication {
public static void main(String[] args) {
SpringApplication.run(IwApplication.class, args);
}
}
启动前后端项目,然后就能的到一个巨丑无比的表格,表格中的数据就是数据库中的数据。后续的简单的CRUD操作,可以直接使用mybatis plus提供的方法即可。
至此简单的前后端数据算是绑定在一起了,可以进行其他的操作了。
这里推荐一个后台管理的前后端项目。
项目地址:vue-element-admin
项目文档也非常的齐全,可供学习参考。