【尚筹网】五、管理员维护

news2024/12/27 3:03:41

【尚筹网】五、管理员维护

  • 任务清单
  • 分页管理管理员信息
    • 目标
    • 思路
    • 代码
        • 引入 PageHelper
        • AdminMapper 中编写 SQL 语句
        • AdminMapper 接口生成方法
        • AdminService
        • AdminHandler
        • 页面显示主体
        • 在页面上使用 `Pagination` 实现导航条
  • 关键词查询
    • 页面上调整表单
    • 在翻页时保持关键词查询条件
  • 单条删除
    • 目标
    • 思路
    • 代码
      • 调整删除的按钮
      • AdminHandler.remove()
      • AdminService.remove()
  • 新增
    • 目标
    • 思路
    • 在 `t_admin` 表中给账号添加唯一约束
    • 调整修改按钮
    • 配置 `view-controller`
    • 准备表单页面
    • handler 方法
    • Service 方法
    • 处理唯一约束
      • 创建自定义异常类
      • 在异常处理器类添加方法
      • 修改 Service 方法
  • 更新
    • 目标
    • 思路
    • 回显表单
      • 调整铅笔按钮
      • Handler 方法
      • 准备页面
      • Service 方法
    • 执行更新
      • Handler 方法
      • Service 方法
      • 创建自定义异常
      • 在异常处理器类添加方法
      • 修改 Service 方法

任务清单

  • 分页显示 Admin 数据
    • 不带关键词分页
    • 带关键词分页
  • 新增 Admin
  • 更新 Admin
  • 单条删除 Admin

分页管理管理员信息

目标

将数据库中的 Admin 数据在页面上以分页形式显示。在后端将“带关键词”和“不带关键词”的分页合并为同一套代码

思路

image-20241126223330409

代码

引入 PageHelper
  • 确认是否加入了依赖

    <!-- MyBatis 分页插件 -->
    <dependency>
    	<groupId>com.github.pagehelper</groupId>
    	<artifactId>pagehelper</artifactId>
    </dependency>
    
  • SqlSessionFactoryBean 配置 MyBatis 插件

    image-20241126223941497

<!-- 配置 SqlSessionFactoryBean 整合 MyBatis -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean" >
    <!-- 指定 MyBatis 全局配置文件位置 -->
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
    <!-- 指定 Mapper.xml 配置文件位置 -->
    <property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml" />
    <!-- 配置数据源  -->
    <property name="dataSource" ref="dataSource" />
    <!-- 配置插件 -->
    <property name="plugins" >
       <array>
          <!-- 配置 PageHelper -->
          <bean class="com.github.pagehelper.PageHelper">
             <property name="properties">
                <props>
                   <!-- 配置数据库方言,告诉 PageHelper 当前使用的数据库 -->
                   <prop key="dialect">mysql</prop>
                   <!-- 配置页码的合理化修正,在1~总页数之间修正页码 -->
                   <prop key="reasonable">true</prop>
                </props>
             </property>
          </bean>
       </array>
    </property>
</bean>
AdminMapper 中编写 SQL 语句

image-20241126224731297

<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>
AdminMapper 接口生成方法

image-20241126225604859

List<Admin> selectAdminByKeyword(String keyword);
AdminService

image-20241126230359513

@Override
public PageInfo<Admin> getPageInfo(String keyword, Integer pageNum, Integer pageSize) {
    // 1.调用 PageHelper 的静态方法开启分页功能
    // 这里充分体现了 PageHelper 的“非侵入式”设计:原本要做的查询不必有任何修改
    PageHelper.startPage(pageNum, pageSize);
    // 2.执行查询
    List<Admin> list = adminMapper.selectAdminByKeyword(keyword);
    // 3.封装为 PageInfo 对象返回
    return new PageInfo<>(list);
}
AdminHandler

image-20241126230824624

@RequestMapping("/admin/get/page.html")
public String getPageInfo(
       // 使用 @RequestParam 注解的 defaultValue 属性,指定默认值,在请求中没有携带对应参数时使用默认值
       // keyword 默认值使用空字符串,和 SQL 语句配合实现两种情况的适配
       @RequestParam(value = "keyword", defaultValue = "") String keyword,
       // pageNum 默认值使用 1
       @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
       // pageSize 默认值使用 5
       @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
       ModelMap modelMap
){
    // 调用 Service 方法获取 PageInfo 对象
    PageInfo<Admin> pageInfo = adminService.getPageInfo(keyword, pageNum, pageSize);
    // 将 PageInfo 对象存入模型
    modelMap.addAttribute(CrowdConstant.ATTR_NAME_PAGE_INFO, pageInfo);
    return "admin-page";
}
页面显示主体

