我是靠谱客的博主 冷静发箍,最近开发中收集的这篇文章主要介绍csmall-passport(Day15)1. 显示角色列表2. 关于客户端提交数组格式的数据3. 调整:添加管理员时关联角色4. 修复:增加管理员时,检查角色id是否存在4. 修复:删除管理员时,需要删除关联数据作业,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 显示角色列表

当【添加管理员】时,必须在操作界面上提供一个可以选择【角色】的控件,且添加时必须确定某些角色,从而,新添加的管理员才会因为选择的角色而关联到某些权限,管理员才会具有某些操作权限!

关于选择【角色】,需要将当前系统中的【角色列表】显示在操作界面上!

关于Mapper层(数据访问层 / DAO(Data Access Object)层 / 持久层)

需要执行的SQL语句大致是:

SELECT id, name, description, sort FROM ams_role ORDER BY sort DESC, id

在根包下创建pojo.vo.RoleListItemVO类:

package cn.tedu.csmall.passport.pojo.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class RoleListItemVO implements Serializable {
private Long id;
private String name;
private String description;
private Integer sort;
}

在根包下创建mapper.RoleMapper接口,并添加抽象方法:

package cn.tedu.csmall.passport.mapper;
import cn.tedu.csmall.passport.pojo.vo.RoleListItemVO;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface RoleMapper {
List<RoleListItemVO> list();
}

src/main/resources下的mapper文件夹中粘贴得到RoleMapper.xml,并在此文件中配置以上抽象方法映射的SQL语句:

<?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="cn.tedu.csmall.passport.mapper.RoleMapper">
<select id="list" resultMap="ListResultMap">
SELECT
<include refid="ListQueryFields" />
FROM
ams_role
ORDER BY
sort DESC, id
</select>
<sql id="ListQueryFields">
<if test="true">
id, name, description, sort
</if>
</sql>
<resultMap id="ListResultMap" type="cn.tedu.csmall.passport.pojo.vo.RoleListItemVO">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="description" property="description" />
<result column="sort" property="sort" />
</resultMap>
</mapper>

src/test/java下的根包下创建mapper.RoleMapperTests测试类,对以上方法进行测试:

package cn.tedu.csmall.passport.mapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@Slf4j
@SpringBootTest
public class RoleMapperTests {
@Autowired
RoleMapper mapper;
@Test
void testList() {
List<?> list = mapper.list();
log.debug("查询列表完成,结果集的数量={}", list.size());
for (Object item : list) {
log.debug("{}", item);
}
}
}

关于Service层(业务逻辑层 / 业务层)

在根包下创建service.IRoleService接口,并在接口中添加抽象方法:

package cn.tedu.csmall.passport.service;
import cn.tedu.csmall.passport.pojo.vo.RoleListItemVO;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Transactional
public interface IRoleService {
List<RoleListItemVO> list();
}

在根包下创建service.impl.RoleServiceImpl类,实现以上接口,并实现抽象方法:

package cn.tedu.csmall.passport.service.impl;
import cn.tedu.csmall.passport.mapper.RoleMapper;
import cn.tedu.csmall.passport.pojo.vo.RoleListItemVO;
import cn.tedu.csmall.passport.service.IRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class RoleServiceImpl implements IRoleService {
@Autowired
private RoleMapper roleMapper;
public RoleServiceImpl() {
log.debug("创建业务对象:RoleServiceImpl");
}
@Override
public List<RoleListItemVO> list() {
log.debug("开始处理【查询角色列表】的业务");
return roleMapper.list();
}
}

src/test/java下的根包下创建service.RoleServiceTests测试类,对以上方法进行测试:

package cn.tedu.csmall.passport.service;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@Slf4j
@SpringBootTest
public class RoleServiceTests {
@Autowired
IRoleService service;
@Test
void testList() {
List<?> list = service.list();
log.debug("查询列表完成,结果集的数量={}", list.size());
for (Object item : list) {
log.debug("{}", item);
}
}
}

关于Controller层(控制器层)

在根包下创建RoleController,并处理请求:

package cn.tedu.csmall.passport.controller;
import cn.tedu.csmall.passport.pojo.vo.RoleListItemVO;
import cn.tedu.csmall.passport.service.IRoleService;
import cn.tedu.csmall.passport.web.JsonResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/roles")
@Api(tags = "02. 角色管理模块")
public class RoleController {
@Autowired
private IRoleService roleService;
public RoleController() {
log.info("创建控制器:RoleController");
}
@GetMapping("")
@ApiOperation("查询角色列表")
@ApiOperationSupport(order = 410)
public JsonResult<List<RoleListItemVO>> list() {
log.debug("开始处理【查询角色列表】的请求");
List<RoleListItemVO> list = roleService.list();
return JsonResult.ok(list);
}
}

