大道至简,Java Web开发提效50%

前言

开发是一个不断积累的过程,可以把我们平时重复用得比较多的内容,封装起来。这样是对自己个人的一种沉淀,以至于不会过一段时间,学了新的,却忘了旧的。所以从很早开始我就封装了一套框架来提升自己的开发效率,经过几年不断的优化。

在平时开发过程中,用得最多的还是spring boot + mybatis这一套。但是mybatis用得那是又爱又恨啊,自由度是挺高的,能够完成各种复杂的场景。但是用法上来说,还是比较繁琐的,需要不断的去实现Mapper,去写CURD的sql,甚至是写mybatis的xml配置。有时候想用hibernate,但是效率不够好,而且不够灵活。

我列举了一下,我封装了这些内容:

  • mybatis实体操作相关:
    1. 引入通用mapper,并扩展BaseMapper;
    2. 审计字段注解、拦截器,创建时间、修改时间、创建人、修改人、版本号。
    3. Example构造工具,使用Filter和OrFilter去构造简单的查询条件。
    4. 自动生成po对应的通用AutoMapper
    5. 数据库表自动生成:自动扫描PO类,根据注解创建数据库表。
  • controller相关:
    1. UserContext抽象类,@CurrentUser@CurrentUserId注解,绑定到controller方法字段。
    2. 查询条件构造器注解@Filter,自动将查询DTO转换成查询表达式List<Filter>
    3. vo字段填充,提供MessageHandler接口。
  • service相关:
    1. 实现BaseServiceBaseServiceImpl,封装CURD,分页查询相关方法。
    2. 参数校验拦截器:对@NotNull@NotEmpty等注解标注的参数校验,可以自定义扩展。
  • 任务分片TaskFragment,以及默认实现基于redis的分片。
  • 点击率记录器HitsRecorder
  • 进度条Progress
  • 工具相关:
    1. 正则表达式RegexUtils
    2. 反射工具RegexUtils
    3. RSA加密工具RSAUtils
    4. 爬虫工具Spider
    5. http请求工具ServiceClient
    6. 多线程文件下载器FastFileDownloader
    7. 视频处理相关:FfmpegUtilsHlsUtilsVideoCompressor

用法

引入

引入依赖包,当前最新版本是1.0.3

<!-- 数据库表自动生成器,不需要可以不引入 -->
<dependency>
    <groupId>com.github.668mt.web</groupId>
    <artifactId>mt-spring-generator-starter</artifactId>
    <version>${mt-spring-web-starter.version}</version>
</dependency>
<!-- 必须引入 -->
<dependency>
    <groupId>com.github.668mt.web</groupId>
    <artifactId>mt-spring-web-starter</artifactId>
    <version>${mt-spring-web-starter.version}</version>
</dependency>

需要配置如下参数:

#通用mapper的配置项
mapper.not-empty=false
mapper.style=camelhump
mapper.enum-as-simple-type=true

#如果需要配置自动创建表
project.generator-enable=true
project.generate-entity-packages=mt.spring.mos.server.entity.po

#需要参数拦截校验的包名,不需要可以不写
project.assert-package-name=mt.spring.mos.server.service

其它的配置和mybatis、jdbc一样。

审计字段

当需要自动注入创建时间、修改时间等审计字段的时候:

/**
 * @Author Martin
 * @Date 2020/5/16
 */
@Data
public class BaseEntity implements Serializable {
	private static final long serialVersionUID = -1294407818709225639L;
	@CreatedDate
	private Date createdDate;
	@CreatedByUserName
	private String createdBy;
	@UpdatedDate
	private Date updatedDate;
	@UpdatedByUserName
	private String updatedBy;
}

配置用户信息上下文

package mt.spring.mos.server.config;

import lombok.extern.slf4j.Slf4j;
import mt.common.currentUser.UserContext;
import mt.spring.mos.server.entity.po.User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

/**
 * @Author Martin
 * @Date 2020/5/23
 */
@Component
@Slf4j
public class MosUserContext implements UserContext<User, Long> {
	