image-20241126234009493

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
    <%@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>
在页面上使用 Pagination 实现导航条

image-20241129223030558

在有需要的页面进行引入

<%@include file="/WEB-INF/include-head.jsp" %>
<link rel="stylesheet" href="css/pagination.css" />
<script type="text/javascript" src="jquery/jquery.pagination.js"></script>
  • HTML代码准备

    使用 Pagination 要求的 div 标签替换原有的页码部分

    <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>
    
    <tfoot>
        <tr>
           <td colspan="6" align="center">
              <div id="Pagination" class="pagination"></div>
           </td>
        </tr>
    </tfoot>
    
  • JQuery 代码

    <script type="text/javascript">
        $(function () {
           // 对页面导航条进行初始化
           initPagination();
        });
    
        // 初始化分页导航条
        function initPagination(){
           // 获取总记录数
           var totalRecord = ${requestScope.pageInfo.total};
           // 声明一个 JSON 对象存储分页导航条需要用到的数据
           var properties = {
              // 边缘页数
              num_edge_entries: 3,
              // 主体页数
              num_display_entries: 5,
              // 指定用户点击翻页的按钮时跳转页面的回调函数
              callback: pageSelectCallback,
              // 每页要显示的记录数
              items_per_page: ${requestScope.pageInfo.pageSize},
              // 当前页码, Pagination 内部使用 pageIndex 来管理页码,pageIndex 从0开始,pageNum 从1开始,所以 pageNum - 1
              current_page: ${requestScope.pageInfo.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>
    
  • 修改 Pagination 源码

    image-20241130221230838

    image-20241130221334944

    // 所有初始化完成,绘制链接
    drawLinks();
    // 回调函数
    // opts.callback(current_page, this);
    

关键词查询

页面上调整表单

image-20241126234009493

<form class="form-inline" role="form" style="float:left;" action="admin/get/page.html" method="post">
    <div class="form-group has-feedback">
       <div class="input-group">
          <div class="input-group-addon">查询条件</div>
          <label>
             <input name="keyword" class="form-control has-success" type="text"
                    placeholder="请输入查询条件">
          </label>
       </div>
    </div>
    <button type="submit" class="btn btn-warning"><i class="glyphicon glyphicon-search"></i>
       查询
    </button>
</form>

在翻页时保持关键词查询条件

image-20241130222510209

window.location.href = "admin/get/page.html?pageNum=" + pageNum + "&keyword=${param.keyword}";

单条删除

目标

在页面上点击单条删除按钮 ,实现 Admin 对应记录的删除

思路

image-20241130223233359

代码

调整删除的按钮

image-20241126234009493

<%-- <button type="button" class="btn btn-danger btn-xs">
<i class=" glyphicon glyphicon-remove"></i>
</button> --%>
<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>

AdminHandler.remove()

image-20241130224244685

@RequestMapping("admin/remove/{adminId}/{pageNum}/{keyword}.html")
public String remove(@PathVariable("adminId") Integer adminId,
                     @PathVariable("pageNum") Integer pageNum,
                     @PathVariable("keyword") String keyword){
    // 调用 Service 方法执行删除
    adminService.remove(adminId);
    // 页面跳转:回到分页页面

    // 尝试方案1:直接转发到 admin-page.jsp 会无法显示分页数据
    // return "admin-page";
    // 尝试方案2:转发到 /admin/get/page.html 页面,一旦刷新页面会重复执行删除浪费性能
    // return "forward:/admin/get/page.html";
    // 尝试方案3:重定向到 /admin/get/page.html 页面
    // 同时为了保持原本所在的页面和查询关键词再附加 pageNum 和 keyword 两个请求参数
    return "redirect:/admin/get/page.html?pageNum=" + pageNum + "&keyword=" + keyword;
}

AdminService.remove()

image-20241126230359513

@Override
public void remove(Integer adminId) {
    adminMapper.deleteByPrimaryKey(adminId);   
}

新增

目标

将表单提交的 Admin 对象保存到数据库中

要求:

  1. loginAcct 不能重复
  2. 密码加密

思路

image-20241201211602466

t_admin 表中给账号添加唯一约束

alter table `project_crowd`.`t_admin` add unique index (`login_acct`);

调整修改按钮

image-20241201212422734

<%-- <button type="button" class="btn btn-primary" style="float:right;"
        onclick="window.location.href='add.html'"><i class="glyphicon glyphicon-plus"></i>
    新增
</button> --%>
<a href="admin/to/add/page.html" class="btn btn-primary" style="float:right;"
        onclick="window.location.href='add.html'"><i class="glyphicon glyphicon-plus"></i>
    新增
</a>

配置 view-controller

image-20241201212902073

<mvc:view-controller path="/admin/to/add/page.html" view-name="admin-add" />

准备表单页面

image-20241201213347508

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
	<%@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="inputLoginAcct">登录账号</label>
									<input type="text" class="form-control" id="inputLoginAcct" name="loginAcct"
									       placeholder="请输入登录账号">
								</div>
								<div class="form-group">
									<label for="inputPassword">登录密码</label>
									<input type="text" class="form-control" id="inputPassword" name="userPswd"
									       placeholder="请输入登录密码">
								</div>
								<div class="form-group">
									<label for="inputUserName">用户昵称</label>
									<input type="text" class="form-control" id="inputUserName" name="userName"
									       placeholder="请输入用户昵称">
								</div>
								<div class="form-group">
									<label for="inputEmail">邮箱地址</label>
									<input type="email" class="form-control" id="inputEmail" name="email"
									       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>

handler 方法

image-20241130224244685

@RequestMapping("admin/save.html")
public String save(Admin admin){
    adminService.saveAdmin(admin);
    return "redirect:/admin/get/page.html?pageNum=" + Integer.MAX_VALUE;
}

Service 方法

image-20241126230359513

public void saveAdmin(Admin admin) {
    // 1.密码加密
    String userPswd = admin.getUserPswd();
    userPswd = CrowdUtil.md5(userPswd);
    admin.setUserPswd(userPswd);
    // 2.生成创建时间
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String createTime = format.format(date);
    admin.setCreateTime(createTime);
    // 3.执行插入
    adminMapper.insert(admin);
}

处理唯一约束

创建自定义异常类

image-20241201221839314

package com.atguigu.crowd.exception;

/**
 * Copyright (C) 2024 - 2024 Jasonakeke, Inc. All Rights Reserved
 *
 * @Desc : 保存或者更新 Admin 时,如果检测到登录账号重复则抛出这个异常
 * @Time : 2024/12/1 22:05
 * @Author : Code_By_Jasonakeke
 * @Email : 2284037977@qq.com
 * @Class : LoginAcctAlreadyInUseException
 * @IDE : IntelliJ IDEA
 */
public class LoginAcctAlreadyInUseException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public LoginAcctAlreadyInUseException(String message) {
       super(message);
    }

    public LoginAcctAlreadyInUseException(String message, Throwable cause) {
       super(message, cause);
    }

    public LoginAcctAlreadyInUseException(Throwable cause) {
       super(cause);
    }

    public LoginAcctAlreadyInUseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
       super(message, cause, enableSuppression, writableStackTrace);
    }

    public LoginAcctAlreadyInUseException() {
    }
}

在异常处理器类添加方法

image-20241201222043272

@ExceptionHandler(LoginAcctAlreadyInUseException.class)
public ModelAndView resolveLoginAcctAlreadyInUseException(LoginAcctAlreadyInUseException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
    String viewName = "admin-add";
    return commonResolve(viewName, exception, request, response);
}

修改 Service 方法

public void saveAdmin(Admin admin) {
    // 1.密码加密
    String userPswd = admin.getUserPswd();
    userPswd = CrowdUtil.md5(userPswd);
    admin.setUserPswd(userPswd);
    // 2.生成创建时间
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String createTime = format.format(date);
    admin.setCreateTime(createTime);
    // 3.执行插入
    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);
       }
    }
}

