当前位置: 首页 > news >正文

学习仓库管理系统--根据B站‘编程界小明哥‘

建项目

新建文件夹: spring-vue-wms2,用idea打开文件夹,然后新建wms模块,选择spring web、MySQL、lombok依赖

新建数据库和用户表

CREATE DATABASE wms2 CHARACTER SET UTF8;

create table `user` ( `id` int not null auto_increment primary key, `no` varchar(20) not null comment '账号', `name` varchar(100) not null comment '名字', `password` varchar(20) not null comment '密码', `age` int default 18 comment '年龄', `sex` int default 0 comment '性别 0女 1男', `phone` varchar(20) default null comment '联系方式', `role_id` int default 2 comment '角色 0超级管理员 1普通管理员 2普通用户', `isValid` int default 1 comment '账号是否天有效 1有效 0无效' ) engine=innodb auto_increment=1 default charset=utf8;

新增mybatis-plus依赖

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency>

修改yml文件

server: port: 8090 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/wms2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8 username: root password: ***

新增User实体类

package com.wms.entity; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; @Data public class User { private int id; private String no; private String name; private String password; private int age; private int sex; private String phone; @TableField("role_id") private int roleId; @TableField("isValid") private int isvalid; }

新增UserMapper接口

package com.wms.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.wms.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends BaseMapper<User> { }

新增UserService接口和UserServiceImpl实现类(面向接口编程,低耦合)

package com.wms.service; import com.baomidou.mybatisplus.extension.service.IService; import com.wms.entity.User; public interface UserService extends IService<User> { }
package com.wms.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wms.entity.User; import com.wms.mapper.UserMapper; import com.wms.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }

新增UserController类进行查询

package com.wms.controller; import com.wms.entity.User; import com.wms.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/list") public List<User> list() { return userService.list(); } }

这个时候查询,结果是空列表,因为没有数据。

往表里插入一条数据

insert user (no, name, password, age, sex, phone, role_id, isValid) values ('刘邦','刘邦','123456',40,1,'15566667777',0,1);

浏览器再访问/user/list接口就有数据了

自定义SQL查询

例如在UserController类中新增查询

@GetMapping("/customList") public List<User> cunstomList() { return userService.customList(); }

需要在UserService接口和UserServiceImpl类中声明和实现这个方法: customList

public interface UserService extends IService<User> { List<User> customList(); }
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> customList() { return userMapper.customList(); } }

还需要在UserMapper接口中声明方法

@Mapper public interface UserMapper extends BaseMapper<User> { List<User> customList(); }

然后在resources目录下新建mapper目录,在mapper目录下新建UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wms.mapper.UserMapper"> <select id="customList" resultType="com.wms.entity.User"> select * from user </select> </mapper>

增删改查

package com.wms.controller; import com.wms.entity.User; import com.wms.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; // 新增一个User @PostMapping public Boolean save(@RequestBody User user) { return userService.save(user); } // 删除一个User @DeleteMapping("/{id}") public Boolean delete(@PathVariable int id) { return userService.removeById(id); } // 更新一个User @PutMapping("/{id}") public Boolean update(@PathVariable int id, @RequestBody User user) { user.setId(id); return userService.updateById(user); } // 查询所有 @GetMapping public List<User> list() { return userService.list(); } // 根据id进行查询 @GetMapping("/{id}") public User list(@PathVariable int id) { return userService.getById(id); } }

分页的实现

配置分页插件

见mybatis-plus官网: https://baomidou.com/plugins/pagination/