	@Override
	public User getCurrentUser() {
		try {
			SecurityContext context = SecurityContextHolder.getContext();
			Authentication authentication = context.getAuthentication();
			if (authentication == null) {
				return null;
			}
			Object principal = authentication.getPrincipal();
			if (principal instanceof User) {
				return (User) principal;
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}
	
	@Override
	public Long getCurrentUserId() {
		User currentUser = getCurrentUser();
		if (currentUser != null) {
			return currentUser.getId();
		}
		return null;
	}
	
	@Override
	public String getCurrentUserName() {
		User currentUser = getCurrentUser();
		if (currentUser != null) {
			return currentUser.getUsername();
		}
		return null;
	}
}

单表CURD流程

PO的配置:
/**
 * @Author Martin
 * @Date 2020/5/20
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Table(name = "mos_dir")
@Index(columns = {"path", "bucket_id"}, type = IndexType.unique)
public class Dir extends BaseEntity {
	private static final long serialVersionUID = -5233564826534911410L;
	@Id
	@KeySql(useGeneratedKeys = true)
	private Long id;
	@Column(nullable = false)
	private String path;
	@ForeignKey(tableEntity = Dir.class, casecadeType = ForeignKey.CascadeType.ALL)
	private Long parentId;
	@ForeignKey(tableEntity = Bucket.class)
	@Column(nullable = false)
	private Long bucketId;
	@Transient
	private Dir child;
	private Boolean isDelete;
	private Date deleteTime;
}
DirService
package mt.spring.mos.server.service;

import lombok.extern.slf4j.Slf4j;
import mt.common.service.BaseServiceImpl;
import mt.common.tkmapper.Filter;
import mt.spring.mos.server.entity.dto.DirUpdateDto;
import mt.spring.mos.server.entity.po.Dir;
import mt.spring.mos.server.entity.po.Resource;
import mt.spring.mos.server.entity.vo.DirDetailInfo;
import mt.utils.common.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.*;

/**
 * @Author Martin
 * @Date 2020/5/20
 */
@Service
@Slf4j
public class DirService extends BaseServiceImpl<Dir> {
	@Autowired
	private BucketService bucketService;
	@Autowired
	private AuditService auditService;
	@Autowired
	@Lazy
	private ResourceService resourceService;
	
	public List<Dir> findAllParentDir(Dir dir) {
		List<Dir> dirs = new ArrayList<>();
		Long parentId = dir.getParentId();
		while (parentId != null) {
			Dir parent = findById(parentId);
			dirs.add(parent);
			parentId = parent.getParentId();
		}
		return dirs;
	}
	
	@Transactional(readOnly = true)
	public Dir findOneByPathAndBucketId(String path, Long bucketId, Boolean isDelete) {
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("path", Filter.Operator.eq, path));
		filters.add(new Filter("bucketId", Filter.Operator.eq, bucketId));
		if (isDelete != null) {
			filters.add(new Filter("isDelete", Filter.Operator.eq, isDelete));
		}
		return findOneByFilters(filters);
	}
	
	@Transactional(readOnly = true)
	public Dir findOneByDirIdAndBucketId(Long dirId, Long bucketId, Boolean isDelete) {
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("id", Filter.Operator.eq, dirId));
		filters.add(new Filter("bucketId", Filter.Operator.eq, bucketId));
		if (isDelete != null) {
			filters.add(new Filter("isDelete", Filter.Operator.eq, isDelete));
		}
		return findOneByFilters(filters);
	}
	
	public String getParentPath(String pathname) {
		if (!pathname.startsWith("/")) {
			pathname = "/" + pathname;
		}
		int lastIndexOf = pathname.lastIndexOf("/");
		String parentPath = pathname.substring(0, lastIndexOf);
		if (StringUtils.isBlank(parentPath)) {
			return "/";
		}
		return parentPath;
	}
	
	@Transactional(rollbackFor = Exception.class)
	public Dir addDir(String path, Long bucketId) {
		bucketService.lockForUpdate(bucketId);
		return addDir0(path, bucketId);
	}
	
