PigUserDetailsService 代码地址与接口文档看总目录:【学习笔记】记录冷冷-pig项目的学习过程,大概包括Authorization Server、springcloud、Mybatis Plus~~~_清晨敲代码的博客-CSDN博客
终于结束从零搭建springcloud的部分了,目前也仅仅是学习了最最基本的逻辑,同时包含了开发系统的一些基本的逻辑。接下来就按照 pig 文档将其余基本的内容再熟悉一下,看一遍和写一遍真的不一样呐~~~
那接下来就一小模块一小模块的学习啦,加油吧少年!
本文及以后的文章还是基于前面的No6系列文章开发的,可以看之前文章顶部的内容总结,简单了解详情~
目录
A1.添加字典功能
字典,又分为字典和字典项,每个字典项属于某一个字典,每个字典有多个字典项。这样前端就可以根据字典拿到字典项。
获取到的字典的属性,要尽可能适用于前端的组件,方便前端使用。
B1.步骤
首先,我们需要提供一个字典的增删改查功能,然后再提供一个字典项的增删改查功能,同时字典项必须要关联一个字典,并且字典项要有值和标签,值对应业务操作,标签对应用户展示。
由于没有复杂业务,所以不需要关联表操作,不需要写 mapper 语句~
B2.编码
确定好数据结构之后,一定要先写接口文档,梳理编码逻辑!
1.新建两个数据表,一个字典sys_dict,一个字典项sys_dict_item,设置 id 自增;
2.新建表对应的实体类,要设置 mps 的id自增,和逻辑删除注解;
3.新建 mapper 接口,继承 mps 的 BaseMapper ,不需要新增方法;
4.新建 service 接口及实现类,继承 mps 的 IService、IServiceImpl ;
5.新建 controller 类,编写接口端点方法,并确定好需要调用的 service 方法;
【我习惯了解数据接口和接口文档后,就针对他们编写 controller 中的接口端点,然后再编写 service 业务方法】
6.有些复杂的业务需要增加业务方法,所以修改 service 类,编写 controller 需要的方法;
-- 1.新建两个数据表,一个字典sys_dict,一个字典项sys_dict_item,设置 id 自增;
CREATE TABLE `sys_dict` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`dict_type` varchar(100) DEFAULT NULL COMMENT '标识',
`description` varchar(100) DEFAULT NULL COMMENT '描述',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`system_flag` char(1) DEFAULT '0' COMMENT '是否是系统内置',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='字典表'
CREATE TABLE `sys_dict_item` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`dict_id` bigint(20) NOT NULL COMMENT '字典ID',
`dict_type` varchar(100) DEFAULT NULL COMMENT '字典标识',
`value` varchar(100) DEFAULT NULL COMMENT '值',
`label` varchar(100) DEFAULT NULL COMMENT '标签',
`description` varchar(100) DEFAULT NULL COMMENT '描述',
`sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序(升序)',
`remark` varchar(255) DEFAULT ' ' COMMENT '备注',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `sys_dict_value` (`value`) USING BTREE,
KEY `sys_dict_label` (`label`) USING BTREE,
KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COMMENT='字典项'
//2.新建表对应的实体类,要设置 mps 的id自增,和逻辑删除注解;
//新增
com.pig4cloud.pig.admin.api.entity.SysDict extends BaseEntity
com.pig4cloud.pig.admin.api.entity.SysDictItem extends BaseEntity
//3.新建 mapper 接口,继承 mps 的 BaseMapper ,不需要新增方法;
@Mapper
public interface SysDictMapper extends BaseMapper<SysDict> {
}
@Mapper
public interface SysDictItemMapper extends BaseMapper<SysDictItem> {
}
//4.新建 service 接口及实现类,继承 mps 的 IService、IServiceImpl ;
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
}
public class SysDictItemServiceImpl extends ServiceImpl<SysDictItemMapper, SysDictItem> implements SysDictItemService {
}
//5.新建 controller 类,编写接口端点方法,并确定好需要调用的 service 方法;
//其中只有两个更新和两个删除的需要重写对应的 service 方法,因为需要判断是否能删除,并且涉及到关联删除~
//其余的使用 mps 提供的 service 方法就行
@RestController
@RequestMapping("/dict")
@RequiredArgsConstructor
public class DictController {
private final SysDictService sysDictService;
private final SysDictItemService sysDictItemService;
/**
* @Description: 添加
* @param: [dict]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("添加字典")
@PostMapping
@PreAuthorize("@pms.hasPermission('sys_dict_add')")
public R<Boolean> save(@RequestBody SysDict dict) {
//标签必须唯一,先判断是否已存在
SysDict sysDict = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getDictType, dict.getDictType()));
if ( sysDict != null){
return R.failed("标签已存在");
}
return R.ok(sysDictService.save(dict));
}
/**
* @Description: 分页查询字典
* @param: [page, dict]
* @return: com.pig4cloud.pig.common.core.util.R<com.baomidou.mybatisplus.core.metadata.IPage<com.pig4cloud.pig.admin.api.entity.SysDict>>
**/
@SysLog("分页查询字典")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('sys_dict_list')")
public R<IPage<SysDict>> getPage(Page page, SysDict dict) {
LambdaQueryWrapper<SysDict> wrapper = Wrappers.lambdaQuery();
wrapper.eq(SysDict::getDelFlag, CommonConstants.NOT_DELETE);
if(StrUtil.isNotBlank(dict.getDictType())){
wrapper.like(SysDict::getDictType, dict.getDictType());
}
if(StrUtil.isNotBlank(dict.getDictType())){
wrapper.like(SysDict::getSystemFlag, dict.getSystemFlag());
}
return R.ok(sysDictService.page(page, wrapper));
}
/**
* @Description: 通过ID查询字典
* @param: [id]
* @return: com.pig4cloud.pig.common.core.util.R<com.pig4cloud.pig.admin.api.entity.SysDict>
**/
@SysLog("通过ID查询字典")
@GetMapping("/{id}")
public R<SysDict> getById(@PathVariable Long id) {
return R.ok(sysDictService.getById(id));
}
/**
* @Description: 添加
* @param: [dictItem]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("添加字典项")
@PostMapping("/item")
public R<Boolean> save(@RequestBody SysDictItem dictItem) {
//value 必须唯一,先判断当前字典中是否已存在该 value
SysDictItem sysDictItem = sysDictItemService.getOne(
Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType()).eq(SysDictItem::getValue, dictItem.getValue()));
if ( sysDictItem != null){
return R.failed("值已存在");
}
return R.ok(sysDictItemService.save(dictItem));
}
/**
* @Description: 分页查询某个字典的字典项
* @param: [page, dictItem]
* @return: com.pig4cloud.pig.common.core.util.R<com.baomidou.mybatisplus.core.metadata.IPage<com.pig4cloud.pig.admin.api.entity.SysDictItem>>
**/
@SysLog("分页查询某个字典的字典项")
@GetMapping("/item/page")
@PreAuthorize("@pms.hasPermission('sys_dictItem_list')")
public R<IPage<SysDictItem>> getDictItemPage(Page page, SysDictItem dictItem) {
return R.ok(sysDictItemService.page(page,
Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType())
.eq(SysDictItem::getDelFlag, CommonConstants.NOT_DELETE)));
}
/**
* @Description: 通过ID查询字典项
* @param: [id]
* @return: com.pig4cloud.pig.common.core.util.R<com.pig4cloud.pig.admin.api.entity.SysDictItem>
**/
@SysLog("通过ID查询字典项")
@GetMapping("/item/{id}")
public R<SysDictItem> getDictItemById(@PathVariable Long id) {
return R.ok(sysDictItemService.getById(id));
}
/**
* @Description: 通过字典标识查找字典项
* @param: [type]
* @return: com.pig4cloud.pig.common.core.util.R<java.util.List<com.pig4cloud.pig.admin.api.entity.SysDictItem>>
**/
@GetMapping("/dictType/{dictType}")
public R<List<SysDictItem>> getDictByType(@PathVariable String dictType) {
return R.ok(sysDictItemService.list(
Wrappers.<SysDictItem>query().lambda().eq(SysDictItem::getDictType, dictType).eq(SysDictItem::getDelFlag, CommonConstants.NOT_DELETE)));
}
}
//6.有些复杂的业务需要增加业务方法,所以修改 service 类,编写 controller 需要的方法;
@Service
@RequiredArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
private final SysDictItemMapper dictItemMapper;
@Override
public Boolean updateDict(SysDict sysDict) {
//1.先拿到对应的存储的信息
SysDict dict = this.getById(sysDict.getId());
// 判断是不是系统内置的,如果是则抛异常不能修改
if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
throw new RuntimeException("系统内置字典不能修改");
}
//不是系统内置,则进行修改
this.updateById(sysDict);
return Boolean.TRUE;
}
@Override
public Boolean deleteDict(Long id) {
//先拿到对应的存储的信息
SysDict dict = this.getById(id);
// 判断是不是系统内置的,如果是则抛异常不能删除
if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
throw new RuntimeException("系统内置字典不允许删除");
}
//不是系统内置,则进行修改
baseMapper.deleteById(id);
//同时删除字典项
dictItemMapper.delete(Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictId, id));
return Boolean.TRUE;
}
}
@Service
@RequiredArgsConstructor
public class SysDictItemServiceImpl extends ServiceImpl<SysDictItemMapper, SysDictItem> implements SysDictItemService {
private final SysDictService dictService;
@Override
public Boolean updateDictItem(SysDictItem dictItem) {
//先获取字典的系统内置信息
SysDict dict = dictService.getById(dictItem.getDictId());
// 判断是不是系统内置的,如果是则抛异常不能修改
if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
throw new RuntimeException("系统内置字典不能修改");
}
//不是系统内置,则进行修改
this.updateById(dictItem);
return Boolean.TRUE;
}
@Override
public Boolean deleteDictItem(Long id) {
// 先根据ID查询字典ID
SysDictItem dictItem = this.getById(id);
//再获取字典的系统内置信息
SysDict dict = dictService.getById(dictItem.getDictId());
// 判断是不是系统内置的,如果是则抛异常不能修改
if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
throw new RuntimeException("系统内置字典不允许删除");
}
this.removeById(id);
return Boolean.TRUE;
}
}
@RestController
@RequestMapping("/dict")
@RequiredArgsConstructor
public class DictController {
private final SysDictService sysDictService;
private final SysDictItemService sysDictItemService;
/**
* @Description: 修改
* @param: [dict]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("修改字典")
@PutMapping
@PreAuthorize("@pms.hasPermission('sys_dict_update')")
public R<Boolean> update(@RequestBody SysDict dict) {
//标签必须唯一,先判断是否已存在未删除的、该标签
SysDict sysDict = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getDictType, dict.getDictType()).ne(SysDict::getId, dict.getId()));
if ( sysDict != null){
return R.failed("标签已存在");
}
return R.ok(sysDictService.updateDict(dict));
}
/**
* @Description: 删除
* @param: [dict]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("删除字典")
@DeleteMapping("/{id:\\d+}")
@PreAuthorize("@pms.hasPermission('sys_dict_del')")
public R<Boolean> deleteDictById(@PathVariable Long id) {
return R.ok(sysDictService.deleteDict(id));
}
/**
* @Description: 修改
* @param: [dictItem]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("修改字典项")
@PutMapping("/item")
public R<Boolean> update(@RequestBody SysDictItem dictItem) {
//value 必须唯一,先判断当前字典中是否已存在该 value
SysDictItem sysDictItem = sysDictItemService.getOne(
Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType()).eq(SysDictItem::getValue, dictItem.getValue()).ne(SysDictItem::getId, dictItem.getId()));
if ( sysDictItem != null){
return R.failed("值已存在");
}
return R.ok(sysDictItemService.updateDictItem(dictItem));
}
/**
* @Description: 删除
* @param: [id]
* @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
**/
@SysLog("删除字典项")
@DeleteMapping("/item/{id:\\d+}")
public R<Boolean> deleteDictItemById(@PathVariable Long id) {
return R.ok(sysDictItemService.deleteDictItem(id));
}
}
B3.测试
然后就按照 api 接口测试吧,后面要学一下 api 自动化测试~
遇到的问题:
1.基础增删改查需要判断是否存在
对于普通的单表,增删改查的业务中,如果遇到非正常操作怎么办?
例如,单表中有唯一数据时,改中要校验唯一数据是否存在(自己本身包含不算)。如果入参的 id 不存在或者已删除怎么办?还需要修改么?
从单账号操作的设计上来说,不会出现这种情况,毕竟操作的数据一定是未删除的。但是如果是多账号使用时,就会多个帐号同时删除此条数据,总有一个人成功,而其余人会失败,失败的人也要收到反馈信息。
此时的反馈信息不应该是 500 报错的。
看下图,我用多个线程来调用删除字典的操作,就有一个报错了,虽然最终的数据是对的。
原因是 controller 里面的判断,他通过,但是 service 里面再获取时就获取到了 null。所以还是要处理一下该异常。
新建一个业务异常处理类,然后可以在此处用 try catch 异常并抛出新增的业务异常处理类。
@Slf4j
@Order(10000)
@RestControllerAdvice
@ConditionalOnExpression("!'${security.oauth2.client.clientId}'.isEmpty()")
public class GlobalBizExceptionHandler {
/**
* 全局异常.
* @param e the e
* @return R
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public R handleGlobalException(Exception e) {
log.error("全局异常信息 ex={}", e.getMessage(), e);
// 业务异常交由 sentinel 记录
Tracer.trace(e);
return R.failed(e.getLocalizedMessage());
}
}
这样就不会报错 500 了
2.增删改查业务添加一个同意逻辑处理模块
写这一块儿的时候,总是修修改改,写某个接口时总感觉逻辑缺少,所以,整理一个基础的单表增删改查逻辑,方便开发理解。
开个新文章,到时粘个链接~
今天的文章建立字典库_alibaba inc「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87817.html