package com.wms.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 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.wms.mapper") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加 // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType return interceptor; } }
进行分页查询
@PostMapping("/test") public IPage<User> test() { Page<User> page = new Page<>(1,10); // 查询第一页,每页10条记录 LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); lqw.like(User::getName, ""); // 查询条件: 用户名包含空字符串的 IPage<User> result = userService.page(page, lqw); System.out.println(result.getTotal()); System.out.println(result.getRecords()); return result; }

创建一个vue项目

vue create vue-wms2
导入element-ui
npm i element-ui -S
在main.js中完整引入
import Vue from 'vue' import ElementUi from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import App from './App.vue' Vue.use(ElementUi) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
新增Index.vue

在components目录下新建Index.vue,主要是参考element-ui官网:https://element.eleme.cn/#/zh-CN/component/container

<template> <div> <el-container style="height: 500px; border: 1px solid #eee"> <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> <el-menu :default-openeds="['1', '3']"> <el-submenu index="1"> <template slot="title"><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>导航二</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-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: right; font-size: 12px"> <el-dropdown> <i class="el-icon-setting" style="margin-right: 15px"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>查看</el-dropdown-item> <el-dropdown-item>新增</el-dropdown-item> <el-dropdown-item>删除</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>王小虎</span> </el-header> <el-main> <el-table :data="tableData"> <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> </el-main> </el-container> </el-container> </div> </template> <style> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style> <script> export default { name:"IndexPage", data() { const item = { date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }; return { tableData: Array(20).fill(item) } } }; </script>

删除HelloWorld.vue,修改App.vue

<template> <div id="app"> <Index/> </div> </template> <script> import Index from "@/components/Index.vue"; export default { name: 'App', components: { Index } } </script> <style> #app { } </style>

还经过了一些样式的调整和vue组件的拆分,这里不再记录,可以去看原视频

下载并导入axios
npm install axios --save

在main.js中导入

import Vue from 'vue' import ElementUi from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import App from './App.vue' import axios from 'axios' Vue.prototype.$axios=axios Vue.use(ElementUi) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')

在进行拆分后的组件Main.vue中使用axios访问后台的一个接口

methods:{ loadGet() { this.$axios.get('http://localhost:8090/user').then(res=>{ console.log(res) }) }, }, beforeMount() { this.loadGet(); },

刷新前台界面,按F12发现有报错:

Access to XMLHttpRequest at 'http://localhost:8090/user' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是因为浏览器的安全机制:CORS策略(同源策略)导致的跨域问题。浏览器规定:前台界面的域名,必须和所请求的接口的域名完全一致(协议、IP、端口都要一样),否则就是跨越,属于非法越界。

前台端口是8080,后台端口是8090,所以导致的跨越

解决办法,在后台加一个配置类,让整个项目的所有接口,统统允许跨域

package com.wms.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 拦截所有接口 .allowedOrigins("http://localhost:8081") // 允许哪个前端来访问 .allowedOrigins("http://localhost:8080") .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许哪些请求方式 .allowCredentials(true); // 允许携带Cookie } }
列表显示用户信息

通过axios调用后台接口,查询所有用户信息,前台获取到用户信息,用列表形式显示。

(修改了一下user表,去掉了no字段,只保留name字段,避免不必要的重复。实体类也要同步修改)

以及加上了分页功能和根据用户名name进行查询的功能

package com.wms.entity; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; @Data public class User { private int id; private String name; private String password; private int age; private int sex; private String phone; @TableField("role_id") private int roleId; @TableField("isValid") private int isValid; }
<script> export default { name:"MainPage", data() { return { tableData: [], pageNumb: 1, pageSize: 1, total: 1, name:"", } }, methods:{ handleSizeChange(val) { console.log(`每页 ${val} 条`); this.pageSize = val this.loadPost() }, handleCurrentChange(val) { console.log(`当前页: ${val}`); this.pageNumb = val this.loadPost() }, loadGet() { this.$axios.get(this.$httpUrl + '/user').then(res=>res.data).then(res=>{ console.log(res[0].name) this.tableData = res }) }, loadPost() { this.$axios.post(this.$httpUrl + '/user/list', { "pageNumb":this.pageNumb, "pageSize":this.pageSize, "param": {"name":this.name} }).then(res=>res.data).then(res=>{ console.log(res) this.tableData = res.data this.total = res.total }) }, loadPut() { this.$axios.put(this.$httpUrl + '/user/2', { "name":"萧何", "age":42, "roleId":1, "isValid":1 }).then(res=>{ console.log(res) }) } }, beforeMount() { this.loadPost() } } </script> <template> <div> <div style="margin-bottom: 5px;"> <el-input v-model="name" placeholder="请输入姓名进行查询" suffix-icon="el-icon-search" style="width: 200px;"></el-input> <el-button type="primary" style="margin-left: 5px;" @click="loadPost()">查询</el-button> <el-button type="success">重置</el-button> </div> <el-table :data="tableData"> <el-table-column prop="id" label="ID" width="40"> </el-table-column> <el-table-column prop="name" label="姓名" width="120"> </el-table-column> <el-table-column prop="password" label="密码" width="120"> <template > <span>***</span> </template> </el-table-column> <el-table-column prop="age" label="年龄" width="140"> </el-table-column> <el-table-column prop="sex" label="性别" width="120"> <template slot-scope="scope"> <el-tag :type="scope.row.sex === 1 ? 'primary' : 'danger'" disable-transitions>{{scope.row.sex === 1 ? '男' : '女'}}</el-tag> </template> </el-table-column> <el-table-column prop="phone" label="电话" width="220"> </el-table-column> <el-table-column prop="roleId" label="角色" width="120"> <template slot-scope="scope"> <el-tag :type="scope.row.roleId === 0 ? 'success' : scope.row.roleId === 1 ? 'primary' : 'info'" disable-transitions>{{scope.row.roleId === 0 ? '超级管理员' : scope.row.roleId === 1 ? '管理员' : '普通用户'}}</el-tag> </template> </el-table-column> <el-table-column prop="isValid" label="状态" > <template slot-scope="scope"> <el-tag :type="scope.row.isValid === 1 ? 'success' : 'warning'" disable-transitions>{{scope.row.isValid === 1 ? '正常' : '失效'}}</el-tag> </template> </el-table-column> </el-table> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNumb" :page-sizes="[1, 5, 10, 100]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> </div> </template> <style scoped> </style>
@PostMapping("/list") public Result list(@RequestBody PageParam pageParam) { LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); HashMap map = pageParam.getParam(); String name = (String)map.get("name"); if (StringUtils.isNotBlank(name)) { lqw.like(User::getName, name); } Page<User> pageIn = new Page<>(pageParam.getPageNumb(), pageParam.getPageSize()); IPage<User> pageOut = userService.page(pageIn, lqw); return Result.suc(pageOut.getRecords(), pageOut.getTotal()); }
踩坑点