	public Dir addDir0(String path, Long bucketId) {
		if (!"/".equals(path) && path.endsWith("/")) {
			path = path.substring(0, path.length() - 1);
		}
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		String finalPath = path;
		
		Dir findDir = findOneByPathAndBucketId(finalPath, bucketId, null);
		if (findDir != null) {
			log.debug("dir[{}]存在", finalPath);
			if (findDir.getIsDelete()) {
				recover(bucketId, findDir.getId(), false, true);
				return findById(findDir.getId());
			} else {
				return findDir;
			}
		}
		log.debug("dir[{}]不存在,进行创建", finalPath);
		Dir parentDir = null;
		if (!"/".equalsIgnoreCase(finalPath)) {
			String parentPath = getParentPath(finalPath);
			parentDir = addDir0(parentPath, bucketId);
		}
		
		Dir dir = new Dir();
		dir.setPath(finalPath);
		dir.setBucketId(bucketId);
		if (parentDir != null) {
			dir.setParentId(parentDir.getId());
		}
		log.debug("创建dir:{}", finalPath);
		save(dir);
		auditService.writeRequestsRecord(bucketId, 1);
		return dir;
	}
	
	@Override
	public Dir findOneByFilters(List<Filter> filters) {
		return super.findOneByFilters(filters);
	}
	
	@Transactional
	public void updatePath(Long bucketId, DirUpdateDto dirUpdateDto) {
		String newPath = dirUpdateDto.getPath();
		Assert.notBlank(newPath, "路径不能为空");
		Assert.state(!newPath.contains(".."), "非法路径:" + newPath);
		if (!newPath.startsWith("/")) {
			newPath = "/" + newPath;
		}
		bucketService.lockForUpdate(bucketId);
		Dir findDir = findOneByPathAndBucketId(newPath, bucketId, null);
		if (findDir != null) {
			if (findDir.getIsDelete()) {
				deleteById(findDir);
			} else {
				throw new IllegalStateException("路径" + newPath + "已存在");
			}
		}
		Dir parentDir = addDir(getParentPath(newPath), bucketId);
		Dir currentDir = findById(dirUpdateDto.getId());
		Assert.state(!"/".equals(currentDir.getPath()), "不能修改根的路径");
		auditService.writeRequestsRecord(bucketId, 1);
		currentDir.setParentId(parentDir.getId());
		currentDir.setPath(newPath);
		updateById(currentDir);
		updateChildDirPath(currentDir);
	}
	
	@Transactional
	public void updateChildDirPath(Dir dir) {
		List<Dir> children = findList("parentId", dir.getId());
		String parentPath = dir.getPath();
		if (CollectionUtils.isNotEmpty(children)) {
			for (Dir child : children) {
				child.setPath(parentPath + child.getName());
				updateById(child);
				updateChildDirPath(child);
			}
		}
	}
	
	private void updateParentDir(Dir dir, Dir parentDir) {
		String path = dir.getPath();
		File file = new File(path);
		String name = file.getName();
		String desPath = parentDir.getPath() + "/" + name;
		dir.setParentId(parentDir.getId());
		dir.setPath(desPath);
		updateById(dir);
		List<Dir> children = findList("parentId", dir.getId());
		if (CollectionUtils.isNotEmpty(children)) {
			for (Dir child : children) {
				updateParentDir(child, dir);
			}
		}
	}
	
	/**
	 * 合并文件夹,同名文件将进行覆盖
	 *
	 * @param bucketId 桶
	 * @param srcId    源路径
	 * @param desId    目标路径
	 */
	@Transactional
	public void mergeDir(Long bucketId, Long srcId, Long desId) {
		Dir srcDir = findOneByDirIdAndBucketId(srcId, bucketId, false);
		Dir desDir = findOneByDirIdAndBucketId(desId, bucketId, false);
		Assert.notNull(srcDir, "源路径不存在");
		Assert.notNull(desDir, "目标路径不存在");
		//把srcDir下的子目录移过去
		List<Dir> children = findList("parentId", srcDir.getId());
		if (CollectionUtils.isNotEmpty(children)) {
			for (Dir child : children) {
				updateParentDir(child, desDir);
			}
		}
		//把srcDir下的文件移过去
		List<Resource> desResources = resourceService.findByFilter(new Filter("dirId", Filter.Operator.eq, desId));
		if (CollectionUtils.isNotEmpty(desResources)) {
			//判断文件是否重名
			for (Resource desResource : desResources) {
				List<Filter> filters = new ArrayList<>();
				filters.add(new Filter("dirId", Filter.Operator.eq, srcId));
				filters.add(new Filter("name", Filter.Operator.eq, desResource.getName()));
				Resource findResource = resourceService.findOneByFilters(filters);
				if (findResource != null) {
					//重名文件存在,删除进行覆盖
					resourceService.deleteById(desResource);
				}
			}
		}
		resourceService.changeDir(srcId, desId);
		//删除原文件夹
		deleteById(srcDir);
	}
	
