SpringBoot+Vue
jdk 1.8
mysql 5.7
vue-cli 安装
npm install -g @vue-cli
npm 设置淘宝镜像加速
npm config set registry https://registry.npm.taobao.org
创建vue项目 vue create 项目名
运行
cd 项目目录
npm run serve
安装elementui
npm i element-ui -S
day 01-Vue项目初始化
HelloView.vue
<template>
<!-- <div class="home">
<h1>{{msg}}</h1>
<el-button type="danger">{{msg}}</el-button>
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div> -->
<el-container style="100vh">
<el-aside width="sideWidth +'px'" style="background-color: rgb(238, 241, 246);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow: hidden;" :collapse="isCollapse"
background-color="rgb(48,65,86)" text-color="#fff" active-text-color="#ffd04b"
:collapse-transition="false"
class="el-menu">
<div style="height: 60px; line-height: 60px; text-align: center">
<img src='../assets/logo.png' style="width: 20px; position: relative; top: 5px; margin-right: 5px"/>
<b style="color: white" v-show = "logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span slot="title">导航一</span>
<!-- <i class="el-icon-message"></i>导航一 -->
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
<!-- <i class="el-icon-menu"></i>导航二 -->
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-document"></i>
<span slot="title">导航三</span>
<!-- <i class="el-icon-setting"></i>导航三 -->
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header
style="text-align:left; font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px; display: flex">
<div style="flex: 1; font-size: 18px">
<span :class="collapseBtnClass" style="cursor: pointer;" @click="collapse()"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer;">
<span>王小虎</span>
<i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<div style="margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div style=" margin: 10px 0; display: flex">
<el-input style="width: 200px;" placeholder="请输入姓名" suffix-icon="el-icon-user"></el-input>
<el-input style="width: 200px;" placeholder="请输入邮箱" suffix-icon="el-icon-message"></el-input>
<el-input style="width: 200px;" placeholder="请输入地址" suffix-icon="el-icon-position"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>
<div style=" margin: 10px 0; display: flex">
<el-button type="primary">新增<i class="el-icon-circle-plus-outline"/></el-button>
<el-button type="danger">批量删除<i class="el-icon-delete"/></el-button>
<el-button type="primary">导入<i class="el-icon-bottom"/></el-button>
<el-button type="primary">导出<i class="el-icon-top"/></el-button>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="success">编辑<i class="el-icon-edit"/></el-button>
<el-button type="danger">删除<i class="el-icon-delete"/></el-button>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[5, 10, 15, 20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="20">
</el-pagination>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
// export default {
// name: 'HomeView',
// components: {
// HelloWorld
// },
// data(){
// return{
// msg: "Hello Vue"
// }
// }
// }
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item),
collapseBtnClass: "el-icon-s-fold",
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
headerBg:'headerBg'
}
},
methods: {
collapse() {
this.isCollapse = !this.isCollapse
if (this.isCollapse) {//收缩
this.sideWidth = 64;
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
}
else{
this.sideWidth = 200;
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
}
},
}
</script>
<style>
.headerBg {
background: #eee!important;
}
</style>
App.vue
<template>
<div id="app">
<!-- <nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav> -->
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
}
nav a {
font-weight: bold;
color: #2c3e50;
}
nav a.router-link-exact-active {
color: #42b983;
}
</style>
global.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ml-5{
margin-left: 5px;
}
.mr-5{
margin-right: 5px;
}
.pd-10{
padding: 10px 0;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import './assets/global.css'
Vue.use(ElementUI);
new Vue({
router,
render: h => h(App)
}).$mount('#app')
效果图
day02-SpringBoot项目创建
pom里配置阿里云仓库
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
application.yml
server:
port: 8081
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: localhost:3306/test?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
username: 用户名
password: 密码
output:
ansi:
enabled: ALWAYS
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
Application.java
package com.junchen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.junchen</groupId>
<artifactId>management</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>management</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
MyBatisPlusConfig.java
package com.junchen.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.junchen.mapper") // 扫描mapper包
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页查询
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
MyMetaObjectHandler.java
package com.junchen.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* mp执行添加操作,这个方法执行 添加时候添加默认值
*/
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class); // 起始版本 3.3.3(推荐)
//版本号,更新时候版本号会增加
this.strictInsertFill(metaObject, "version", () -> 1, Integer.class);
//逻辑删除 0表示未删除
this.strictInsertFill(metaObject, "deleted", () -> 0, Integer.class);
}
/**
* mp执行更新操作,这个方法执行 添加时候更新默认值
*/
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); // 起始版本 3.3.3(推荐)
}
}
MyBatis-Plus代码生成
pom依赖
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
SyS_User
CREATE TABLE management.sys_user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
username VARCHAR(50) NULL DEFAULT NULL COMMENT '用户名',
password VARCHAR(50) NULL DEFAULT NULL COMMENT '密码',
salt VARCHAR(50) NULL DEFAULT NULL COMMENT '盐',
nickname VARCHAR(50) NULL DEFAULT NULL COMMENT '昵称',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
phone VARCHAR(50) NULL DEFAULT NULL COMMENT '电话',
address VARCHAR(255) NULL DEFAULT NULL COMMENT '地址',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`version` INT ( 255 ) DEFAULT NULL,
`deleted` INT ( 255 ) DEFAULT NULL,
PRIMARY KEY (id)
)ENGINE = INNODB DEFAULT CHARSET = utf8;
生成器代码
package com.junchen.utils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import java.util.Collections;
/**
* mp代码生成器
* @author sunjunchen
* @since 2022-01-26
*/
public class CodeGenerator {
public static void main(String[] args) {
generate();
}
private static void generate() {
FastAutoGenerator.create("localhost:3306/management?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false", "用户名", "密码")
.globalConfig(builder -> {
builder.author("SunJunchen") // 设置作者
// .enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("C:\\Users\\sunjunchen\\IdeaProjects\\management\\src\\main\\java\\"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.junchen") // 设置父包名
.moduleName(null) // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "C:\\Users\\sunjunchen\\IdeaProjects\\management\\src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.entityBuilder().enableLombok();
// builder.mapperBuilder().enableMapperAnnotation().build();
builder.controllerBuilder().enableHyphenStyle() // 开启驼峰转连字符
.enableRestStyle(); // 开启生成@RestController 控制器
builder.addInclude("sys_user") // 设置需要生成的表名
.addTablePrefix("t_", "sys_"); // 设置过滤表前缀
builder.serviceBuilder().formatServiceFileName("%sService");//去掉IService 的I
})
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
User.java
package com.junchen.entity;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
@Getter
@Setter
@TableName("sys_user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户id
* 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法 nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 盐
*/
private String salt;
/**
* 昵称
*/
private String nickname;
/**
* 邮箱
*/
private String email;
/**
* 电话
*/
private String phone;
/**
* 地址
*/
private String address;
/**
* 创建时间
* 插入时填充字段
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
* 插入和更新时填充字段
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
* 版本
* Version乐观锁注解
*/
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
/**
* 逻辑删除的标志 0表示未删除 1表示已删除
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
}
UserMapper.java
package com.junchen.mapper;
import com.junchen.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
public interface UserMapper extends BaseMapper<User> {
}
UserService.java
package com.junchen.service;
import com.junchen.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
public interface UserService extends IService<User> {
}
UserServiceImpl.java
package com.junchen.service.impl;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.junchen.entity.User;
import com.junchen.mapper.UserMapper;
import com.junchen.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junchen.utils.Md5UUIDSaltUtil;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
加盐
package com.junchen.utils;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.UUID;
public class Md5UUIDSaltUtil {
public static String uuid = UUID.randomUUID().toString().replace("-", "");
//创建md5对象
public static String createMd5Code(String code) {
return DigestUtils.md5Hex(code);
}
//进行密码校验
public static boolean checkPassword(String userCode, String dbCode) {
if (dbCode.equals(createMd5Code(userCode))) {
return true;
} else {
return false;
}
}
public static String getUUID() {
return uuid;
}
//email + uuid
public static String getSalt(String email) {
String salt =email + uuid.substring(0, 5) ;
return salt;
}
}
day03 User 的 CRUD
UserController
package com.junchen.controller;
import com.junchen.entity.User;
import com.junchen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 前端控制器
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<Boolean> saveUser(@RequestBody User user) {
userService.saveUser(user);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
@PutMapping
public ResponseEntity<Boolean> updateUser(@RequestBody User user) {
userService.updateUser(user);
return ResponseEntity.noContent().build();
}
}
UserService.java
package com.junchen.service;
import com.junchen.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
public interface UserService extends IService<User> {
void saveUser(User user);
void updateUser(User user);
}
UserServiceImpl.java
package com.junchen.service.impl;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.junchen.entity.User;
import com.junchen.mapper.UserMapper;
import com.junchen.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junchen.utils.Md5UUIDSaltUtil;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author SunJunchen
* @since 2022-07-21
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public void saveUser(User user) {
//加盐,并将加过盐的密码 和盐重新存入数据库中
String salt = Md5UUIDSaltUtil.getSalt(user.getEmail());
String password = Md5UUIDSaltUtil.createMd5Code(user.getPassword()+salt);
user.setPassword(password);
user.setSalt(salt);
boolean saveFlag = this.save(user);
if (!saveFlag){
throw new RuntimeException("添加失败");
}
}
@Override
public void updateUser(User user) {
Long id = user.getId();
User user1 = this.lambdaQuery().eq(User::getId, id).one();
if (ObjectUtils.isNotEmpty(user1)){
this.lambdaUpdate().eq(User::getId,id).update(user);
}
}
}
更多推荐