根据name进行查询的时候,QueryWrapper中的like '%name%'没有生效,这是因为UserMapper.xml中我写了一个<select id="selectPage"> </select> 覆盖了 Mybatis Plus 自带的分页方法

http://www.jsqmd.com/news/724327/

相关文章:

  • e签宝携eSign.AI亮相第十届万物生长大会,以数字信任筑牢AI时代创新底座
  • 深圳配眼镜攻略:破解价格迷雾,解码视觉价值的“三种配镜哲学” - 资讯焦点
  • 上下文多臂老虎机在LLM查询优化中的应用与实现
  • 嵌入式MTP NVM技术解析与应用场景
  • AlienFX Tools终极配置指南:3大核心技术突破与500KB轻量级AWCC替代方案
  • 3个简单步骤:用Windows Cleaner彻底解决电脑卡顿问题
  • 如何在5分钟内为Unity游戏添加智能翻译:XUnity.AutoTranslator完整指南
  • Windows Cleaner终极指南:3分钟快速解决C盘爆满问题,让系统重获新生!
  • 是德MX0032A和MX0041A探头 MX0041A InfiniiMax 4 差分焊入式探头 – 52 GHz
  • 轻食加盟市场风险调研报告——十大不推荐加盟品牌深度解析 - 资讯焦点
  • 深入Gold-YOLO的GD机制:看华为如何用‘聚集-分发’解决YOLO系列的老大难问题
  • 如何在Windows上完美使用PS4/PS5手柄:3步快速配置终极指南
  • Session粘滞性问题->Redis实现session共享
  • 如何快速上手数字电路设计:Logisim-Evolution 完整实战指南
  • python学习笔记 | 8.1、函数式编程-高阶函数
  • 从一站式采购到前店后仓,乐居如何重塑汤原的“家”与“业”?
  • MCP协议服务健康检查工具mcp-checkup的设计与实战
  • 旧物回收系统源码 – go语言版
  • 开源知识管理工具Costea:基于间隔重复与知识图谱构建第二大脑
  • 大连做金融相关法律服务的品牌律所推荐,哪家更靠谱? - 工业推荐榜
  • 海康录像机提示“已达到通道资源添加上限”是什么原因---远程维修服务日记
  • 0.43%入选门槛6重筛选:2026年上海家装七强全维度标杆企业重磅揭晓 - 资讯焦点
  • 3步彻底解决Zotero中文文献管理难题:茉莉花插件完全指南
  • uboot学习笔记
  • 不止于Dotplot:解锁MUMmer套件的隐藏技能,从SNP检测到基因组结构变异分析
  • 猫抓cat-catch终极指南:浏览器资源嗅探神器让网页资源下载如此简单
  • 2025—2026年度上海装修市场深度调研:5家靠谱装企全解析 - 资讯焦点
  • 终极指南:如何免费永久备份微信聊天记录到电脑
  • 如何永久备份微信聊天记录?免费开源工具WeChatMsg终极使用指南
  • Docker 化 Java 应用与镜像瘦身完全指南