SpringBoot开发全流程
Controller层往传输层传是VO,接受数据是DTO
**1.分析需求
2.创建Controller**
常用注解:
@Slf4j
@RestController
@Api("权限点管理")
@RequestMapping("/api/fill")
service注入接口:
@Autowired
private XXXService xxServbice;
创建方法:增删查改的请求方法不甚相同。
- 获取
/**
* 注解:这是方法的作用
*
* @return
*/
@Operation(summary = "档案目录全量树", description = "获取档案目录全量树")
@**GetMapping**("/tree")
public RestApiResult<> funtion(){
1.调用Service
xxx=xxxService.funtion();
2.return RestApiResult.success();
}
- 新增
@Operation(summary = "新增档案目录文件夹结点", description = "新增档案目录文件夹结点")
@**PostMapping**("/dir")
与上同。。。
- 修改
@Operation(summary = "修改档案目录文件夹结点", description = "修改档案目录文件夹结点", parameters = {
@Parameter(name = "id", description = "档案目录id")
})
@**PutMapping**("/dir/{id}")
与上同。。。
- 删除
@Operation(summary = "删除档案目录文件夹结点", description = "删除档案目录文件夹结点")
@**DeleteMapping**("/dir/{id}")
3.创建Service接口interface
/**
* XXX服务
*
* @author lcj
*/
/**
* 注解:方法作用
*
* @param archiveCatalogue
* @return
*/
//抽象方法
List<ArchiveCatalogueTreeNode> getAllArchiveCatalogueDir();
返回值 方法名(形参 实参)
4.创建ServiceImpl
@Slf4j
@Service
/**
* 注解:xxx服务实现类
*
* @Author:xxx
* @Date:2021/4/23
*/
@Autowired
private xxxDao xxxDao;
锁内校验:
@Override
@Transactional(rollbackFor = Exception.class)
//锁到同一parentId下
String lockStrByFatherId = LOCK_FLAG_FOR_MOVE + archiveCatalogue.getParentId();
synchronized (lockStrByFatherId.intern()) {
//校验:如果查不到要修改的结点,则返回找不到结点
Optional<ArchiveCatalogue> upArchive = Optional.ofNullable(archiveCatalogueDao.getById(archiveCatalogue.getId()));
if (!upArchive.isPresent() || upArchive.get().getDeleted()) {
throw new ApmCommonException("找不到要修改的档案目录,档案目录的id有误");
});
archiveCatalogueDao.updateNameById(archiveCatalogue);
}
抽象:
第一步:将传过来的DTO转化为POJO实体类对象。
ArchiveCatalogue archiveCatalogue = ArchiveCatalogue.builder()
.name(archiveCatalogueVO.getDirName())
.id(id)
.parentId(archiveCatalogueVO.getParentId())
.gmtModified(DateUtils.localTimeNow())
.build();
第二步:将传过来的值进行校验:包括但不限于空值校验,重名校验,是否删除校验等
//校验:如果查不到要修改的结点,则返回找不到结点
Optional<ArchiveCatalogue> upArchive = Optional.ofNullable(archiveCatalogueDao.getById(archiveCatalogue.getId()));
if (!upArchive.isPresent() || upArchive.get().getDeleted()) {
throw new ApmCommonException("找不到要修改的档案目录,档案目录的id有误");
}
//校验:询修改后的结点是否在同级有重名
archiveCatalogueDao.getArchiveByName(archiveCatalogue.getParentId(), archiveCatalogue.getName())
.ifPresent(dupNode -> {
log.error("新增失败,档案目录名称发生重复,ArchiveCatalogue:{}", archiveCatalogue);
throw new ApmCommonException("修改后的档案目录名称不能与同级档案重名!");
});
第三步:
调用Dao层方法
archiveCatalogueDao.updateNameById(archiveCatalogue);
5.创建Dao接口extends IService
public interface ArchiveCatalogueDao extends IService<ArchiveCatalogue> {
}
/**
* 方法作用注解
*
* @return
*/
List<ArchiveCatalogue> getAllarchiveCatalogues();
6.创建DaoImpl
@Dao
@Component
public class ArchiveCatalogueDaoImpl extends ServiceImpl<ArchiveCatalogueMapper,ArchiveCatalogue> implements ArchiveCatalogueDao {
private static final String ID = "id";//数据库字段一一映射关系
//注入mapper
@Autowired
private ArchiveCatalogueMapper archiveCatalogueMapper;
@Override
public List<ArchiveCatalogue> listCatalogues(Collection<Integer> catalogueIds) {
//dao层校验
if (CollectionUtils.isEmpty(catalogueIds)) {
return Lists.newArrayList();
}
//调用QueryMapper的各种方法,in,eq等过滤
//selectList,selectone等
QueryWrapper<ArchiveCatalogue> queryWrapper = new QueryWrapper<>();
queryWrapper.in(ID, catalogueIds).eq(IS_DELETED, false);
return archiveCatalogueMapper.selectList(queryWrapper);
}
}
7.创建接口mapper
extends BaseMapper
常用注解
@Component
把普通pojo实例化到spring容器中
/**
*
* 数据库表名 Mapper
*
* @Author:liangchangjian
* @Date:2021/4/23
*/
@Component
public interface ArchiveCatalogueMapper extends BaseMapper<ArchiveCatalogue> {
}
8.创建DTO
接受前端传输的数据是DTO
主要注解:
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class AddArchiveCatalogueDirDTO {
@Schema(description = "名称")
@NotBlank(message = "名称不能为空")
@Schema(description = "父级节点id")
@NotNull(message = "父级节点id不能为空")
@Min(value = 0, message = "父级节点id最小为0")
private Integer parentId;
/**
* afterId. 默认为0,可以不传
*/
@Schema(description = "afterId. 默认为0,可以不传")
@Nullable
@Min(0)
private Integer afterId;
//将DTO转实体对象
public ArchiveCatalogue toArchiveCatalogue() {
return ArchiveCatalogue.builder()
.name(this.dirName)
.afterId(Objects.isNull(afterId) ? TemplateConstant.LLAST_AFTER_ID : afterId)
.type(ArchiveCatalogueNodeType.DIR.getCode())
.parentId(this.parentId)
.deleted(Boolean.FALSE)
.gmtCreate(DateUtils.localTimeNow())
.gmtModified(DateUtils.localTimeNow())
.build();
}
9.创建VO
往传输层前端传是VO
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ArchiveCatalogueVO {
/**
* 后继结点id
*/
@Schema(description = "afterId. 默认为0,可以不传")
@Nullable
@Min(0)
private Integer afterId;
//将处理完的实体对象转化为VO对象
public static ArchiveCatalogueVO from(ArchiveCatalogue catalogue) {
return ArchiveCatalogueVO.builder()
.id(catalogue.getId())
.dirName(catalogue.getName())
.parentId(catalogue.getParentId())
.afterId(catalogue.getAfterId()).build();
}
}
10.创建枚举类
public enum ArchiveCatalogueNodeType {
/**
*类型:文件夹
**/
DIR(2,Boolean.FALSE,"dir");
@Getter
private final Integer code;
@Getter
private final Boolean isFile;
ArchiveCatalogueNodeType(Integer code, Boolean isFile, String name) {
this.code = code;
this.isFile = isFile;
this.name = name;
}
/**
* 根据传值校验文件夹类型
* @param type
* @return
*/
/**
* 根据传入值返回对应枚举对象
*
* @param b Boolean
* @return TemplateType
*/
public static ArchiveCatalogueNodeType valueOf(@NonNull Boolean b) {
for (ArchiveCatalogueNodeType type : ArchiveCatalogueNodeType.values()) {
if (type.isFile.equals(b)) {
}
}
throw new IllegalArgumentException();
}
}
完结,撒花!