项目是一个简单的员工管理系统,适合初学springboot的人入门练手,有简单的增删改查,也有分页查询,复杂条件模糊查询等一些功能,麻雀虽小,但五脏六全,哈哈哈…博客尾部会附上源码,现在主要分析一下功能思路!
- 使用拦截器技术,达到必须登录才能访问,会提示"对不起,您尚未登录"的提示信息
- 可以删除一个,也可以批量删除,全选
- 点击编辑员工信息,会回显员工信息,进而再来修改
关于登录功能更详细的参考这篇博客
单个删除: 给删除按钮绑定单击事件,带上员工的id参数,就可以删除
<!--删除功能-->
<button class="btn btn-sm btn-danger deleteBtn" th:attr="uri=@{/emp/}+${emp.id}">删除</button>
但是我的项目是restful风格的,所以删除请求路径还是emp,但是改变他的请求方式为delete
如何改变请求方式?
1.建立一个表单,post请求方式
2.建立隐藏域,_methed,value就是改变的请求方式
<form id="delForm" action="#" method="post">
<input type="hidden" name="_method" value="delete">
</form>
3.绑定单击事件,提交表单:
<script>
/*删除功能*/
$(".deleteBtn").click(function () {
//删除当前员工
if(confirm("你确定要删除吗?")){
$("#delForm").attr("action",$(this).attr("uri")).submit();
return false;
}
});
</script>
批量删除: 批量删除一个道理,给选中删除按钮绑定单击事件,给复选框的value值设置为员工id
<td><input type="checkbox" class="td_checkbox" name="eid" th:value="${emp.id}"></td>
<script>
/*全选功能*/
$("#th_checkbox").click(function () {
$(".td_checkbox").attr("checked", this.checked);
});
/*删除选中:给删除选中按钮绑定单击事件,点击提交表单,携带删除的员工id*/
$("#delAll").click(function () {
if(confirm("你确定要删除所有选中吗?")){
$("#delSelected").attr("action",$(this).attr("uri")).submit();
return false;
}
});
</script>
controller: 控制层可以使用request获取id集合
//删除选中
@DeleteMapping("/emps")
public String delSelected(HttpServletRequest request){
//获取被选中的所有员工id
String[] eids = request.getParameterValues("eid");
System.out.println(eids);
empService.delSelected(eids);
return "redirect:/emps";
}
service: 然后遍历集合,调用mapper删除
//批量删除员工
@Override
public void delSelected(String[] ids) {
if(ids != null && ids.length > 0){
//1.遍历数组
for (String id : ids) {
//2.调用mapper删除
mapper.deleteEmp(Integer.parseInt(id));
}
}
}
添加功能和修改功能相对简单,把前端提交的参数封装到Emp对象中,然后调用mapper插入数据就可以了,主要技术难点在于修改功能中的回显,就是编辑某个员工的信息时,可以向后端发送请求查询该员工信息,然后回显在前端页面,接着修改信息并提交插入
核心代码:
<form th:action="@{/emp}" method="post">
<!--如何修改请求方式?
1.页面创建一个post表单
2.创建一个input项,name="_method";值就是我们指定的请求方式
-->
<input type="hidden" name="_method" value="put" th:if="${emp!=null}">
<input type="hidden" name="id" th:value="${emp.id}" th:if="${emp!=null}">
<div class="form-group">
<label>name</label>
<input type="text" class="form-control" name="name" placeholder="zhangsan" th:value="${emp!=null}?${emp.name}">
</div>
<div class="form-group">
<label>email</label>
<input type="email" class="form-control" name="email" placeholder="[email protected]" th:value="${emp!=null}?${emp.email}">
</div>
<div class="form-group">
<label>gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="男" th:checked="${emp!=null}?${emp.gender=='男'}">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="女" th:checked="${emp!=null}?${emp.gender=='女'}">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select class="form-control" name="deptId">
<option th:selected="${emp!=null}?${dept.id==emp.deptId}" th:value="${dept.id}" th:each="dept:${depts}">[[${dept.deptName}]]</option>
</select>
</div>
<div class="form-group">
<label>birth</label>
<input type="date" class="form-control" name="birth" placeholder="zhangsan" th:value="${emp!=null}?${#dates.format(emp.birth, 'yyyy-MM-dd')}">
</div>
<button type="submit" class="btn btn-primary" th:text="${emp!=null}?'修改':'添加'">添加</button>
</form>
思路:
1.前端需要给后端传入哪儿些信息?
1、当前页码(currentPage)
2、每页显示多少条数据(pageSize)
3、这两个参数是必须的,后端会根据当前页码和每页显示多少来响应数据给前端
2.后端需要给前端响应哪儿些信息?
1、总记录数(totalCount):数据库查了多少条数据
2、总页码数(totalPage):总共有多少页,分页导航条需要用,一开始用的是假的分页导航条,只有查了数据库才知道有多少条记录,分了多少页,然后响应给前端,分页导航条遍历一下就可以了
3、查询的员工数据集合(List)
3.为了方便交互,可以把这些参数封装到一个JavaBean对象中,前后端交互直接通过这个PageBean对象
/**
* 分页对象,实现分页查询
* 前端传入:currentPage 当前页码
* pageSize 每页显示多少条记录
* 后端响应:totalCount 总记录数
* totalPage 总页码
* List list 每页的数据
*/
public class PageBean<T> implements Serializable {
private Integer totalPage;//总页码
private Integer totalCount;//总记录数
private Integer pageSize;//每页显示多少条记录
private Integer currentPage;//当前页码
private List<T> list;//每页的数据
核心代码:
controller:
//分页查询+复杂查询
@GetMapping("/emps")
public String findAllEmp(PageBean<Emp> pageBean,Emp emp,Model model){
if (pageBean.getCurrentPage()==null||"".equals(pageBean.getCurrentPage())){
pageBean.setCurrentPage(1);
}
if (pageBean.getPageSize()==null||"".equals(pageBean.getPageSize())){
pageBean.setPageSize(7);
}
PageBean<Emp> pb = empService.findAll(pageBean,emp);
List<Department> depts = deptService.findAll();
model.addAttribute("depts",depts);
model.addAttribute("pb",pb);
model.addAttribute("emp",emp);
return "emp/list";
}
- 首先要判断前端前端传入的currentPage和pageSize是否为空,因为在删除和添加功能操作后,会直接转到查询页面,这样是无法带参数的,所以可以加个判断,如果为空,可以将其赋值
- 然后调用service层查询,再把数据存入request域中响应给前端页面
service:
//分页查询所有员工 + 复杂查询
@Override
public PageBean<Emp> findAll(PageBean<Emp> pageBean,Emp emp) {
int currentPage = pageBean.getCurrentPage(); //获取前端传来的currentPage
//控制上一页操作超出
if(currentPage<1){
currentPage=1;
}
int pageSize = pageBean.getPageSize(); //获取前端传来的pageSize
//创建一个新的pageBean对象
PageBean<Emp> pb = new PageBean<Emp>();
//设置参数
pb.setCurrentPage(currentPage);
pb.setPageSize(pageSize);
//查询总记录数,并设置到新的pb对象中
Integer totalCount = mapper.findTotalCount(emp.getName(),emp.getGender(),emp.getDeptId());
pb.setTotalCount(totalCount);
//查询emp集合数据,先计算开始的索引
int start = (currentPage-1)*pageSize;
List<Emp> emps = mapper.findAll(start,pageSize,emp.getName(),emp.getGender(),emp.getDeptId());
pb.setList(emps);
//计算总页码
int totalPage = (totalCount % pageSize) == 0 ? totalCount/pageSize : (totalCount/pageSize) + 1;
pb.setTotalPage(totalPage);
//控制下一页操作超出
if (currentPage>=totalPage){
currentPage=totalPage;
pb.setCurrentPage(currentPage);
}
return pb;
}
前端页面:
分页导航条
<div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item">
<a class="page-link" href="#" th:href="@{/emps(currentPage=${pb.currentPage}-1,pageSize=7,name=${emp.name},gender=${emp.gender},deptId=${emp.deptId})}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<th:block th:each="page:${#numbers.sequence(1,pb.totalPage)}" >
<li class="page-item " th:class="${(pb.currentPage==page)?'page-item active':'page-item'}"><a class="page-link" href="#" th:href="@{/emps(currentPage=${page},pageSize=7,name=${emp.name},gender=${emp.gender},deptId=${emp.deptId})}" th:text="${page}"></a></li>
</th:block>
<li class="page-item">
<a class="page-link" href="#" th:href="@{/emps(currentPage=${pb.currentPage}+1,pageSize=7,name=${emp.name},gender=${emp.gender},deptId=${emp.deptId})}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<li>
<span id="span_page">共<span style="color: red">[[${pb.totalPage}]]</span>页,<span style="color: red">[[${pb.totalCount}]]</span>条记录</span>
</li>
</ul>
</nav>
</div>
员工数据
<tbody>
<form id="delSelected" action="#" method="post">
<input type="hidden" name="_method" value="delete">
<tr th:each="emp:${pb.list}">
<td><input type="checkbox" class="td_checkbox" name="eid" th:value="${emp.id}"></td>
<!--使用emp来遍历emps,所以其默认状态变量为:empStat,empStat.count实现循环时递增序号-->
<td th:text="${empStat.count}"></td>
<td th:text="${emp.id}"></td>
<td th:text="${emp.name}"></td>
<td th:text="${emp.email}"></td>
<td th:text="${emp.gender}"></td>
<td th:text="${emp.deptId}"></td>
<td th:text="${#dates.format(emp.birth,'yyyy-MM-dd')}"></td>
<td>
<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a>
<!--删除功能-->
<button class="btn btn-sm btn-danger deleteBtn" th:attr="uri=@{/emp/}+${emp.id}">删除</button>
</td>
</tr>
</form>
</tbody>
mapper:
<select id="findAll" parameterType="map" resultMap="empMap">
select * from emp
<where>
<if test="name!=null and name !=''">
and name like #{name}
</if>
<if test="gender!=null and gender !=''">
and gender = #{gender}
</if>
<if test="deptId!=null and deptId!='' and deptId!=0">
and dept_id = #{deptId}
</if>
</where>
limit #{start},#{pageSize}
</select>
- 用where,if标签实现动态SQL语句,根据参数的不同就可以实现分页查询+复杂条件查询
想要了解更多细节,可自取源码学习
链接:https://pan.baidu.com/s/1GyABuboKeSsRF_tnmzLlSw
提取码:8691
有啥错误大家可以指出,相互学习哈~~