使用SpringBoot一小时快速搭建一个简单后台管理(后端篇)
Posted 全栈小袁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用SpringBoot一小时快速搭建一个简单后台管理(后端篇)相关的知识,希望对你有一定的参考价值。
不好意思让大家久等啦,最近也是因为学期末了,事情多了一点,所以更新的比较慢,请大家谅解下~
好了话不多说,进入今天的教程环节
本次案例一共两篇文章教学:
(第一篇):数据表设计,前端框架引入和编写前端页面,搭建基本的springboot项目,引入前端到springboot项目中,在浏览器显示
(第二篇):后端代码的设计,这部分逻辑涉及的比较多,所以单独放一篇出来讲,代码从0手敲讲解,保证你能学会,完成增删改查的功能
效果演示
目录
前言
我们在上一篇中呢已经简单的搭建了一个前端页面,有基础的增删改查按钮
同时呢也创建了一个SpringBoot项目,也做了一些初始配置,并且已经成功的将项目运行了起来,那么,我们今天就把后端完善,实现基本的增删改查功能
项目结构介绍
项目的整体结构目录如下
学过SSM的同学对这个目录结构是不是非常的熟悉,我们大致介绍一下每个目录的作用
bean 数据层(存放数据类) config 存放一些基本配置文件 controller 控制层(处理客户端的请求) repository 相当于DAO层(数据访问层,和数据库打交道) service 业务层的接口类(定义接口方法) serviceImpl 业务层的实现类(处理逻辑) 好了,整体项目结构以及每个目录的作用已经介绍完毕,接下来我们就开始设计吧~
bean(数据层)
我们在bean包下新建一个User类,添加两个注解
这里的@Entity注解里面为什么要加上name这个属性值呢,因为我们在上一篇中创建表的时候,保存表的表名为 t_user ,不知道大伙还记得没
如果不加上name这个属性,会默认类名小写(user)去识别数据库中的表,这时候就会对应不上,所以需要加上name属性与t_user表绑定
@Data注解会自动生成set,get,toString等方法
@GeneratedValue注解设置主键id为自增长,不然和数据库不一致会报错哦~
@Entity(name = "t_user") @Data public class User @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Integer id; private String username; private String nickname; private String password;
repository(数据访问层)
在repository包下新建一个UserRepository接口类(注意是接口哦!)
这里只需要定义接口类就行了,我们暂时还用不到自定义sql语句,所以其他不用写
public interface UserRepository extends JpaRepository<User, Integer>
service(业务层接口)
在service包下新建一个UserService接口类(注意是接口哦!)
定义五个方法(增删改查),其中查询有两个方法,一个是页面加载要显示所有用户信息的,一个是通过搜索框搜索的模糊查询
public interface UserService void insertUser(User user);// 添加用户 void deleteUser(Integer uid);// 删除用户 void updateUser(User user);// 修改用户 List<User> selectAllUser();// 查询所有用户 List<User> selectLike(String search);// 模糊查询
serviceImpl(业务层实现)
在serviceImpl包下新建一个UserServiceImpl类,实现UserService接口
前面四个基本的增删改查就不多说啦~大伙应该都知道
主要是第五个selectLike(重点!原创)这个方法,大伙可以仔细研究一下我的这个模糊查询设计模式,很有帮助的哦~ 这里不多介绍了,可以自己仔细学一学
@Service public class UserServiceImpl implements UserService @Autowired private UserRepository userRepository; @Override public void insertUser(User user) userRepository.save(user); @Override public void deleteUser(Integer uid) userRepository.deleteById(uid); @Override public void updateUser(User user) userRepository.saveAndFlush(user); @Override public List<User> selectAllUser() return userRepository.findAll(); /** * 查询优先级: * 1.先查询是否为整型,为整型则通过ID主键查询,返回结果,不为整型则模糊查询其他字段 * 2.模糊查询字段,忽略密码的模糊查询,对用户名和昵称进行模糊查询,返回结果 * @param search 查询字段 * @return 查询列表集合 */ @Override public List<User> selectLike(String search) List<User> list = new ArrayList<>();// 查询列表集合 User user = new User(); user.setUsername(search); user.setNickname(search); try Integer uid = Integer.parseInt(search); Optional<User> optional = userRepository.findById(uid); if (!optional.isPresent()) list = selectVague(user); else list.add(optional.get()); catch (NumberFormatException e) // 查询字段不为整型数据,捕获异常 list = selectVague(user); return list; /** * 模糊查询 * @param user * @return */ private List<User> selectVague(User user) List<User> list = null; ExampleMatcher matcher = ExampleMatcher.matchingAny() .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains()) .withMatcher("nickname", ExampleMatcher.GenericPropertyMatchers.contains()) .withIgnoreCase("uid") .withIgnoreCase("password"); Example<User> example = Example.of(user, matcher); list = userRepository.findAll(example); return list;
controller(控制层)
基本的一个整体流程已经搭建完毕,最后就是处理controller控制层的逻辑,我们首先完善一下上一篇中的IndexController的代码,让页面加载时候就能显示所有用户的数据、
在controller包下新建一个UserController类,设置改控制类处理所有/user下的请求
@RestController @RequestMapping(value = "/user") public class UserController
页面加载显示数据
IndexController(页面加载显示所有用户)
@RestController public class IndexController @Autowired private UserService userService; @RequestMapping(value = "/index") // 访问路径 public ModelAndView toIndex() // 返回templates目录下index.html ModelAndView view = new ModelAndView("index"); // 查询所有的用户,添加到model视图里 view.addObject("user_list", userService.selectAllUser()); return view;
前端修改
同时修改前端内容,通过th:each遍历user_list,分别获取编号,用户名,昵称,密码,通过th:text标签赋值text(对thymeleaf语法不熟悉的可以先去简单看一下基础语法哦~)
还有HTML顶部不要忘了添加支持thymeleaf语法哦~
运行结果
为了方便查看结果,预先在数据库插入几条数据
回到IDEA项目,点击右上角的debug模式启动项目,打开浏览器输入localhost:8081/index(路径根据自己情况来),就能看到数据已经成功显示上来啦
查询功能模块
Ajax异步请求局部刷新
给搜索按钮和搜索框都设置一个ID,同时给数据显示部分的div设置th:fragment标签,获取后端的代码片段
在index.js中添加代码,向后端发送异步请求
// 查询 $('#findBtn').click(function () // 发送GET异步请求 $.ajax( type: 'GET', url: '/user/select', // 请求路径 data: 'search': $('#search').val() , success: function (data) // 局部刷新数据显示部分的div $('#userTable').html(data) , error: function (err) console.log(err) alert('操作失败,请刷新重新尝试!') ) )
UserController处理查询请求
@RestController @RequestMapping(value = "/user") public class UserController // 注入业务层对象 @Autowired private UserService userService; @GetMapping(value = "/select") public ModelAndView selectLike(String search) // 返回th:fragment代码片段 ModelAndView view = new ModelAndView("index::userTable"); view.addObject("user_list", userService.selectLike(search)); return view;
运行结果
重新启动,输入xiao,成功显示
输入数值,优先查询编号
删除功能模块
刚刚的查询功能前端呢我是在index.js里面处理的,接下来删除模块我们换一个方法
首先,删除一条数据,我们是不是通关编号id进行删除呀,所以发送请求的时候是不是要传递编号数据
修改前端
在删除按钮中添加一个th:onclick标签,传递参数为当前行的编号
接着在html底部添加如下代码
<script th:inline="javascript"> function deleteBtn(id) // 发送请求 $.ajax( type: 'POST', url: '/user/delete', data: 'id': 'id' // 编号 , success: function (data) // 局部刷新 $('#userTable').html(data) , error: function (err) console.log(err) alert("操作失败,请刷新重新尝试!") ) </script>
UserController处理删除请求
添加新的方法
@PostMapping(value = "/delete") public ModelAndView deleteUser(Integer id) // 通过编号删除用户 userService.deleteUser(id); ModelAndView view = new ModelAndView("index::userTable"); // 返回新的数据列表 view.addObject("user_list", userService.selectAllUser()); return view;
运行结果
点击删除第五条数据,成功删除了第五条数据并刷新表格
添加功能模块
JS和Ajax部分
通过JQuery对提交的表单进行一些非空检验,通过之后发出POST异步请求
在index.js添加下面代码
// 添加 $('#addSubmitBtn').click(function () var username = $('#addUserName').val() var nickname = $('#addNickname').val() var password = $("#addPassword").val() // 非空效验 if (username.length == 0) alert("用户名不能为空") else if(nickname.length == 0) alert("昵称不能为空") else if (password.length == 0) alert("密码不能为空") else $.ajax( type: 'POST', url: '/user/insert', data: 'username': username, //用户名 'nickname': nickname, //昵称 'password': password //密码 , success: function (data) // 关闭modal框 $('#modal-form-add').modal('hide') // 清空modal框里上一次的数据 document.getElementById("addForm").reset() // 局部刷新 $('#userTable').html(data) , error: function (err) console.log(err) alert("操作失败,请刷新重新尝试!") ) )
UserController处理添加请求
添加新的方法
@PostMapping(value = "/insert") public ModelAndView insertUser(User user) // 插入数据 userService.insertUser(user); // 回传代码片段 ModelAndView view = new ModelAndView("index::userTable"); view.addObject("user_list", userService.selectAllUser()); return view;
修改功能模块
修改前端
当我们点击的修改的时候,弹出一个修改信息框,我们是不是要在信息框显示当前修改前的用户数据
这次我们使用th:onclick的方法快速绑定数据到弹出框,但是这次的数据有string字符串类型,之前的方法会报错,我们采用另一种新的方法
通过[[$ ]]方法传递字符串数据(那个报错小红点不用理,正常运行)
接着在HTML底部的内联javascript里加上代码
// 点击修改按钮 function updateBtn(id, username, nickname, password) // 传递数据到弹出框 $('#modal-form-update').modal('show'); $('#updateUserId').val(id) $('#updateUsername').val(username) $('#updateNickname').val(nickname) $('#updatePassword').val(password)
刷新浏览器,随便点击一个修改,成功显示数据上来了
同时给编号的input标签设置disabled属性,禁止修改
JS逻辑处理
在index.js添加如下代码
// 修改提交 $('#updateSubmitBtn').click(function () var id = $('#updateUserId').val() var username = $('#updateUsername').val() var nickname = $('#updateNickname').val() var password = $("#updatePassword").val() // 非空检验 if (username.length ==0) alert('用户名不能为空') else if (nickname.length == 0) alert('昵称不能为空') else if (password.length == 0) alert('密码不能为空') else $.ajax( type: 'POST', url: '/user/update', data: 'id': id, //编号 'username': username, //用户名 'nickname': nickname, //昵称 'password': password //密码 , success: function (data) // 关闭modal框 $('#modal-form-update').modal('hide') // 清空modal框里上一次的数据 document.getElementById("updateForm").reset() // 局部刷新 $('#userTable').html(data) , error: function (err) console.log(err) alert('操作失败,请刷新重新尝试!') ) )
UserController处理修改请求
@PostMapping(value = "update") public ModelAndView updateUser(User user) userService.updateUser(user); ModelAndView view = new ModelAndView("index::userTable"); view.addObject("user_list", userService.selectAllUser()); return view;
总结
整体的一个项目呢已经做完了,增删改查的功能都有了
其实还有很多地方可以完善的,比如搜索框回车搜索、重复代码抽取成函数单独进行等等,这些有兴趣的小伙伴自己再去优化啦~ 或者私信我帮忙也行~
这里总结我再帮大家捋一捋整个流程
- 表的设计和创建
- 搭建前端静态页面
- 搭建后端
- bean数据层
- repository数据访问层
- service业务接口
- serviceImpl业务实现
- controller控制层
- 优化前端(JS,Ajax)
Gitee开源项目下载地址(所以项目都在这里)
SpringBoot项目教学合集: CSDN中的所有SpringBoot项目开源,持续更新新项目、新教学文章
各大技术基础教学、实战项目开发教学
各大技术基础教学、实战开发教学(最新更新时间2021-12-11)
没有Gitee账号可以后台CSDN私聊我获取项目源码,或者文章留言你的邮箱我也会发给你
SpingBoot 测试如何使用SpringBoot搭建一个简单后台1
很久没写博客了,最近接到一个组内的测试开发任务是做一个使用SpringBoot 开发一个后台程序(还未完成),特写感想记录一下
1. 为什么选择SpringBoot ?
首先是目前很多公司的后台还是JAVA编写的,或者直接就是MVC的一个后台,大部分测试其实会采用python 作为一个测试语言,易上手然后见效快。
但是我们可以想见,其实在传统行业,领导更希望你能够使用同一种语言来进行一些程序或者代码的编写。
PS: 其实是因为我自己报的,我说了python或者springboot都可以,领导给我选了springboot
2. 使用springboot 你需要什么样的技术栈? 你需要了解什么才能启动起来?
一般默认的是: springboot+mybatis+(MVC三件套: mapper,entity,service,controller) 等等,你需要了解基本的java语法,以及一些sql语法
最重要的,你需要一个前端童鞋配合你,调用你的后台接口(全栈大神可以忽略)
3. 作为一个测试,你可能遇到什么问题?或者说我已经遇到了什么问题?
3.1 首先是我之前基本就很少接触过springboot, 当然对JAVA还算熟悉,开发过appium为框架下的自动化测试程序。那么你需要一个自学springboot的过程
3.2 其次是业务逻辑的学习,我需要首先把Jira 的数据拉取下来,那么需要了解Jira本身提供的那些api怎么使用
3.3 如何与前端联调,加强自己的后台开发能力
进入正题:
---------------------------------------------------------------------------------------------------------------------------------------------------------
说下我目前的开发顺序和进度(大家可以规避我的误区,直接选择新建一个SpringBoot 项目去开启):
了解需求---翻看JIRA的API---参考了博主“天外飞云”的JIRA程序---启动一个JAVA程序去调用JIRA的API---调通了之后思考如何引入SpringBoot(翻车,重新来)
---另外启动一个全新的SpringBoot程序---开始参考别人的SpringBoot入门博客---编写SpringBoot后台---调试自己完成的接口---联系前端调用----满足前端要求新增接口
分享一:
application.yml的写法 (单数据库源)
server: port: 8080 spring: datasource: name: XXXX url: jdbc:mysql://127.0.0.1:3306/XXXX?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver jpa: database-platform: org.hibernate.dialect.MySQLDialect mybatis: mapper-locations: classpath:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径 type-aliases-package: com.ctyun.springboot.entity # 注意:对应实体类的路径
分享二:
如果需要操作数据库,可以使用generatorConfig.xml去获取 ; 或者是自己先写好实体类entity ,然后自动生成数据库表。
这里我使用的是第一种,先在数据库建表,然后使用generatorConfig 提取到SpringBoot程序中
顺序: 1. 起SpringBoot 程序 2. 启动下面的generator
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包--> <classPathEntry location="C:\xxxx\mysql\mysql-connector-java\5.1.45\mysql-connector-java-5.1.45.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <property name="suppressDate" value="true"/> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="false"/> </commentGenerator> <!--数据库连接驱动类,URL,用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/xxxx?characterEncoding=utf8" userId="root" password="123456"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 生成(实体)模型的包名和位置--> <javaModelGenerator targetPackage="com.ctyun.springboot.entity" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- 生成XML映射文件的包名和位置--> <sqlMapGenerator targetPackage="resources.mapper" targetProject="src/main"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 生成DAO接口的包名和位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="com.ctyun.springboot.mapper" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名--> <!--<table tableName="xxx" domainObjectName="xxx" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>--> <!--<table tableName="xxx" domainObjectName="menus" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>--> <table tableName="xxx" domainObjectName="Menusconfig" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>
分享三:
后台可能有两种情况:
1. 不需要数据库,直接提供service+entity+controller 调用
2. 需要连接数据库,那么后台需要编写: mapper.xml --- mapper --- entity ---service ---controller 这么几层 【需要注意的是entity 相当于VO层, mapper 相当于DAO层,不用重复】
下面放一下第二种,mapper.xml的写法
下面是一个简单的用户表, 在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.ctyun.springboot.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.ctyun.springboot.entity.User"> <id column="id" property="id" jdbcType="INTEGER"/> <result column="username" property="username" jdbcType="VARCHAR"/> <result column="password" property="password" jdbcType="VARCHAR"/> <result column="nickname" property="nickname" jdbcType="VARCHAR"/> </resultMap> <sql id="Base_Column_List"> id, username, password, nickname </sql> <!--用户登录验证--> <select id="userlogin" parameterType="User" resultType="com.ctyun.springboot.entity.User"> SELECT <include refid="Base_Column_List"/> FROM user WHERE username = #username AND password = #password </select> <!--新用户注册 方式1--> <insert id="adduser" parameterType="user" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (username,password,nickname) VALUES (#username,#password,#nickname) </insert> <!--新用户注册 方式2--> <insert id="adduser1" parameterType="user"> <selectKey keyProperty="id" resultType="int"> select LAST_INSERT_ID() </selectKey> INSERT INTO user (username,password,nickname) VALUES (#username,#password,#nickname) </insert> <!--查询所有用户--> <select id="queryAllUser" resultType="map"> SELECT <include refid="Base_Column_List"/> FROM user </select> <!--查询数据库里面的username--> <select id="queryUserName" resultType="java.lang.String"> SELECT username FROM user </select>
</mapper>
以上是关于使用SpringBoot一小时快速搭建一个简单后台管理(后端篇)的主要内容,如果未能解决你的问题,请参考以下文章
SpingBoot 测试如何使用SpringBoot搭建一个简单后台1
SpringBoot 学习笔记 -- [了解SpringBoot的基础知识,快速上手搭建一个简单案例]