原文地址:http://www.work100.net/training/monolithic-project-iot-cloud-admin-manager-search.html
更多教程:光束云 - 免费课程
搜索功能
序号 | 文内章节 | 视频 |
---|---|---|
1 | 概述 | - |
2 | 使用动态SQL | - |
3 | 修改AuthManagerDao接口 | - |
4 | 修改AuthManagerService接口 | - |
5 | 定义搜索器ManagerSearcher | - |
6 | 修改AuthManagerServiceImpl实现 | - |
7 | 修改ManagerController | - |
8 | 修改视图文件 | - |
9 | 测试验证 | - |
10 | 实例源码 | - |
请参照如上章节导航
进行阅读
1.概述
接下来实现 账户列表
页面的 搜索功能
,预期实现的画面效果如下:
1.1.简单搜索
1.2.复杂搜索
2.使用动态SQL
因搜索功能的查询条件是动态变化的,所以我们的查询语句也需要动态生成,这里就需要使用我们前述章节 MyBatis 动态 SQL 讲述的知识。
我们在 AuthManagerMapper.xml
映射文件中新增一个 select
语句 search
,代码如下:
<select id="search" resultType="AuthManager">
SELECT
<include refid="authManagerColumns" />
FROM
auth_manager AS a
<where>
<if test="userName != null and userName != ''">
AND a.user_name LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="roles != null and roles != ''">
AND a.roles LIKE CONCAT('%', #{roles}, '%')
</if>
<if test="status != -1">
AND a.status = #{status}
</if>
</where>
ORDER BY a.id DESC
</select>
3.修改AuthManagerDao接口
增加 search
方法,代码如下:
/**
* 搜索
*
* @param authManager
* @return
*/
List<AuthManager> search(AuthManager authManager);
4.修改AuthManagerService接口
增加 search
方法,代码如下:
/**
* 搜索
*
* @param managerSearcher 搜索器
* @return
*/
List<AuthManager> search(ManagerSearcher managerSearcher);
这里面我们引入了
ManagerSearcher
搜索器类,该类用于传递查询参数,下面将完成其实现代码
5.定义搜索器ManagerSearcher
5.1.BaseSearcher 类
在 iot-cloud-commons
项目下的 net.work100.training.stage2.iot.cloud.commons.dto
包中新增一个 BaseSearcher
类,代码如下:
package net.work100.training.stage2.iot.cloud.commons.dto;
import java.io.Serializable;
/**
* <p>Title: Searcher</p>
* <p>Description: </p>
*
* @author liuxiaojun
* @date 2020-03-08 16:45
* ------------------- History -------------------
* <date> <author> <desc>
* 2020-03-08 liuxiaojun 初始创建
* -----------------------------------------------
*/
public abstract class BaseSearcher implements Serializable {
private String keyword;
private boolean advanced;
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public boolean isAdvanced() {
return advanced;
}
public void setAdvanced(boolean advanced) {
this.advanced = advanced;
}
}
5.2.ManagerSearcher 类
在 iot-cloud-web-admin
项目下增加一个 net.work100.training.stage2.iot.cloud.web.admin.dto.auth
类包,然后该类包下新建一个 ManagerSearcher
类,代码如下:
package net.work100.training.stage2.iot.cloud.web.admin.dto.auth;
import net.work100.training.stage2.iot.cloud.commons.dto.BaseSearcher;
/**
* <p>Title: ManagerSearcher</p>
* <p>Description: </p>
* <p>Url: http://www.work100.net/training/monolithic-project-iot-cloud-admin.html</p>
*
* @author liuxiaojun
* @date 2020-03-08 17:02
* ------------------- History -------------------
* <date> <author> <desc>
* 2020-03-08 liuxiaojun 初始创建
* -----------------------------------------------
*/
public class ManagerSearcher extends BaseSearcher {
private String userName;
private String roles;
private int status;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
6.修改AuthManagerServiceImpl实现
实现 search
方法,代码如下:
@Override
public List<AuthManager> search(ManagerSearcher managerSearcher) {
AuthManager authManager = new AuthManager();
if (!managerSearcher.isAdvanced()) {
authManager.setUserName(managerSearcher.getKeyword());
authManager.setRoles("");
authManager.setStatus(-1);
} else {
authManager.setUserName(managerSearcher.getUserName());
authManager.setRoles(managerSearcher.getRoles());
authManager.setStatus(managerSearcher.getStatus());
}
return authManagerDao.search(authManager);
}
7.修改ManagerController
7.1.修改 list 方法
@RequestMapping(value = "list", method = RequestMethod.GET)
public String list(Model model) {
ManagerSearcher managerSearcher = new ManagerSearcher();
managerSearcher.setKeyword("");
managerSearcher.setAdvanced(false);
managerSearcher.setRoles("");
managerSearcher.setStatus(-1);
model.addAttribute(managerSearcher);
List<AuthManager> authManagers = authManagerService.selectAll();
model.addAttribute("authManagers", authManagers);
return "auth/manager_list";
}
7.2.新增 search 方法
@RequestMapping(value = "search", method = RequestMethod.POST)
public String search(ManagerSearcher managerSearcher, Model model) {
List<AuthManager> authManagers = authManagerService.search(managerSearcher);
model.addAttribute("managerSearcher", managerSearcher);
model.addAttribute("authManagers", authManagers);
return "auth/manager_list";
}
8.修改视图文件
下面修改视图文件 manager_list.jsp
的实现代码。
8.1.引入 form 表单标签库
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
8.2.搜索功能实现
修改 <div class="card">
标签部分代码,修改后的代码如下:
<form:form action="/auth/manager/search" method="post" modelAttribute="managerSearcher">
<form:hidden path="advanced" />
<div class="card">
<div class="card-header">
<div class="card-title">
<div class="btn-group">
<a href="/auth/manager/add" type="button" class="btn btn-primary">新增</a>
<button type="button" class="btn btn-default">更多...</button>
<button type="button" class="btn btn-default dropdown-toggle dropdown-icon" data-toggle="dropdown">
<span class="sr-only">Toggle Dropdown</span>
<div class="dropdown-menu" role="menu">
<a class="dropdown-item" href="#">批量锁定</a>
<a class="dropdown-item" href="#">批量解锁</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">批量删除</a>
</div>
</button>
</div>
<div class="btn-group">
<a href="/auth/manager/list" type="button" class="btn btn-default" title="重新加载"><i class="fas fa-redo"></i></a>
<button type="button" class="btn btn-default" title="打印"><i class="fas fa-print"></i></button>
<button type="button" class="btn btn-default" title="下载"><i class="fas fa-download"></i></button>
</div>
</div>
<div id="btnOpen" class="card-tools" style="display: ${managerSearcher.advanced?"none":"block"};">
<div class="input-group" style="padding-top: 5px;">
<form:input path="keyword" cssClass="form-control" placeholder="关键字:用户名" />
<div class="input-group-append">
<button type="submit" class="btn btn-default">搜索
<i class="fas fa-search"></i></button>
</div>
<div class="input-group-append">
<button type="button" class="btn btn-default" title="展开更多" onclick="showSearcher()">
展开 <i class="fas fa-angle-double-down"></i></button>
</div>
</div>
</div>
<div id="btnClose" class="card-tools" style="display: ${managerSearcher.advanced?"block":"none"};">
<div class="input-group" style="padding-top: 5px;">
<div class="input-group-append">
<button type="button" class="btn btn-default" title="合拢更多" onclick="hideSearcher()">
合拢 <i class="fas fa-angle-double-up"></i></button>
</div>
</div>
</div>
</div>
<div class="card-header" id="searcher" style="display: ${managerSearcher.advanced?"block":"none"};background-color: #f2f4f8;">
<div class="row">
<div class="col-md-9">
<div class="input-group">
<form:input path="userName" cssClass="form-control" placeholder="用户名" />
<form:select path="roles" class="form-control select2" style="width: 150px;">
<option value="" ${managerSearcher.roles == "" ? "selected" : ""}>
角色
</option>
<option value="admin" ${managerSearcher.roles == "admin" ? "selected" : ""}>
admin
</option>
<option value="editor" ${managerSearcher.roles == "editor" ? "selected" : ""}>
editor
</option>
</form:select>
<form:select path="status" class="form-control select2" style="width: 150px;">
<option value="-1" ${managerSearcher.status == -1 ? "selected" : ""}>
状态
</option>
<option value="0" ${managerSearcher.status == 0 ? "selected" : ""}>
未激活
</option>
<option value="1" ${managerSearcher.status == 1 ? "selected" : ""}>
激活
</option>
<option value="2" ${managerSearcher.status == 2 ? "selected" : ""}>
锁定
</option>
<option value="3" ${managerSearcher.status == 3 ? "selected" : ""}>
删除
</option>
</form:select>
</div>
</div>
<div class="col-md-3">
<div class="btn-group">
<button type="submit" class="btn btn-primary">搜 索</button>
</div>
<div class="btn-group">
<a href="/auth/manager/list" type="button" class="btn btn-default">重 置</a>
</div>
</div>
</div>
</div>
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>角色</th>
<th>超级用户</th>
<th>状态</th>
<th>更新时间</th>
<th width="120px" align="center">操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${authManagers}" var="authManager">
<tr>
<td>${authManager.id}</td>
<td>${authManager.userName}</td>
<td>${authManager.roles}</td>
<td>${authManager.superuser?"是":"否"}</td>
<td>
<c:choose>
<c:when test="${authManager.status==0}">
<label class="text-muted">未激活</label>
</c:when>
<c:when test="${authManager.status==1}">
<label class="text-success">已激活</label>
</c:when>
<c:when test="${authManager.status==2}">
<label class="text-warning">锁定</label>
</c:when>
<c:when test="${authManager.status==3}">
<label class="text-danger">被删除</label>
</c:when>
</c:choose>
</td>
<td>
<fmt:formatDate value="${authManager.updated}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>
<div class="btn-group">
<a href="#" type="button" class="btn btn-default btn-sm"><i class="fas fa-eye"></i></a>
<a href="/auth/manager/edit/${authManager.userKey}" type="button" class="btn btn-primary btn-sm"><i class="fas fa-edit"></i></a>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#modal-operate-confirm" data-whatever="${authManager.userKey}">
<i class="fas fa-trash"></i></button>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</form:form>
8.3.修改 JS 脚本
修改页面中自定义的 JS 脚本,增加 select
控件的初始化,以及增加 高级搜索
表单的显示
与隐藏
功能,代码如下:
$(function() {
//Initialize Select2 Elements
$('.select2').select2();
//Initialize Select2 Elements
$('.select2bs4').select2({
theme: 'bootstrap4'
});
if (${baseResult.status != null && baseResult.status == 200}) {
const Toast = Swal.mixin({
toast: true,
position: 'top',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
})
Toast.fire({
type: 'success',
title: '${baseResult.message}'
})
}
$('#modal-operate-confirm').on('show.bs.modal', function(event) {
let trigger = $(event.relatedTarget)
let userKey = trigger.data('whatever')
let modal = $(this)
let ok = modal.find('.modal-footer button')[1]
$(ok).click(function(e) {
location.href = '/auth/manager/delete/' + userKey
})
})
})
// 显示高级搜索
function showSearcher() {
$("#advanced").val(true);
$("#searcher").css('display', 'block');
$("#btnOpen").css('display', 'none');
$("#btnClose").css('display', 'block');
}
// 隐藏高级搜索
function hideSearcher() {
$("#advanced").val(false);
$("#searcher").css('display', 'none');
$("#btnOpen").css('display', 'block');
$("#btnClose").css('display', 'none');
}
8.4.完整代码
视图 manager_list.jsp
文件的完整代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<title>查询列表 - 后台账户 | IoT-Admin</title>
<jsp:include page="../includes/resources_head.jsp" />
</head>
<body class="hold-transition sidebar-mini">
<div class="wrapper">
<jsp:include page="../includes/layout_header.jsp" />
<jsp:include page="../includes/layout_left.jsp" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">查询列表</h1>
</div><!-- /.col -->
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#">后台账户</a></li>
<li class="breadcrumb-item active">查询列表</li>
</ol>
</div><!-- /.col -->
</div><!-- /.row -->
</div><!-- /.container-fluid -->
</div>
<!-- /.content-header -->
<!-- Main content -->
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col">
<form:form action="/auth/manager/search" method="post" modelAttribute="managerSearcher">
<form:hidden path="advanced" />
<div class="card">
<div class="card-header">
<div class="card-title">
<div class="btn-group">
<a href="/auth/manager/add" type="button" class="btn btn-primary">新增</a>
<button type="button" class="btn btn-default">更多...</button>
<button type="button" class="btn btn-default dropdown-toggle dropdown-icon" data-toggle="dropdown">
<span class="sr-only">Toggle Dropdown</span>
<div class="dropdown-menu" role="menu">
<a class="dropdown-item" href="#">批量锁定</a>
<a class="dropdown-item" href="#">批量解锁</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">批量删除</a>
</div>
</button>
</div>
<div class="btn-group">
<a href="/auth/manager/list" type="button" class="btn btn-default" title="重新加载"><i class="fas fa-redo"></i></a>
<button type="button" class="btn btn-default" title="打印"><i class="fas fa-print"></i></button>
<button type="button" class="btn btn-default" title="下载"><i class="fas fa-download"></i></button>
</div>
</div>
<div id="btnOpen" class="card-tools" style="display: ${managerSearcher.advanced?"none":"block"};">
<div class="input-group" style="padding-top: 5px;">
<form:input path="keyword" cssClass="form-control" placeholder="关键字:用户名" />
<div class="input-group-append">
<button type="submit" class="btn btn-default">搜索
<i class="fas fa-search"></i></button>
</div>
<div class="input-group-append">
<button type="button" class="btn btn-default" title="展开更多" onclick="showSearcher()">
展开 <i class="fas fa-angle-double-down"></i></button>
</div>
</div>
</div>
<div id="btnClose" class="card-tools" style="display: ${managerSearcher.advanced?"block":"none"};">
<div class="input-group" style="padding-top: 5px;">
<div class="input-group-append">
<button type="button" class="btn btn-default" title="合拢更多" onclick="hideSearcher()">
合拢 <i class="fas fa-angle-double-up"></i></button>
</div>
</div>
</div>
</div>
<div class="card-header" id="searcher" style="display: ${managerSearcher.advanced?"block":"none"};background-color: #f2f4f8;">
<div class="row">
<div class="col-md-9">
<div class="input-group">
<form:input path="userName" cssClass="form-control" placeholder="用户名" />
<form:select path="roles" class="form-control select2" style="width: 150px;">
<option value="" ${managerSearcher.roles == "" ? "selected" : ""}>
角色
</option>
<option value="admin" ${managerSearcher.roles == "admin" ? "selected" : ""}>
admin
</option>
<option value="editor" ${managerSearcher.roles == "editor" ? "selected" : ""}>
editor
</option>
</form:select>
<form:select path="status" class="form-control select2" style="width: 150px;">
<option value="-1" ${managerSearcher.status == -1 ? "selected" : ""}>
状态
</option>
<option value="0" ${managerSearcher.status == 0 ? "selected" : ""}>
未激活
</option>
<option value="1" ${managerSearcher.status == 1 ? "selected" : ""}>
激活
</option>
<option value="2" ${managerSearcher.status == 2 ? "selected" : ""}>
锁定
</option>
<option value="3" ${managerSearcher.status == 3 ? "selected" : ""}>
删除
</option>
</form:select>
</div>
</div>
<div class="col-md-3">
<div class="btn-group">
<button type="submit" class="btn btn-primary">搜 索</button>
</div>
<div class="btn-group">
<a href="/auth/manager/list" type="button" class="btn btn-default">重 置</a>
</div>
</div>
</div>
</div>
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>角色</th>
<th>超级用户</th>
<th>状态</th>
<th>更新时间</th>
<th width="120px" align="center">操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${authManagers}" var="authManager">
<tr>
<td>${authManager.id}</td>
<td>${authManager.userName}</td>
<td>${authManager.roles}</td>
<td>${authManager.superuser?"是":"否"}</td>
<td>
<c:choose>
<c:when test="${authManager.status==0}">
<label class="text-muted">未激活</label>
</c:when>
<c:when test="${authManager.status==1}">
<label class="text-success">已激活</label>
</c:when>
<c:when test="${authManager.status==2}">
<label class="text-warning">锁定</label>
</c:when>
<c:when test="${authManager.status==3}">
<label class="text-danger">被删除</label>
</c:when>
</c:choose>
</td>
<td>
<fmt:formatDate value="${authManager.updated}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>
<div class="btn-group">
<a href="#" type="button" class="btn btn-default btn-sm"><i class="fas fa-eye"></i></a>
<a href="/auth/manager/edit/${authManager.userKey}" type="button" class="btn btn-primary btn-sm"><i class="fas fa-edit"></i></a>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#modal-operate-confirm" data-whatever="${authManager.userKey}">
<i class="fas fa-trash"></i></button>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</form:form>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- /.content -->
<div class="modal fade" id="modal-operate-confirm">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">操作确认</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>操作后不可恢复,确定吗?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary">确定</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
</div>
<!-- /.content-wrapper -->
<jsp:include page="../includes/layout_footer.jsp" />
</div>
<!-- ./wrapper -->
<jsp:include page="../includes/resources_body.jsp" />
<script>
$(function() {
//Initialize Select2 Elements
$('.select2').select2();
//Initialize Select2 Elements
$('.select2bs4').select2({
theme: 'bootstrap4'
});
if (${baseResult.status != null && baseResult.status == 200}) {
const Toast = Swal.mixin({
toast: true,
position: 'top',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true
})
Toast.fire({
type: 'success',
title: '${baseResult.message}'
})
}
$('#modal-operate-confirm').on('show.bs.modal', function(event) {
let trigger = $(event.relatedTarget)
let userKey = trigger.data('whatever')
let modal = $(this)
let ok = modal.find('.modal-footer button')[1]
$(ok).click(function(e) {
location.href = '/auth/manager/delete/' + userKey
})
})
})
// 显示高级搜索
function showSearcher() {
$("#advanced").val(true);
$("#searcher").css('display', 'block');
$("#btnOpen").css('display', 'none');
$("#btnClose").css('display', 'block');
}
// 隐藏高级搜索
function hideSearcher() {
$("#advanced").val(false);
$("#searcher").css('display', 'none');
$("#btnOpen").css('display', 'block');
$("#btnClose").css('display', 'none');
}
</script>
</body>
</html>
9.测试验证
重启 Tomcat
运行并验证搜索功能效果。
10.实例源码
实例源码已经托管到如下地址:
- https://github.com/work100-net/training-stage2/tree/master/iot-cloud3
- https://gitee.com/work100-net/training-stage2/tree/master/iot-cloud3
上一篇:删除账户
上一篇:JS代码重构
如果对课程内容感兴趣,可以扫码关注我们的
公众号
或QQ群
,及时关注我们的课程更新