	@Transactional
	public void deleteDir(Long bucketId, long dirId) {
		bucketService.lockForUpdate(bucketId);
		Dir dir = findOneByDirIdAndBucketId(dirId, bucketId, false);
		if (dir == null) {
			return;
		}
		dir.setIsDelete(true);
		dir.setDeleteTime(new Date());
		updateById(dir);
		List<Resource> resources = resourceService.findResourcesInDir(dirId);
		if (CollectionUtils.isNotEmpty(resources)) {
			for (Resource resource : resources) {
				resourceService.deleteResource(bucketId, resource.getId());
			}
		}
		List<Dir> children = findChildren(dirId);
		if (CollectionUtils.isNotEmpty(children)) {
			for (Dir child : children) {
				deleteDir(bucketId, child.getId());
			}
		}
	}
	
	@Transactional
	public void recover(Long bucketId, Long dirId, boolean recoverChildren, boolean recoverParent) {
		bucketService.lockForUpdate(bucketId);
		Dir dir = findOneByDirIdAndBucketId(dirId, bucketId, true);
		if (dir == null) {
			return;
		}
		dir.setIsDelete(false);
		dir.setDeleteTime(null);
		updateById(dir);
		if (recoverChildren) {
			List<Resource> resources = resourceService.findResourcesInDir(dirId);
			if (CollectionUtils.isNotEmpty(resources)) {
				for (Resource resource : resources) {
					resourceService.recover(bucketId, resource.getId(), false);
				}
			}
			List<Dir> children = findChildren(dirId);
			if (CollectionUtils.isNotEmpty(children)) {
				for (Dir child : children) {
					recover(bucketId, child.getId(), true, false);
				}
			}
		}
		Long parentId = dir.getParentId();
		if (recoverParent && parentId != null) {
			recover(bucketId, parentId, false, true);
		}
	}
	
	public List<Dir> findChildren(long dirId) {
		return findList("parentId", dirId);
	}
	
	
	@Transactional
	public void realDeleteDir(Long bucketId, long dirId) {
		bucketService.lockForUpdate(bucketId);
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("id", Filter.Operator.eq, dirId));
		filters.add(new Filter("bucketId", Filter.Operator.eq, bucketId));
		Dir dir = findOneByFilters(filters);
		org.springframework.util.Assert.notNull(dir, "路径不存在");
		auditService.writeRequestsRecord(bucketId, 1);
		deleteById(dir);
	}
	
	@Transactional(rollbackFor = Exception.class)
	public boolean realDeleteDir(Long bucketId, String path) {
		org.springframework.util.Assert.state(StringUtils.isNotBlank(path), "路径不能为空");
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("path", Filter.Operator.eq, path));
		filters.add(new Filter("bucketId", Filter.Operator.eq, bucketId));
		Dir dir = findOneByFilters(filters);
		if (dir != null) {
			realDeleteDir(bucketId, dir.getId());
			return true;
		}
		return false;
	}
	
	@Transactional
	public List<Dir> getRealDeleteDirsBefore(Integer beforeDays) {
		Calendar instance = Calendar.getInstance();
		instance.add(Calendar.DAY_OF_MONTH, -Math.abs(beforeDays));
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("isDelete", Filter.Operator.eq, true));
		filters.add(new Filter("deleteTime", Filter.Operator.le, instance.getTime()));
		return findByFilters(filters);
	}
	
	public DirDetailInfo findDetailInfo(@NotNull Long id, int thumbCount) {
		List<Resource> thumbs = resourceService.findDirThumbs(id, thumbCount);
		DirDetailInfo dirDetailInfo = new DirDetailInfo();
		dirDetailInfo.setThumbs(thumbs);
		dirDetailInfo.setDirCount((long) count(Collections.singletonList(new Filter("parentId", Filter.Operator.eq, id))));
		dirDetailInfo.setFileCount((long) resourceService.count(Collections.singletonList(new Filter("dirId", Filter.Operator.eq, id))));
		return dirDetailInfo;
	}
}

Controller
/**
 * @Author Martin
 * @Date 2020/12/5
 */