完成后,启动项目,可以通过Knife4j的调试功能进行测试,注意:需要携带有效的JWT!

另外,如果响应结果时,不希望包含为null的属性,可以在application.properties中补充配置:

# 响应结果中,不显示为null的属性
spring.jackson.default-property-inclusion=non_null

2. 关于客户端提交数组格式的数据

在使用qs将对象转换成FormData格式的字符串时,如果原对象中有数组,默认情况下,数组数据会被转换成如下格式:

roleIds%5B0%5D=1&roleIds%5B1%5D=2

以上代码中,%5B表示[%5D表示]

可以在使用qs时进行配置,以设置数组数据的格式,例如:

let formData = this.qs.stringify(this.ruleForm, {'arrayFormat': 'repeat'});

arrayFormat属性的值为repeat时,FormData格式为:

roleIds=1&roleIds=2&roleIds=3

arrayFormat属性的值为indices时,FormData格式为:

roleIds%5B0%5D=1&roleIds%5B1%5D=2

arrayFormat属性的值为brackets时,FormData格式为:

roleIds%5B%5D=1&roleIds%5B%5D=2

其实,无论使用以上哪种方式,Spring MVC框架都可以正常接收到数组值!

3. 调整:添加管理员时关联角色

关于Mapper层

在服务器端,添加管理员时,需要添加管理员与角色的关联,否则,管理员没有关联角色,也就没有权限了!

需要执行的SQL语句大致是(每个管理员可以关联多个角色):

INSERT INTO ams_admin_role (admin_id, role_id) VALUES (?,?), (?,?), ... (?,?);

在根包下创建pojo.entity.AdminRole实体类:

package cn.tedu.csmall.passport.pojo.entity;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class AdminRole implements Serializable {
private Long id;
private Long adminId;
private Long roleId;
private LocalDateTime gmtCreate;
private LocalDateTime gmtModified;
}

在根包下创建mapper.AdminRoleMapper接口,并添加抽象方法:

package cn.tedu.csmall.passport.mapper;
import cn.tedu.csmall.passport.pojo.entity.AdminRole;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface AdminRoleMapper {
int insertBatch(List<AdminRole> adminRoleList);
}

src/main/resources下的mapper文件夹中粘贴得到AdminRoleMapper.xml文件,并配置以上抽象方法映射的SQL语句:

<!-- int insertBatch(List<AdminRole> adminRoleList); -->
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="id">
INSERT INTO ams_admin_role (
admin_id, role_id, gmt_create, gmt_modified
) VALUES
<foreach collection="list" item="adminRole" separator=",">
(#{adminRole.adminId}, #{adminRole.roleId},
#{adminRole.gmtCreate}, #{adminRole.gmtModified})
</foreach>
</insert>

完成后,在src/test/java下的根包下创建mapper.AdminRoleMapperTests测试类,对以上功能进行测试:

package cn.tedu.csmall.passport.mapper;
import cn.tedu.csmall.passport.pojo.entity.AdminRole;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@SpringBootTest
public class AdminRoleMapperTests {
@Autowired
AdminRoleMapper mapper;
@Test
void testInsertBatch() {
LocalDateTime now = LocalDateTime.now();
List<AdminRole> adminRoleList = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
AdminRole adminRole = new AdminRole();
adminRole.setAdminId(5L);
adminRole.setRoleId(i + 0L);
adminRole.setGmtCreate(now);
adminRole.setGmtModified(now);
adminRoleList.add(adminRole);
}
int rows = mapper.insertBatch(adminRoleList);
log.debug("批量插入管理员与角色的关联关系数据成功,受影响的行数={}", rows);
}
}

关于Service层

由于此前已经实现了“增加管理员”的业务,只是尚未实现“插入管理员与角色的关联关系”,所以,只需要在原有代码基础上调整即可,并不需要创建新的接口、实现类!

原有代码中,关于“增加管理员”的业务方法的声明是:

void addNew(AdminAddNewDTO adminAddNewDTO);

以上方法中,参数AdminAddNewDTO中并不包含若干个角色id,所以,需要先补充声明此属性:

@Data
public class AdminAddNewDTO implements Serializable {
// 省略原有代码,以下是新增的属性
/**
* 管理员的角色
*/
private Long[] roleIds;
}

然后,在AdminServiceImpl中,先自动装配AdminRoleMapper对象:

@Autowired
private AdminRoleMapper adminRoleMapper;

然后,在原有的addNew()方法的最后补充:

// 插入管理员与角色的关联关系
log.debug("准备插入管理员与角色的关联关系");
LocalDateTime now = LocalDateTime.now();
Long[] roleIds = adminAddNewDTO.getRoleIds();
List<AdminRole> adminRoleList = new ArrayList<>();
for (int i = 0; i < roleIds.length; i++) {
AdminRole adminRole = new AdminRole();
adminRole.setAdminId(admin.getId());
adminRole.setRoleId(roleIds[i]);
adminRole.setGmtCreate(now);
adminRole.setGmtModified(now);
adminRoleList.add(adminRole);
}
rows = adminRoleMapper.insertBatch(adminRoleList);
if (rows != roleIds.length) {
// 是:抛出ServiceException(ERR_INSERT)
String message = "添加管理员失败,服务器忙,请稍后再尝试![错误代码:2]";
log.warn(message);
throw new ServiceException(ServiceCode.ERR_INSERT, message);
}
log.debug("添加管理员完成!");

完成后,可以通过AdminServiceTests中原有的测试方法进行测试,也可以在重启项目后,通过前端页面来添加管理员,都会是成功的,此功能开发至此就已经完成!

4. 修复:增加管理员时,检查角色id是否存在

客户端提交的角色id是Long[] roleIds,可以通过WHERE id IN (?,?)作为条件的查询进行检查,需要执行的SQL语句大致是:

SELECT count(*) FROM ams_role WHERE id IN (?,?, ... ?);

RoleMapper.java接口中补充抽象方法:

int countByIds(Long[] ids);

RoleMapper.xml中配置以上抽象方法映射的SQL语句:

<!-- int countByIds(Long[] ids); -->
<select id="countByIds" resultType="int">
SELECT count(*) FROM ams_role WHERE id IN (
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</select>

RoleMapperTests中编写并执行测试:

@Test
void testCountByIds() {
Long[] ids = {1L,2L,3L,7L,9L};
int count = mapper.countByIds(ids);
log.debug("根据id({})进行统计,统计结果={}", Arrays.toString(ids), count);
}

最后,在AdminServiceImpladdNew()方法,在插入管理员与角色关联之前,补充:

// 需要补充:自动装配RoleMapper对象
// 检查各角色id是否存在
Long[] roleIds = adminAddNewDTO.getRoleIds(); // 从原下方代码中移动到此处
int countByIds = roleMapper.countByIds(roleIds);
if (countByIds != roleIds.length) {
// 是:抛出ServiceException(ERR_BAD_REQUEST)
String message = "添加管理员失败,角色数据错误!";
log.warn(message);
throw new ServiceException(ServiceCode.ERR_BAD_REQUEST, message);
}

4. 修复:删除管理员时,需要删除关联数据

当删除管理员时,对应的“管理员与角色的关联”数据也需要一并删除!

关于Mapper层

需要执行的SQL语句大致是:

DELETE FROM ams_admin_role WHERE admin_id=?

AdminRoleMapper.java接口中添加抽象方法:

int deleteByAdmin(Long adminId);

AdminMapper.xml中配置SQL:

<!-- int deleteByAdmin(Long adminId); -->
<delete id="deleteByAdmin">
DELETE FROM ams_admin_role WHERE admin_id=#{adminId}
</delete>

AdminMapperTests中编写并执行测试:

@Test
void testDeleteByAdmin() {
Long adminId = 17L;
int rows = mapper.deleteByAdmin(adminId);
log.debug("根据管理员【id={}】删除关联数据,受影响的行数={}", adminId, rows);
}

关于Service层

需要在现有的“删除管理员”的业务中,补充“从ams_admin_role表中删除此管理员的关联数据”。

AdminServiceImpl类中的deleteById()方法的最后补充:

// 删除“管理员与角色”的关联数据
rows = adminRoleMapper.deleteByAdmin(id);
// 判断返回值是否小于1
if (rows < 1) {
// 抛出ServiceException,业务状态码:DELETE对应的常量
String message = "删除管理员失败!服务器忙,请稍后再次尝试![错误代码:2]";
log.warn(message);
throw new ServiceException(ServiceCode.ERR_DELETE, message);
}

作业

完成:通过前端页面的操作,实现“启用”、“禁用”管理员账号。

最后

以上就是冷静发箍为你收集整理的csmall-passport(Day15)1. 显示角色列表2. 关于客户端提交数组格式的数据3. 调整:添加管理员时关联角色4. 修复:增加管理员时,检查角色id是否存在4. 修复:删除管理员时,需要删除关联数据作业的全部内容,希望文章能够帮你解决csmall-passport(Day15)1. 显示角色列表2. 关于客户端提交数组格式的数据3. 调整:添加管理员时关联角色4. 修复:增加管理员时,检查角色id是否存在4. 修复:删除管理员时,需要删除关联数据作业所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部