更新

目标

修改现有 Admin 的数据,不修改密码和创建时间

思路

image-20241201222639454

回显表单

调整铅笔按钮

image-20241126234009493

<%-- <button type="button" class="btn btn-primary btn-xs">
<i class=" glyphicon glyphicon-pencil"></i>
</button> --%>
<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>

Handler 方法

image-20241201223812557

@RequestMapping("admin/to/edit/page.html")
public String toEditPage(
       @RequestParam("adminId") Integer adminId,
       ModelMap modelMap
){
    // 1.根据 adminId 查询 Admin 对象
    Admin admin = adminService.getAdminById(adminId);
    // 2.将 Admin 对象存入模型
    modelMap.addAttribute("admin", admin);
    return "admin-edit";
}

准备页面

image-20241201224622773

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
	<%@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="inputLoginAcct">登录账号</label>
									<input type="text" class="form-control" id="inputLoginAcct" name="loginAcct" value="${requestScope.admin.loginAcct}"
									       placeholder="请输入登录账号">
								</div>
								<div class="form-group">
									<label for="inputUserName">用户昵称</label>
									<input type="text" class="form-control" id="inputUserName" name="userName" value="${requestScope.admin.userName}"
									       placeholder="请输入用户昵称">
								</div>
								<div class="form-group">
									<label for="inputEmail">邮箱地址</label>
									<input type="email" class="form-control" id="inputEmail" name="email" value="${requestScope.admin.email}"
									       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>