@RestController
@RequestMapping("/member/dir")
public class DirController {
	
	@Autowired
	private DirService dirService;
	@Autowired
	private BucketService bucketService;
	
	@GetMapping("/{bucketName}/detailInfo/{id}")
	@ApiOperation("获取文件夹详细信息")
	@NeedPerm(perms = BucketPerm.SELECT)
	public DirDetailInfo detailInfo(@PathVariable String bucketName, @ApiIgnore Bucket bucket,
									@PathVariable Long id,
									@RequestParam(defaultValue = "3") Integer thumbCount) {
		Assert.state(thumbCount > 0 && thumbCount <= 100, "thumbCount只能是0-10");
		return dirService.findDetailInfo(id, thumbCount);
	}
	
	@GetMapping("/{bucketName}/select")
	@NeedPerm(BucketPerm.SELECT)
	@ApiOperation("模糊查找")
	public ResResult selectByPath(@RequestParam(required = false, defaultValue = "30") Integer pageSize, @PathVariable String bucketName, @ApiIgnore @CurrentUser User currentUser, String path) {
		Bucket bucket = bucketService.findBucketByUserIdAndBucketName(currentUser.getId(), bucketName);
		Assert.notNull(bucket, "不存在bucket:" + bucketName);
		if (path == null) {
			path = "/";
		}
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		PageHelper.startPage(1, pageSize, "(length(path) - length(replace(path,'/',''))) asc");
		List<Filter> filters = new ArrayList<>();
		filters.add(new Filter("bucketId", Filter.Operator.eq, bucket.getId()));
		filters.add(new Filter("path", Filter.Operator.like, '%' + path + '%'));
		return ResResult.success(dirService.findByFilters(filters));
	}
	
	@GetMapping("/{bucketName}/findByPath")
	@NeedPerm(BucketPerm.SELECT)
	@ApiOperation("精确查找")
	public ResResult findByPath(@ApiIgnore @CurrentUser User currentUser, @PathVariable String bucketName, String path) {
		Bucket bucket = bucketService.findBucketByUserIdAndBucketName(currentUser.getId(), bucketName);
		Assert.notNull(bucket, "不存在bucket:" + bucketName);
		Dir dir = dirService.findOneByPathAndBucketId(path, bucket.getId(), false);
		return ResResult.success(dir);
	}
	
	@PutMapping("/{bucketName}/{id}")
	@NeedPerm(BucketPerm.UPDATE)
	@ApiOperation("修改")
	public ResResult update(@ApiIgnore @CurrentUser User currentUser, @PathVariable String bucketName, @PathVariable Long id, @RequestBody DirUpdateDto dirUpdateDto) {
		Bucket bucket = bucketService.findBucketByUserIdAndBucketName(currentUser.getId(), bucketName);
		Assert.notNull(bucket, "不存在bucket:" + bucketName);
		dirUpdateDto.setBucketName(bucketName);
		dirUpdateDto.setId(id);
		dirService.updatePath(bucket.getId(), dirUpdateDto);
		return ResResult.success();
	}
	
	@PutMapping("/{bucketName}/merge/{srcId}/to/{desId}")
	@NeedPerm(BucketPerm.UPDATE)
	@ApiOperation("合并")
	public ResResult merge(@ApiIgnore @CurrentUser User currentUser, @PathVariable String bucketName, @PathVariable Long srcId, @PathVariable Long desId) {
		Bucket bucket = bucketService.findBucketByUserIdAndBucketName(currentUser.getId(), bucketName);
		Assert.notNull(bucket, "不存在bucket:" + bucketName);
		dirService.mergeDir(bucket.getId(), srcId, desId);
		return ResResult.success();
	}
	
	
	@PostMapping("/{bucketName}")
	@NeedPerm(BucketPerm.INSERT)
	@ApiOperation("新增")
	public ResResult add(@ApiIgnore @CurrentUser User currentUser, @PathVariable String bucketName, @RequestBody DirAddDto dirAddDto) {
		Bucket bucket = bucketService.findBucketByUserIdAndBucketName(currentUser.getId(), bucketName);
		Assert.notNull(bucket, "不存在bucket:" + bucketName);
		dirService.addDir(dirAddDto.getPath(), bucket.getId());
		return ResResult.success();
	}
}
查询条件DTO的定义

