day03【后台】管理员维护
1、分页
1.1、思路
1.2、导入依赖
在component
工程中导入PageHelper
的依赖
< dependency>
< groupId> com.github.pagehelper</ groupId>
< artifactId> pagehelper</ artifactId>
</ dependency>
1.3、配置 PageHelper
Spring
的配置文件中,在 SqlSessionFactoryBean
中配置 PageHelper
插件
< bean id = " sqlSessionFactoryBean"
class = " org.mybatis.spring.SqlSessionFactoryBean" >
< property name = " dataSource" ref = " dataSource" />
< property name = " configLocation"
value = " classpath:mybatis-config.xml" />
< property name = " mapperLocations"
value = " classpath:mybatis/mapper/*Mapper.xml" />
< property name = " plugins" >
< array>
< bean class = " com.github.pagehelper.PageHelper" >
< property name = " properties" >
< props>
< prop key = " dialect" > mysql</ prop>
< prop key = " reasonable" > true</ prop>
</ props>
</ property>
</ bean>
</ array>
</ property>
</ bean>
1.4、编写Mapper
在AdminMapper
接口中添加selectAdminByKeyword
方法声明,该方法根据关键字搜索用户
List< Admin> selectAdminByKeyword ( String keyword) ;
在AdminMapper.xml
中添加selectAdminByKeyword
方法对应的查询SQL
语句
< select id = " selectAdminByKeyword" resultMap = " BaseResultMap" >
select id, login_acct, user_pswd, user_name, email, create_time
from t_admin
where
login_acct like concat("%",#{keyword},"%") or
user_name like concat("%",#{keyword},"%") or
email like concat("%",#{keyword},"%")
</ select>
1.5、编写Service
在AdminService.java
接口下添加getPageInfo
方法,用于查询管理员分页数据
PageInfo< Admin> getPageInfo ( String keyword, Integer pageNum, Integer pageSize) ;
在AdminServiceImpl.java
中实现上述方法
@Override
public PageInfo< Admin> getPageInfo ( String keyword, Integer pageNum, Integer pageSize) {
PageHelper. startPage ( pageNum, pageSize) ;
List< Admin> list = adminMapper. selectAdminByKeyword ( keyword) ;
return new PageInfo < > ( list) ;
}
1.6、编写Handler
在AdminHandler
调用AdminService
获取数据
@RequestMapping ( "/admin/get/page.html" )
public String getPageInfo (
@RequestParam ( value= "keyword" , defaultValue= "" ) String keyword,
@RequestParam ( value= "pageNum" , defaultValue= "1" ) Integer pageNum,
@RequestParam ( value= "pageSize" , defaultValue= "5" ) Integer pageSize,
ModelMap modelMap
) {
PageInfo< Admin> pageInfo = adminService. getPageInfo ( keyword, pageNum, pageSize) ;
modelMap. addAttribute ( CrowdConstant. ATTR_NAME_PAGE_INFO, pageInfo) ;
return "admin-page" ;
}
1.7、编写页面
在component
工程的pom
文件中引入JSTL
标签库依赖
< dependency>
< groupId> jstl</ groupId>
< artifactId> jstl</ artifactId>
</ dependency>
在include-sidebar.jsp
页面中添加跳转地址
< li style =" height : 30px; " > < a href = " admin/get/page.html" > < i
class = " glyphicon glyphicon-user" > </ i> 用户维护</ a> </ li>
在admin-page.jsp
页面中取出数据并显示
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
< html lang = " zh-CN" >
<%@include file="/WEB-INF/include-head.jsp"%>
< body>
<%@ include file="/WEB-INF/include-nav.jsp"%>
< div class = " container-fluid" >
< div class = " row" >
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
< div class = " col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< div class = " panel panel-default" >
< div class = " panel-heading" >
< h3 class = " panel-title" >
< i class = " glyphicon glyphicon-th" > </ i> 数据列表
</ h3>
</ div>
< div class = " panel-body" >
< form class = " form-inline" role = " form" style =" float : left; " >
< div class = " form-group has-feedback" >
< div class = " input-group" >
< div class = " input-group-addon" > 查询条件</ div>
< input class = " form-control has-success" type = " text"
placeholder = " 请输入查询条件" >
</ div>
</ div>
< button type = " button" class = " btn btn-warning" >
< i class = " glyphicon glyphicon-search" > </ i> 查询
</ button>
</ form>
< button type = " button" class = " btn btn-danger"
style =" float : right; margin-left : 10px; " >
< i class = " glyphicon glyphicon-remove" > </ i> 删除
</ button>
< button type = " button" class = " btn btn-primary"
style =" float : right; " onclick = " window.location.href=' add.html' " >
< i class = " glyphicon glyphicon-plus" > </ i> 新增
</ button>
< br>
< hr style =" clear : both; " >
< div class = " table-responsive" >
< table class = " table table-bordered" >
< thead>
< tr>
< th width = " 30" > #</ th>
< th width = " 30" > < input type = " checkbox" > </ th>
< th> 账号</ th>
< th> 名称</ th>
< th> 邮箱地址</ th>
< th width = " 100" > 操作</ th>
</ tr>
</ thead>
< tbody>
< c: if test = " ${empty requestScope.pageInfo.list }" >
< tr>
< td colspan = " 6" align = " center" > 抱歉!没有查询到您要的数据!</ td>
</ tr>
</ c: if>
< c: if test = " ${!empty requestScope.pageInfo.list }" >
< c: forEach items = " ${requestScope.pageInfo.list }" var = " admin"
varStatus = " myStatus" >
< tr>
< td> ${myStatus.count }</ td>
< td> < input type = " checkbox" > </ td>
< td> ${admin.loginAcct }</ td>
< td> ${admin.userName }</ td>
< td> ${admin.email }</ td>
< td>
< button type = " button" class = " btn btn-success btn-xs" >
< i class = " glyphicon glyphicon-check" > </ i>
</ button>
< button type = " button" class = " btn btn-primary btn-xs" >
< i class = " glyphicon glyphicon-pencil" > </ i>
</ button>
< button type = " button" class = " btn btn-danger btn-xs" >
< i class = " glyphicon glyphicon-remove" > </ i>
</ button>
</ td>
</ tr>
</ c: forEach>
</ c: if>
</ tbody>
< tfoot>
< tr>
< td colspan = " 6" align = " center" >
< ul class = " pagination" >
< li class = " disabled" > < a href = " #" > 上一页</ a> </ li>
< li class = " active" > < a href = " #" > 1 < span
class = " sr-only" > (current)</ span> </ a> </ li>
< li> < a href = " #" > 2</ a> </ li>
< li> < a href = " #" > 3</ a> </ li>
< li> < a href = " #" > 4</ a> </ li>
< li> < a href = " #" > 5</ a> </ li>
< li> < a href = " #" > 下一页</ a> </ li>
</ ul>
</ td>
</ tr>
</ tfoot>
</ table>
</ div>
</ div>
</ div>
</ div>
</ div>
</ div>
</ body>
</ html>
1.8、测试
1.9、Tips
以上部分均为day02
内容,以下部分才是day03
内容
2、分页导航条
2.1、导入资源
在webapp
目录下引入Pagination
所需要的js
和css
库
2.2、在需要的页面引入资源
在admin-page.jsp
页面引入相关的资源,由于<%@include%>
引入了jQuery
,将资源的引入jQuery
的后面
<%@include file="/WEB-INF/include-head.jsp" %>
<link rel="stylesheet" href="css/pagination.css" />
<script type="text/javascript" src="jquery/jquery.pagination.js" ></script>
2.3、加入分页条
< tfoot>
< tr>
< td colspan = " 6" align = " center" >
< div id = " Pagination" class = " pagination" >
</ div>
</ td>
</ tr>
</ tfoot>
2.4、使用Pagination
在admin-page.jsp
页面下添加如下代码,使用Pagination
生成分页条
<script type="text/javascript">
$(function() {
// 调用后面声明的函数对页码导航条进行初始化操作
initPagination ( ) ;
} ) ;
// 生成页码导航条的函数
function initPagination() {
// 获取总记录数
var totalRecord = $ { requestScope.pageInfo.total} ;
// 声明一个JSON对象存储Pagination要设置的属性
var properties = {
num_edge_entries: 3, // 边缘页数
num_display_entries: 5, // 主体页数
callback: pageSelectCallback, // 指定用户点击“翻页”的按钮时跳转页面的回调函数
items_per_page: $ { requestScope.pageInfo.pageSize} , // 每页要显示的数据的数量
current_page: $ { requestScope.pageInfo.pageNum - 1} , // Pagination内部使用pageIndex来管理页码,pageIndex从0开始,pageNum从1开始,所以要减一
prev_text : "上一页" , // 上一页按钮上显示的文本
next_text : "下一页" // 下一页按钮上显示的文本
} ;
// 生成页码导航条
$( "#Pagination" ) .pagination ( totalRecord, properties) ;
}
// 回调函数的含义:声明出来以后不是自己调用,而是交给系统或框架调用
// 用户点击“上一页、下一页、1、2、3……”这样的页码时调用这个函数实现页面跳转
// pageIndex是Pagination传给我们的那个“从0开始”的页码
function pageSelectCallback(pageIndex, jQuery) {
// 根据pageIndex计算得到pageNum
var pageNum = pageIndex + 1;
// 跳转页面
window.location.href = "admin/get/page.html?pageNum=" +pageNum;
// 由于每一个页码按钮都是超链接,所以在这个函数最后取消超链接的默认行为
return false;
}
</script>
2.5、修复Pagination Bug
Bug
产生原因:请求页面 --> 绘制分页条 --> 调用回调函数 --> 页面跳转 --> 请求页面 --> 绘制分页条 --> 调用回调函数 --> 页面跳转 … 就这样陷入了陷入死循环
2.6、测试
3、关键词查询
3.1、修改表单
修改admin-page.jsp
中查询表单
表单提交URI
为admin/get/page.html
<input name="keyword"/>
:输入框名称需要与Handler
参数名称对应<button type="submit">
:submit
按钮用于提交表单
< form action = " admin/get/page.html" class = " form-inline" role = " form"
style =" float : left; " >
< div class = " form-group has-feedback" >
< div class = " input-group" >
< div class = " input-group-addon" > 查询条件</ div>
< input name = " keyword" class = " form-control has-success"
type = " text" placeholder = " 请输入查询条件" value = " ${param.keyword }" >
</ div>
</ div>
< button type = " submit" class = " btn btn-warning" >
< i class = " glyphicon glyphicon-search" > </ i> 查询
</ button>
</ form>
3.2、翻页带上关键词查询条件
由于搜索关键词之后,并没有进行重定向操作,所以都是同一次请求,直接从请求参数中取出搜索关键词即可
< script type= "text/javascript" >
$ ( function ( ) {
initPagination ( ) ;
} ) ;
function initPagination ( ) {
var totalRecord = ${ requestScope. pageInfo. total} ;
var properties = {
num_edge_entries: 3 ,
num_display_entries: 5 ,
callback: pageSelectCallback,
items_per_page: ${ requestScope. pageInfo. pageSize} ,
current_page: ${ requestScope. pageInfo. pageNum - 1 } ,
prev_text: "上一页" ,
next_text: "下一页"
} ;
$ ( "#Pagination" ) . pagination ( totalRecord, properties) ;
}
function pageSelectCallback ( pageIndex, jQuery) {
var pageNum = pageIndex + 1 ;
window. location. href = "admin/get/page.html?pageNum=" + pageNum+ "&keyword=${param.keyword}" ;
return false ;
}
< / script>
3.3、测试
4、单条删除
4.1、提交删除请求
在admin-page.jsp
页面,添加提交删除请求的a
标签,删除管理员时,除了要携带管理员Id
:id
,还需要附带当前页码:pageNum
,当前查询关键词:keyword
< a href = " admin/remove/${admin.id }/${requestScope.pageInfo.pageNum }/${param.keyword }.html"
class = " btn btn-danger btn-xs" >
< i class = " glyphicon glyphicon-remove" > </ i> </ a>
4.2、编写业务逻辑
4.2.1、Handler代码
在AdminHandler
中添加remove
方法,从路径变量中取出所需的参数即可
@RequestMapping ( "/admin/remove/{adminId}/{pageNum}/{keyword}.html" )
public String remove (
@PathVariable ( "adminId" ) Integer adminId,
@PathVariable ( "pageNum" ) Integer pageNum,
@PathVariable ( "keyword" ) String keyword
) {
adminService. remove ( adminId) ;
return "redirect:/admin/get/page.html?pageNum=" + pageNum+ "&keyword=" + keyword;
}
4.2.2、Service代码
在Service
接口中声明remove
方法,在Service
实现类中实现remove
方法
@Override
public void remove ( Integer adminId) {
adminMapper. deleteByPrimaryKey ( adminId) ;
}
4.3、莫名其妙的Bug
4.3.1、Bug描述
莫名其妙会执行删除管理员的操作,但是我并没有执行删除操作。。。
4.3.2、Bug排除
特么居然是因为FasterChrome
插件,只要你鼠标悬停有超链接的标签上,这个插件会预先发送请求给服务器,并接受服务器的请求,以缓存方式保存,等到你点击时,便会直接从缓存中取出数据,让你纵享丝滑~~~
恰好删除按钮并没有写JS
代码,只要鼠标悬停在删除按钮上,便会触发删除请求,我特么的,终于知道为什么t_admin
表中的数据莫名其妙地消失了。。。
4.3.3、解决办法
5、新增
5.1、思路
5.2、设置唯一约束
ALTER TABLE ` project_crowd` . ` t_admin` ADD UNIQUE INDEX ( ` login_acct` ) ;
5.3、提交新增请求
修改admin-page.jsp
页面,添加提交新增请求的a
标签
< a style =" float : right; " href = " admin/to/add/page.html"
class = " btn btn-primary" >
< i class = " glyphicon glyphicon-plus" > </ i> 新增</ a>
5.4、配置view-controller
由于点击a
标签超链接后直接转发页面,无需其他操作,所以我们直接配置view-controller
< mvc: view-controller
path = " /admin/to/add/page.html" view-name = " admin-add" />
5.5、准备表单页面
准备新增管理员表单页面admin-add.jsp
表单提交地址为admin/save.html
各个input
标签的name
属性值需要与java bean
属性对应
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
< html lang = " zh-CN" >
<%@include file="/WEB-INF/include-head.jsp"%>
< body>
<%@ include file="/WEB-INF/include-nav.jsp"%>
< div class = " container-fluid" >
< div class = " row" >
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
< div class = " col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< ol class = " breadcrumb" >
< li> < a href = " /admin/to/main/page.html" > 首页</ a> </ li>
< li> < a href = " /admin/get/page.html" > 数据列表</ a> </ li>
< li class = " active" > 新增</ li>
</ ol>
< div class = " panel panel-default" >
< div class = " panel-heading" >
表单数据
< div style =" float : right; cursor : pointer; " data-toggle = " modal"
data-target = " #myModal" >
< i class = " glyphicon glyphicon-question-sign" > </ i>
</ div>
</ div>
< div class = " panel-body" >
< form action = " admin/save.html" method = " post" role = " form" >
< p> ${requestScope.exception.message }</ p>
< div class = " form-group" >
< label for = " exampleInputPassword1" > 登录账号</ label>
< input
name = " loginAcct" type = " text" class = " form-control"
id = " exampleInputPassword1" placeholder = " 请输入登录账号" >
</ div>
< div class = " form-group" >
< label for = " exampleInputPassword1" > 登录密码</ label>
< input
name = " userPswd" type = " text" class = " form-control"
id = " exampleInputPassword1" placeholder = " 请输入登录密码" >
</ div>
< div class = " form-group" >
< label for = " exampleInputPassword1" > 用户昵称</ label>
< input
name = " userName" type = " text" class = " form-control"
id = " exampleInputPassword1" placeholder = " 请输入用户名称" >
</ div>
< div class = " form-group" >
< label for = " exampleInputEmail1" > 邮箱地址</ label>
< input type = " email"
name = " email" class = " form-control" id = " exampleInputEmail1"
placeholder = " 请输入邮箱地址" >
< p class = " help-block label label-warning" > 请输入合法的邮箱地址, 格式为:
xxxx@xxxx.com</ p>
</ div>
< button type = " submit" class = " btn btn-success" >
< i class = " glyphicon glyphicon-plus" > </ i> 新增
</ button>
< button type = " reset" class = " btn btn-danger" >
< i class = " glyphicon glyphicon-refresh" > </ i> 重置
</ button>
</ form>
</ div>
</ div>
</ div>
</ div>
</ div>
</ body>
</ html>
5.6、Handler代码
在Handler
中保存新增的管理员之后,重定向至分页页面
@RequestMapping ( "/admin/save.html" )
public String save ( Admin admin) {
adminService. saveAdmin ( admin) ;
return "redirect:/admin/get/page.html?pageNum=" + Integer. MAX_VALUE;
}
5.7、用户名重复异常
在util
工程下创建LoginAcctAlreadyInUseException
类,表示用户名重复异常
public class LoginAcctAlreadyInUseException extends RuntimeException {
private static final long serialVersionUID = 1 L;
public LoginAcctAlreadyInUseException ( ) {
super ( ) ;
}
public LoginAcctAlreadyInUseException ( String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super ( message, cause, enableSuppression, writableStackTrace) ;
}
public LoginAcctAlreadyInUseException ( String message, Throwable cause) {
super ( message, cause) ;
}
public LoginAcctAlreadyInUseException ( String message) {
super ( message) ;
}
public LoginAcctAlreadyInUseException ( Throwable cause) {
super ( cause) ;
}
}
5.8、Service代码
在Service
中实现上述Handler
中调用的方法
将管理员密码加密存储 设置管理员创建时间 如果login_acct
键重复,则抛出异常
private Logger logger = LoggerFactory. getLogger ( AdminServiceImpl. class ) ;
@Override
public void saveAdmin ( Admin admin) {
String userPswd = admin. getUserPswd ( ) ;
userPswd = CrowdUtil. md5 ( userPswd) ;
admin. setUserPswd ( userPswd) ;
Date date = new Date ( ) ;
SimpleDateFormat format = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" ) ;
String createTime = format. format ( date) ;
admin. setCreateTime ( createTime) ;
try {
adminMapper. insert ( admin) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
logger. info ( "异常全类名=" + e. getClass ( ) . getName ( ) ) ;
if ( e instanceof DuplicateKeyException ) {
throw new LoginAcctAlreadyInUseException ( CrowdConstant. MESSAGE_LOGIN_ACCT_ALREADY_IN_USE) ;
}
}
}
5.9、统一处理异常
在CrowdExceptionResolver
配置类中统一处理LoginAcctAlreadyInUseException
类型的异常
@ExceptionHandler ( value = LoginAcctAlreadyInUseException. class )
public ModelAndView resolveLoginAcctAlreadyInUseException (
LoginAcctAlreadyInUseException exception,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String viewName = "admin-add" ;
return commonResolve ( viewName, exception, request, response) ;
}
private ModelAndView commonResolve (
String viewName,
Exception exception,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
boolean judgeResult = CrowdUtil. judgeRequestType ( request) ;
if ( judgeResult) {
ResultEntity< Object> resultEntity = ResultEntity. failed ( exception. getMessage ( ) ) ;
Gson gson = new Gson ( ) ;
String json = gson. toJson ( resultEntity) ;
response. getWriter ( ) . write ( json) ;
return null;
}
ModelAndView modelAndView = new ModelAndView ( ) ;
modelAndView. addObject ( "exception" , exception) ;
modelAndView. setViewName ( viewName) ;
return modelAndView;
}
5.10、测试
6、更新
6.1、思路
6.2、提交更新请求
修改admin-page.jsp
页面,添加提交更新请求的a
标签
更新管理员信息需要管理员Id
更新完成后回到分页页面需要:当前页面pageNum
和搜索关键词keyword
< a href = " admin/to/edit/page.html?adminId=${admin.id }&pageNum=${requestScope.pageInfo.pageNum }&keyword=${param.keyword }"
class = " btn btn-primary btn-xs" >
< i class = " glyphicon glyphicon-pencil" > </ i> </ a>
6.3、查询管理员
6.3.1、Handler代码
在AdminHandler
中查询出Admin
信息,并转发至admin-edit.jsp
页面;由于是同一次请求,所以请求参数pageNum
和keyword
到更新Admin
的时候再取出来使用
@RequestMapping ( "/admin/to/edit/page.html" )
public String toEditPage (
@RequestParam ( "adminId" ) Integer adminId,
ModelMap modelMap
) {
Admin admin = adminService. getAdminById ( adminId) ;
modelMap. addAttribute ( "admin" , admin) ;
return "admin-edit" ;
}
6.3.2、Service代码
在Service
中实现上述Handler
中调用的方法
@Override
public Admin getAdminById ( Integer adminId) {
return adminMapper. selectByPrimaryKey ( adminId) ;
}
6.4、表单回显
添加admin-edit.jsp
页面,用于表单回显,表单提交地址为admin/update.html
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
< html lang = " zh-CN" >
<%@include file="/WEB-INF/include-head.jsp"%>
< body>
<%@ include file="/WEB-INF/include-nav.jsp"%>
< div class = " container-fluid" >
< div class = " row" >
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
< div class = " col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< ol class = " breadcrumb" >
< li> < a href = " /admin/to/main/page.html" > 首页</ a> </ li>
< li> < a href = " /admin/get/page.html" > 数据列表</ a> </ li>
< li class = " active" > 更新</ li>
</ ol>
< div class = " panel panel-default" >
< div class = " panel-heading" >
表单数据
< div style =" float : right; cursor : pointer; " data-toggle = " modal"
data-target = " #myModal" >
< i class = " glyphicon glyphicon-question-sign" > </ i>
</ div>
</ div>
< div class = " panel-body" >
< form action = " admin/update.html" method = " post" role = " form" >
< input type = " hidden" name = " id" value = " ${requestScope.admin.id }" />
< input type = " hidden" name = " pageNum" value = " ${param.pageNum }" />
< input type = " hidden" name = " keyword" value = " ${param.keyword }" />
< p> ${requestScope.exception.message }</ p>
< div class = " form-group" >
< label for = " exampleInputPassword1" > 登录账号</ label>
< input
name = " loginAcct"
value = " ${requestScope.admin.loginAcct }"
type = " text" class = " form-control"
id = " exampleInputPassword1" placeholder = " 请输入登录账号" >
</ div>
< div class = " form-group" >
< label for = " exampleInputPassword1" > 用户昵称</ label>
< input
name = " userName"
value = " ${requestScope.admin.userName }"
type = " text" class = " form-control"
id = " exampleInputPassword1" placeholder = " 请输入用户名称" >
</ div>
< div class = " form-group" >
< label for = " exampleInputEmail1" > 邮箱地址</ label>
< input type = " email"
name = " email"
value = " ${requestScope.admin.email }" class = " form-control" id = " exampleInputEmail1"
placeholder = " 请输入邮箱地址" >
< p class = " help-block label label-warning" > 请输入合法的邮箱地址, 格式为:
xxxx@xxxx.com</ p>
</ div>
< button type = " submit" class = " btn btn-success" >
< i class = " glyphicon glyphicon-edit" > </ i> 更新
</ button>
< button type = " reset" class = " btn btn-danger" >
< i class = " glyphicon glyphicon-refresh" > </ i> 重置
</ button>
</ form>
</ div>
</ div>
</ div>
</ div>
</ div>
</ body>
</ html>
6.5、Handler代码:更新管理员
6.5.1、Handler代码
在AdminHandler
中更新Admin
管理员的信息,并重定向至分页页面
@RequestMapping ( "/admin/update.html" )
public String update ( Admin admin, @RequestParam ( "pageNum" ) Integer pageNum, @RequestParam ( "keyword" ) String keyword) {
adminService. update ( admin) ;
return "redirect:/admin/get/page.html?pageNum=" + pageNum+ "&keyword=" + keyword;
}
6.5.2、Service代码
在Service
中保存Admin
信息,并且捕获唯一键约束异常
@Override
public void update ( Admin admin) {
try {
adminMapper. updateByPrimaryKeySelective ( admin) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
logger. info ( "异常全类名=" + e. getClass ( ) . getName ( ) ) ;
if ( e instanceof DuplicateKeyException ) {
throw new LoginAcctAlreadyInUseForUpdateException ( CrowdConstant. MESSAGE_LOGIN_ACCT_ALREADY_IN_USE) ;
}
}
}
6.6、异常处理
6.6.1、创建异常类
在util
工程添加LoginAcctAlreadyInUseForUpdateException
类,该类表示更新Admin
时,其login_acct
字段不唯一,引发的异常
public class LoginAcctAlreadyInUseForUpdateException extends RuntimeException {
private static final long serialVersionUID = 1 L;
public LoginAcctAlreadyInUseForUpdateException ( ) {
super ( ) ;
}
public LoginAcctAlreadyInUseForUpdateException ( String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super ( message, cause, enableSuppression, writableStackTrace) ;
}
public LoginAcctAlreadyInUseForUpdateException ( String message, Throwable cause) {
super ( message, cause) ;
}
public LoginAcctAlreadyInUseForUpdateException ( String message) {
super ( message) ;
}
public LoginAcctAlreadyInUseForUpdateException ( Throwable cause) {
super ( cause) ;
}
}
6.6.2、处理异常
在CrowdExceptionResolver
配置类中统一处理LoginAcctAlreadyInUseForUpdateException
类型的异常
@ExceptionHandler ( value = LoginAcctAlreadyInUseForUpdateException. class )
public ModelAndView resolveLoginAcctAlreadyInUseForUpdateException (
LoginAcctAlreadyInUseForUpdateException exception,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String viewName = "system-error" ;
return commonResolve ( viewName, exception, request, response) ;
}
6.7、测试
7、Ajax加餐
7.1、异步Ajax
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
< html lang = " zh-CN" >
<%@include file="/WEB-INF/include-head.jsp"%>
< script type = " text/javascript" >
$ ( function ( ) {
$ ( "#asyncBtn" ) . click ( function ( ) {
console. log ( "ajax函数之前" ) ;
$. ajax ( {
"url" : "test/ajax/async.html" ,
"type" : "post" ,
"dataType" : "text" ,
"async" : true ,
"success" : function ( response) {
console. log ( "ajax函数内部的success函数" + response) ;
}
} ) ;
console. log ( "ajax函数之后" ) ;
} ) ;
} ) ;
</ script>
< body>
<%@ include file="/WEB-INF/include-nav.jsp"%>
< div class = " container-fluid" >
< div class = " row" >
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
< div class = " col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< button id = " asyncBtn" > 发送Ajax请求</ button>
</ div>
</ div>
</ div>
</ body>
</ html>
@ResponseBody
@RequestMapping ( "/test/ajax/async.html" )
public String testAsync ( ) throws InterruptedException {
Thread. sleep ( 5000 ) ;
return "success" ;
}
7.2、同步Ajax
将Ajax
请求修改为同步:"async" : false
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
< html lang = " zh-CN" >
<%@include file="/WEB-INF/include-head.jsp"%>
< script type = " text/javascript" >
$ ( function ( ) {
$ ( "#asyncBtn" ) . click ( function ( ) {
console. log ( "ajax函数之前" ) ;
$. ajax ( {
"url" : "test/ajax/async.html" ,
"type" : "post" ,
"dataType" : "text" ,
"async" : false ,
"success" : function ( response) {
console. log ( "ajax函数内部的success函数" + response) ;
}
} ) ;
console. log ( "ajax函数之后" ) ;
} ) ;
} ) ;
</ script>
< body>
<%@ include file="/WEB-INF/include-nav.jsp"%>
< div class = " container-fluid" >
< div class = " row" >
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
< div class = " col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main" >
< button id = " asyncBtn" > 发送Ajax请求</ button>
</ div>
</ div>
</ div>
</ body>
</ html>