Service 方法

@Override
public Admin getAdminById(Integer adminId) {
    return adminMapper.selectByPrimaryKey(adminId);
}

执行更新

Handler 方法

]image-20241201223812557

@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;
}

Service 方法

image-20241126230359513

@Override
public void update(Admin admin) {
    try {
       // Selective:表示有选择的更新,对于 null 值的字段不更新
       adminMapper.updateByPrimaryKeySelective(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);
       }
    }
}

创建自定义异常

image-20241201231834624

package com.atguigu.crowd.exception;

/**
 * Copyright (C) 2024 - 2024 Jasonakeke, Inc. All Rights Reserved
 *
 * @Desc :
 * @Time : 2024/12/1 23:12
 * @Author : Code_By_Jasonakeke
 * @Email : 2284037977@qq.com
 * @Class : LoginAcctAlreadyInUseForUpdateException
 * @IDE : IntelliJ IDEA
 */
public class LoginAcctAlreadyInUseForUpdateException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public LoginAcctAlreadyInUseForUpdateException() {
    }

    public LoginAcctAlreadyInUseForUpdateException(String message) {
       super(message);
    }

    public LoginAcctAlreadyInUseForUpdateException(String message, Throwable cause) {
       super(message, cause);
    }

    public LoginAcctAlreadyInUseForUpdateException(Throwable cause) {
       super(cause);
    }

    public LoginAcctAlreadyInUseForUpdateException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
       super(message, cause, enableSuppression, writableStackTrace);
    }
}

在异常处理器类添加方法

image-20241201222043272

@ExceptionHandler(LoginAcctAlreadyInUseForUpdateException.class)
public ModelAndView resolveLoginAcctAlreadyInUseForUpdateException(LoginAcctAlreadyInUseForUpdateException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
    String viewName = "system-error";
    return commonResolve(viewName, exception, request, response);
}

修改 Service 方法

@Override
public void update(Admin admin) {
    try {
       // Selective:表示有选择的更新,对于 null 值的字段不更新
       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);
       }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2251848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 启动失败问题分析与解决方案:`mysqld.service failed to run ‘start-pre‘ task`

目录 前言1. 问题背景2. 错误分析2.1 错误信息详解2.2 可能原因 3. 问题排查与解决方案3.1 检查 MySQL 错误日志3.2 验证 MySQL 配置文件3.3 检查文件和目录权限3.4 手动启动 MySQL 服务3.5 修复 systemd 配置文件3.6 验证依赖环境 4. 进一步优化与自动化处理结语 前言 在日常…

Apache storm UI如何更换默认8080端口

在搭建Apache storm环境的时候&#xff0c;遇到Apache storm UI默认端口是8080&#xff0c;但是这个端口会被其他java程序占用&#xff0c;导致Apache storm UI服务无法启动。报错Exception in thread “main” java.lang.RuntimeException: java.io.IOException: Failed to bi…

FPGA实现串口升级及MultiBoot(十)串口升级SPI FLASH实现

本文目录索引 工程架构example9工程设计Vivado设计Vitis设计example9工程验证1、读取FLASH ID2、擦除整个FLASH3、Blank-Check4、烧写Golden区位流5、读取FLASH内容6、烧写MultiBoot区位流(升级位流)7、MultiBoot区位流(升级位流)启动example10工程设计Vivado设计Vitis设计exam…

图解人工智能:从规则到深度学习的全景解析

&#x1f31f;作者简介&#xff1a;热爱数据分析&#xff0c;学习Python、Stata、SPSS等统计语言的小高同学~&#x1f34a;个人主页&#xff1a;小高要坚强的博客&#x1f353;当前专栏&#xff1a;Python之机器学习&#x1f34e;本文内容&#xff1a;图解人工智能&#xff1a;…

Binder架构

一、架构 如上图&#xff0c;binder 分为用户层和驱动层两部分&#xff0c;用户层有客户端&#xff08;Client&#xff09;、服务端&#xff08;Server&#xff09;、服务管理&#xff08;ServiceManager&#xff09;。 从用户空间的角度&#xff0c;使用步骤如下&#xff08;…

基于springboot中小型制造企业质量管理系统源码和论文

信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古以来的…

Flutter 权限申请

这篇文章是基于permission_handler 10.2.0版本写的 前言 在App开发过程中我们经常要用到各种权限&#xff0c;我是用的是permission_handler包来实现权限控制的。 pub地址&#xff1a;https://pub.dev/packages/permission_handler permission_handler 权限列表 变量 Androi…