这个例子跟上面的dir无关。

/**
 * @Author Martin
 * @Date 2022/10/31
 */
@Data
public class ResourceLogCondition {
	@Filter
	private Long userId;
	@Filter
	private ResourceType resourceType;
	@Filter(operator = mt.common.tkmapper.Filter.Operator.in)
	private List<Long> resourceId;
	@Filter
	private LogType logType;
}

这个例子跟上面的dir无关。
调用baseService的findPage方法进行分页查询

@GetMapping("/list")
	public PageInfo<ResourceLog> list(@ApiIgnore @CurrentUserId Long userId,
									  Integer pageNum,
									  Integer pageSize,
									  ResourceLogCondition condition
	) {
		condition.setUserId(userId);
		return resourceLogService.findPage(pageNum, pageSize, "id desc", condition);
	}
Vo字段填充
/**
 * @Author Martin
 * @Date 2022/10/18
 */
@Data
public class VideoVo implements Serializable {
	
	private static final long serialVersionUID = -61658698405813771L;
	
	private Long id;
	private String name;
	private String videoLength;
	private String pathnamePrefix;
	/**
	 * 缩略图
	 */
	@Message(params = {"#thumbPicPathname", "#pathnamePrefix"}, handlerClass = StorageUrlMessageHandler.class)
	private String thumbPicPathname;
	@Message(params = {"#previewVideoPathname", "#pathnamePrefix"}, handlerClass = StorageUrlMessageHandler.class)
	private String previewVideoPathname;
	/**
	 * 实际发布日期
	 */
	private Date publishedDate;
	/**
	 * 上传用户
	 */
	private Long uploadedUserId;
	/**
	 * 价格
	 */
	private Long price;
	/**
	 * 分类
	 */
	private String category;
	
	/**
	 * 点击量
	 */
	private Long hits;
	/**
	 * 点赞量
	 */
	private Long likes;
	private Long notLikes;
	
	/**
	 * 文件大小
	 */
	private Long fileSize;
	/**
	 * 比特率
	 */
	private Integer bitRate;
	/**
	 * 是否原创
	 */
	private Boolean isOriginal;
	
	@Message(params = "#fileSize", handlerClass = ReadableFileSizeMessageHandler.class)
	private String readableFileSize;
	
	@Message(params = "#bitRate", handlerClass = IsHighDefinitionMessageHandler.class)
	private Boolean isHd;
	@BatchMessage(column = "uploadedUserId", handlerClass = UserVoBatchMessageHandler.class)
	private UserVo uploadedUser;
	@BatchMessage(column = "id", params = "video", handlerClass = IsLikeBatchMessageHandler.class)
	private Boolean isLike;
	private Long rankScore;
	private Set<String> tags;
}

UserVoBatchMessageHandler:

/**
 * @Author Martin
 * @Date 2022/10/19
 */
@Component
public class UserVoBatchMessageHandler implements BatchMessageHandler<Long, UserVo> {
	@Autowired
	private UserService userService;
	
	@Override
	public Map<Long, UserVo> handle(Collection<?> list, Set<Long> userIds, String[] params) {
		Map<Long, UserVo> map = new HashMap<>(16);
		if (CollectionUtils.isNotEmpty(userIds)) {
			List<User> users = userService.findByFilter(new Filter("id", Filter.Operator.in, userIds));
			users.stream().map(user -> BeanUtils.transform(UserVo.class, user)).forEach(userVo -> {
				map.put(userVo.getId(), userVo);
			});
		}
		return map;
	}
}

ReadableFileSizeMessageHandler:

/**
 * @Author Martin
 * @Date 2022/10/18
 */
@Component
public class ReadableFileSizeMessageHandler implements MessageHandler<Object, String> {
	@Override
	public String handle(Object o, Object[] params, String mark) {
		Long fileSize = getParam(params, 0, Long.class);
		if (fileSize != null) {
			return FileSizeUtils.getReadableSize(fileSize, "#");
		}
		return null;
	}
}

总结

还有列举的其它包的用法,就不挨个解释了,详细的用法可以结合实际项目看我的github。

  • 框架项目:https://github.com/668mt/mt-spring-web.git
  • 对象存储MOS:https://github.com/668mt/mos.git
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值