一、PageDTO<T>
java
复制代码
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.Convert;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果")
public class PageDTO<T> {
@ApiModelProperty("总条数")
protected Long total;
@ApiModelProperty("总页码数")
protected Long pages;
@ApiModelProperty("当前页数据")
protected List<T> list;
public static <T> PageDTO<T> empty(Long total, Long pages) {
return new PageDTO<>(total, pages, CollUtils.emptyList());
}
public static <T> PageDTO<T> empty(Page<?> page) {
return new PageDTO<>(page.getTotal(), page.getPages(), CollUtils.emptyList());
}
public static <T> PageDTO<T> of(Page<T> page) {
if(page == null){
return new PageDTO<>();
}
if (CollUtils.isEmpty(page.getRecords())) {
return empty(page);
}
return new PageDTO<>(page.getTotal(), page.getPages(), page.getRecords());
}
public static <T,R> PageDTO<T> of(Page<R> page, Function<R, T> mapper) {
if(page == null){
return new PageDTO<>();
}
if (CollUtils.isEmpty(page.getRecords())) {
return empty(page);
}
return new PageDTO<>(page.getTotal(), page.getPages(),
page.getRecords().stream().map(mapper).collect(Collectors.toList()));
}
public static <T> PageDTO<T> of(Page<?> page, List<T> list) {
return new PageDTO<>(page.getTotal(), page.getPages(), list);
}
public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz) {
return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz));
}
public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz, Convert<R, T> convert) {
return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz, convert));
}
@ApiModelProperty(hidden = true)
@JsonIgnore
public boolean isEmpty(){
return list == null || list.size() == 0;
}
}
二、 PageQuery
2.1 PageQuery代码
java
复制代码
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxx.common.constants.Constant;
import com.xxx.common.utils.StringUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.Min;
@Data
@ApiModel(description = "分页请求参数")
@Accessors(chain = true)
public class PageQuery {
public static final Integer DEFAULT_PAGE_SIZE = 20;
public static final Integer DEFAULT_PAGE_NUM = 1;
@ApiModelProperty(value = "页码", example = "1")
@Min(value = 1, message = "页码不能小于1")
private Integer pageNo = DEFAULT_PAGE_NUM;
@ApiModelProperty(value = "每页大小", example = "5")
@Min(value = 1, message = "每页查询数量不能小于1")
private Integer pageSize = DEFAULT_PAGE_SIZE;
@ApiModelProperty(value = "是否升序", example = "true")
private Boolean isAsc = true;
@ApiModelProperty(value = "排序字段", example = "id")
private String sortBy;
public int from(){
return (pageNo - 1) * pageSize;
}
public <T> Page<T> toMpPage(OrderItem ... orderItems) {
Page<T> page = new Page<>(pageNo, pageSize);
// 是否手动指定排序方式
if (orderItems != null && orderItems.length > 0) {
for (OrderItem orderItem : orderItems) {
page.addOrder(orderItem);
}
return page;
}
// 前端是否有排序字段
if (StringUtils.isNotEmpty(sortBy)){
OrderItem orderItem = new OrderItem();
orderItem.setAsc(isAsc);
orderItem.setColumn(sortBy);
page.addOrder(orderItem);
}
return page;
}
public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {
if (StringUtils.isBlank(sortBy)){
sortBy = defaultSortBy;
this.isAsc = isAsc;
}
Page<T> page = new Page<>(pageNo, pageSize);
OrderItem orderItem = new OrderItem();
orderItem.setAsc(this.isAsc);
orderItem.setColumn(sortBy);
page.addOrder(orderItem);
return page;
}
public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
return toMpPage(Constant.DATA_FIELD_NAME_CREATE_TIME, false);
}
}
2.2 使用举例
java
复制代码
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "互动问题分页查询条件")
public class QuestionPageQuery extends PageQuery {
// 用户端查询条件
@ApiModelProperty(value = "课程id")
private Long courseId;
@ApiModelProperty(value = "小节id", example = "1")
private Long sectionId;
@ApiModelProperty(value = "是否只查询我的问题", example = "1")
private Boolean onlyMine;
}
----------------------------------------------------------------
//1 获取用户id
Long userId = UserContext.getUser();
Boolean onlyMine = query.getOnlyMine(); // 是否只查询自己
Long sectionId = query.getSectionId();
Long courseId = query.getCourseId();
//2 分页查询问题表(question)数据
// selecgt * from question where user_id=? and course_id =? and section_id=? and hidden= false;
Page<InteractionQuestion> page = this.lambdaQuery()
.eq(onlyMine, InteractionQuestion::getUserId, userId) // 只查询自己,才拼接条件
.eq(courseId != null, InteractionQuestion::getCourseId, courseId) // 传递了 课程,才拼接课程查询
.eq(sectionId != null, InteractionQuestion::getSectionId, sectionId) // 传递了 小节,才拼接小节查询
.eq(InteractionQuestion::getHidden, false) // 被管理员隐藏的不显示
.page(query.toMpPageDefaultSortByCreateTimeDesc()); // 按照创建日期倒叙排序
List<InteractionQuestion> records = page.getRecords();
if(CollUtils.isEmpty(records)){ // 如果没有
return PageDTO.empty(page);
}
java
复制代码
// 1.获取用户id
Long userId = UserContext.getUser();
// 2) 分页查询数据库
// select * from learning_lesson where user_id=? order by create_time desc limit 5
Page<LearningLesson> page = this.lambdaQuery()
.eq(LearningLesson::getUserId, userId)
.page(query.toMpPage("latest_learn_time", false));
// mybatis 会把 查询的数据全部封装到 page 中: 数据, 总条数数据集
List<LearningLesson> records = page.getRecords(); // 获取当前页数据
if(CollUtils.isEmpty(records)){
return PageDTO.empty(page); // 如果没有数据返回空对象
}
三、BeanUtils
3.1 BeanUtils代码
java
复制代码
import cn.hutool.core.bean.BeanUtil;
import java.util.List;
import java.util.stream.Collectors;
/**
* 继承自 hutool 的BeanUtil,增加了bean转换时自定义转换器的功能
*/
public class BeanUtils extends BeanUtil {
/**
* 将原对象转换成目标对象,对于字段不匹配的字段可以使用转换器处理
*
* @param source 原对象
* @param clazz 目标对象的class
* @param convert 转换器
* @param <R> 原对象类型
* @param <T> 目标对象类型
* @return 目标对象
*/
public static <R, T> T copyBean(R source, Class<T> clazz, Convert<R, T> convert) {
T target = copyBean(source, clazz);
if (convert != null) {
convert.convert(source, target);
}
return target;
}
/**
* 将原对象转换成目标对象,对于字段不匹配的字段可以使用转换器处理
*
* @param source 原对象
* @param clazz 目标对象的class
* @param <R> 原对象类型
* @param <T> 目标对象类型
* @return 目标对象
*/
public static <R, T> T copyBean(R source, Class<T> clazz){
if (source == null) {
return null;
}
return toBean(source, clazz);
}
public static <R, T> List<T> copyList(List<R> list, Class<T> clazz) {
if (list == null || list.size() == 0) {
return CollUtils.emptyList();
}
return copyToList(list, clazz);
}
public static <R, T> List<T> copyList(List<R> list, Class<T> clazz, Convert<R, T> convert) {
if (list == null || list.size() == 0) {
return CollUtils.emptyList();
}
return list.stream().map(r -> copyBean(r, clazz, convert)).collect(Collectors.toList());
}
}
java
复制代码
package com.xxx.common.utils;
/**
* 对原对象进行计算,设置到目标对象中
**/
public interface Convert<R,T>{
void convert(R origin, T target);
}
3.2 举例
java
复制代码
public void save(CourseTeacherSaveDTO courseTeacherSaveDTO) {
//1.数据删除条件
LambdaUpdateWrapper<CourseTeacherDraft> updateWrapper =
Wrappers.lambdaUpdate(CourseTeacherDraft.class)
.eq(CourseTeacherDraft::getCourseId, courseTeacherSaveDTO.getId());
//1.1.数据删除
baseMapper.delete(updateWrapper);
//2.组装即将插入的数据
// List<TeacherInfo> teachers
List<CourseTeacherDraft> courseTeacherDrafts =
BeanUtils.copyList(courseTeacherSaveDTO.getTeachers(),
CourseTeacherDraft.class,
(teacherInfo, teacherDraft) -> {
//2.1.设置课程id
teacherDraft.setCourseId(courseTeacherSaveDTO.getId());
//2.2.设置老师id
teacherDraft.setTeacherId(teacherInfo.getId());
//2.3.设置课程中老师排序
teacherDraft.setCIndex(courseTeacherSaveDTO.getTeachers().indexOf(teacherInfo));
});
//3.批量插入课程的老师信息
saveBatch(courseTeacherDrafts);
//4.更新课程填写进度
courseDraftService.updateStep(courseTeacherSaveDTO.getId(), CourseConstants.CourseStep.TEACHER);
}
-----------------------------------------------------
@ApiModel("课程老师关系模型")
public class CourseTeacherSaveDTO {
@ApiModelProperty("课程id")
@NotNull(message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_COURSE_ID_NULL)
private Long id;
@ApiModelProperty("老师id和用户端是否展示,该列表按照界面上的顺序")
@NotNull(message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_TEACHERS_NULL)
// @Min(value = 1, message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_TEACHERS_NULL)
@Size(min = 1, max = 5, message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_TEACHERS_NUM_MAX )
private List<TeacherInfo> teachers;
@Data
@ApiModel("老师id和用户端是否显示")
public static class TeacherInfo{
@ApiModelProperty("老师id")
@NotNull(message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_TEACHER_ID_NULL)
private Long id;
@ApiModelProperty("用户端是否展示")
@NotNull(message = CourseErrorInfo.Msg.COURSE_TEACHER_SAVE_TEACHER_SHOW)
private Boolean isShow;
}
}
四、CollUtils
4.1 CollUtils代码
java
复制代码
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.IterUtil;
import com.xxx.common.validate.Checker;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 继承自 hutool 的集合工具类
*/
public class CollUtils extends CollectionUtil {
public static <T> List<T> emptyList() {
return Collections.emptyList();
}
public static <T> Set<T> emptySet() {
return Collections.emptySet();
}
public static <K,V> Map<K, V> emptyMap() {
return Collections.emptyMap();
}
public static <T> Set<T> singletonSet(T t) {
return Collections.singleton(t);
}
public static <T> List<T> singletonList(T t) {
return Collections.singletonList(t);
}
public static List<Integer> convertToInteger(List<String> originList){
return CollUtils.isNotEmpty(originList) ? originList.stream().map(NumberUtils::parseInt).collect(Collectors.toList()) : null;
}
public static List<Long> convertToLong(List<String> originLIst){
return CollUtils.isNotEmpty(originLIst) ? originLIst.stream().map(NumberUtils::parseLong).collect(Collectors.toList()) : null;
}
/**
* 以 conjunction 为分隔符将集合转换为字符串 如果集合元素为数组、Iterable或Iterator,则递归组合其为字符串
* @param collection 集合
* @param conjunction 分隔符
* @param <T> 集合元素类型
* @return 连接后的字符串
* See Also: IterUtil.join(Iterator, CharSequence)
*/
public static <T> String join(Collection<T> collection, CharSequence conjunction) {
if (null == collection || collection.isEmpty()) {
return null;
}
return IterUtil.join(collection.iterator(), conjunction);
}
public static <T> String joinIgnoreNull(Collection<T> collection, CharSequence conjunction) {
if (null == collection || collection.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
for (T t : collection) {
if(t == null) continue;
sb.append(t).append(",");
}
if(sb.length() <= 0){
return null;
}
return sb.deleteCharAt(sb.length() - 1).toString();
}
/**
* 集合校验逻辑
*
* @param data 要校验的集合
* @param checker 校验器
* @param <T> 集合元素类型
*/
public static <T> void check(List<T> data, Checker<T> checker){
if(data == null){
return;
}
for (T t : data){
checker.check(t);
}
}
/**
* 集合校验逻辑
*
* @param data 要校验的集合
* @param <T> 集合元素类型
*/
public static <T extends Checker<T>> void check(List<T> data){
if(data == null){
return;
}
for (T t : data){
t.check();
}
}
/**
* 将元素加入到集合中,为null的过滤掉
*
* @param list 集合
* @param data 要添加的数据
* @param <T> 元素类型
*/
public static <T> void add(Collection<T> list, T... data) {
if (list == null || ArrayUtils.isEmpty(data)) {
return;
}
for (T t : data) {
if (ObjectUtils.isNotEmpty(t)) {
list.add(t);
}
}
}
//将两个集合出现次数相加
public static Map<Long, Integer> union(Map<Long, Integer> map1, Map<Long, Integer> map2) {
if (CollUtils.isEmpty(map1)) {
return map2;
} else if (CollUtils.isEmpty(map2)) {
return map1;
}
for (Map.Entry<Long, Integer> entry : map1.entrySet()) {
Integer num = map2.get(entry.getKey());
map2.put(entry.getKey(), NumberUtils.null2Zero(num) + entry.getValue());
}
return map2;
}
public static <T,R> R getFiledOfFirst(List<T> list, Function<T, R> function) {
if (CollUtils.isEmpty(list)) {
return null;
}
return function.apply(list.get(0));
}
}
java
复制代码
/**
* 实现后在接口访问时如果接口实现了这个接口
* 会被自动自行接口check进行校验
**/
public interface Checker<T> {
/**
* 用于实现validation不能校验的数据逻辑
*/
default void check(){
}
default void check(T data){
}
}
4.2 checker举例
java
复制代码
@ApiModel(description = "章节")
public class CataSaveDTO implements Checker {
@ApiModelProperty("章、节、练习id")
private Long id;
@ApiModelProperty("目录类型1:章,2:节,3:测试")
@NotNull(message = "")
private Integer type;
@ApiModelProperty("章节练习名称")
private String name;
@ApiModelProperty("章排序,章一定要传,小节和练习不需要传")
private Integer index;
@ApiModelProperty("当前章的小节或练习")
@Size(min = 1, message = "不能出现空章")
private List<CataSaveDTO> sections;
@Override
public void check() {
//名称为空校验
if(type == CourseConstants.CataType.CHAPTER && StringUtils.isEmpty(name)) {
throw new BadRequestException(CourseErrorInfo.Msg.COURSE_CATAS_SAVE_NAME_NULL);
}else if(StringUtils.isEmpty(name)){
throw new BadRequestException(CourseErrorInfo.Msg.COURSE_CATAS_SAVE_NAME_NULL2);
}
//名称长度问题
if (type == CourseConstants.CataType.CHAPTER && name.length() > 30){
throw new BadRequestException(CourseErrorInfo.Msg.COURSE_CATAS_SAVE_NAME_SIZE);
}else if(name.length() > 30) {
throw new BadRequestException(CourseErrorInfo.Msg.COURSE_CATAS_SAVE_NAME_SIZE2);
}
if(CollUtils.isEmpty(sections)){
throw new BadRequestException("不能出现空章");
}
}
}
java
复制代码
@ApiModel("题目保存模型")
@Data
public class SubjectSaveDTO implements Checker {
@ApiModelProperty("题目id,为空新增,不为空更新")
private Long id;
@ApiModelProperty("名称")
@NotNull(message = "题目为空,请设置题目")
@Size(max = 200, min = 5, message = "题目长度为5-200")
private String name;
@ApiModelProperty("所属题目分类")
@NotNull(message = "题目分类为空,请设置题目分类")
private List<List<Long>> cates;
@ApiModelProperty("题目类型")
@NotNull(message = "题目类型为空,请设置题目类型")
@EnumValid(enumeration = {1,2,3,4,5}, message = "题目类型只有单选题,多选题,不定向选择题,判断题,您的题目超出题纲")
private Integer subjectType;
@ApiModelProperty("题目难易度")
@NotNull(message = "难度不能为空")
@EnumValid(enumeration = {1,2,3},message = "题目难度只有简单,中等,困难")
private Integer difficulty;
@ApiModelProperty("分值")
private Integer score;
@ApiModelProperty("课程id")
private List<Long> courseIds;
@ApiModelProperty("选项,最多10个")
private List<String> options;
@ApiModelProperty("答案,判断题,数组第一个如果是1,代表正确,其他代表错误")
@NotNull(message = "题目答案不能为空")
private List<Integer> answers;
@ApiModelProperty("解析")
private String analysis;
@Override
public void check() {
//选择题 单选,多选,不定向选择
if(subjectType == SubjectConstants.Type.SIGNLE_CHOICE.getType() ||
subjectType == SubjectConstants.Type.MUtiple_CHOICE.getType() ||
subjectType == SubjectConstants.Type.NON_DIRECTIONAL_CHOICE.getType()){
Integer answerOptionMax = answers.stream().max(Integer::compare).get();
//选项最少1个最多10个
if(CollUtils.isEmpty(options) || options.size() > 10){
throw new BizIllegalException("最少1个选项,最多10个选项");
}
//选择题答案 不能超过选项数
if(answerOptionMax > options.size()){
throw new BizIllegalException("存在正确的答案找不到选项");
}
if(StringUtils.isNotEmpty(analysis)
&& (StringUtils.length(analysis) < 5
|| StringUtils.length(analysis) > 300)) {
throw new BadRequestException("答案解析长度为5-300");
}
}
}
}