MATLAB期末复习笔记(下)

五、数据和函数的可视化 1.MATLAB的可视化对象 图形对象是 MATLAB用来创建可视化数据的组件。每个对象都有一个名为句柄 的唯一标识符。使用该句柄&#xff0c;您可以通过设置对象 属性 来操作现有图形对象的特征 ROOT: &#xff1a;即电脑屏幕 Figure &#xff1a;图窗…

web安全从0到1:burp-suite3

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

深度学习:梯度下降法

损失函数 L&#xff1a;衡量单一训练样例的效果。 成本函数 J&#xff1a;用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b &#xff1f; 成本函数J是参数w和b的函数&#xff0c;它被定义为平均值&#xff1b; 损失函数L可以衡量你的算法效果&a…

Linux:文件系统inode

早期&#xff0c;存储文件的设备是磁盘&#xff08;当下的市场几乎都是SSD&#xff09;&#xff0c;但大家习惯的把它们都称为磁盘&#xff0c;磁盘是用来表示区分内存的存储设备。而在操作系统看来&#xff0c;这个存储设备的结构就是一个线性结构&#xff0c;这一点很重要。 …

94.【C语言】解析预处理(2)

目录 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 运行结果 分析 "副作用"的解释 2.宏替换规则 解释 3.宏和函数的对比 附一张对比表 承接93.【C语言】解析预处理(1)文章 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 #define MAX(a, b) (…

Linux学习笔记12 systemd的其他命令

前文已经介绍了systemd在系统初始化中起到的作用和服务的管理和配置。这里补充一下systemd的其他工具和系统进程的管理 前文 Linux学习笔记10 系统启动初始化&#xff0c;服务和进程管理&#xff08;上&#xff09;-CSDN博客 Linux学习笔记11 系统启动初始化&#xff0c;服务…

vue3+ts+uniapp微信小程序顶部导航栏

这是colorui改的&#xff0c;不用就不用看啦 color-ui(https://docs.xzeu.com/#/) 新建component文件夹创建topNavigation.vue <template><view><view class"cu-custom" :style"height: CustomBar px"><view class"cu-bar…

ubuntu20.04更换安装高版本CUDA以及多个CUDA版本管理

Ubuntu 20.04下多版本CUDA的安装与切换 CUDA安装配置环境变量软连接附上参考博客CUDA安装 cuda官方下载地址 因为我需要安装的是11.1版本的,所以这里按着11.1举例安装 安装命令如下: wget https://developer.download.nvidia.com/compute/cuda/11.1.0/local_installers/cu…

C语言——库函数

常用的函数 https://cplusplus.com/reference/ 没事儿多看看 1 数学函数 #include <math.h> #include <stdio.h> int main() {printf("%lf\n", sqrt(4));//开平方根——>double类型printf("%lf\n", pow(2, 10));//求几次方的——>do…

树莓派远程连接方法

1、树莓派端 在树莓派终端&#xff08;Ctrl键alt键T键&#xff09;输入&#xff1a; ipconfig 查看树莓派的IP&#xff0c;记住这个IP号&#xff0c;都是192.168开头的 注意&#xff0c;这里远程连接需要树莓派和电脑在同一网络之下才可以 2、电脑端 我们在电脑上面下载 M…

qt QProxyStyle详解

1、概述 QProxyStyle是Qt框架中QStyle类的一个子类&#xff0c;它提供了一种代理机制&#xff0c;允许开发者在不直接修改现有样式&#xff08;QStyle&#xff09;实现的情况下&#xff0c;对样式行为进行定制或扩展。通过继承QProxyStyle&#xff0c;开发者可以重写其虚方法&…

TCP三次握手与四次挥手(TCP重传机制,2MSL)超详细!!!计算机网络

本篇是关于3次握手和四次挥手的详细解释~ 如果对你有帮助&#xff0c;请点个免费的赞吧&#xff0c;谢谢汪。&#xff08;点个关注也可以&#xff01;&#xff09; 如果以下内容需要补充和修改&#xff0c;请大家在评论区多多交流~。 目录 1. TCP头部&#xff1a; 2. 三次握手…

智能化业务校验框架:动态设计与应用实践

目录 一、业务背景 二、配置内容展示 三、商品动态配置内容展示 &#xff08;一&#xff09;商品spu校验信息数据 &#xff08;二&#xff09;商品sku校验信息数据 &#xff08;三&#xff09;组包商品校验信息数据 &#xff08;四&#xff09;商品数据校验数据持有者 &…