List<实体类>多属性去重
list = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(o -> o.getProjectId() + ";" + o.getUserId()))
), ArrayList::new
)
);
List集合根据对象某个属性去重
designQualifications.stream()
.filter(distinctByKey(DesignQualification::getNameCode))
.collect(Collectors.toList());
private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
List按某个String字段(可转double)排序
arrayList = arrayList.stream()
.sorted(Comparator.comparing(c -> Double.valueOf(c.getTaxPoints())))
.collect(Collectors.toList());
Collections.reverse(arrayList);
List根据某日期属性分组
public R<Map<String,List<Schedule>>> findListByDate(Schedule schedule) {
List<Schedule> list = scheduleService.list(Condition.getQueryWrapper(schedule));
for (Schedule scheduleTemp : list) {
scheduleTemp.setFormatScheduleDate(DateUtil.format(scheduleTemp.getScheduleDate(), "yyyy-MM-dd"));
}
Map<String,List<Schedule>> resultList = list.stream().collect(Collectors.groupingBy(Schedule::getFormatScheduleDate));
return R.data(resultList);
}
List2Tree
public static List<Person> listToTree(List<Person> list) {
Map<String, List<Person>> parentIdMap = list.stream().collect(Collectors.groupingBy(Person::getParentId));
list.forEach(p -> p.setChildList(parentIdMap.get(p.getId())));
return list.stream().filter(p -> p.getParentId().equals("0")).collect(Collectors.toList());
}
相差月份
String text1 = "2020-08-02";
Temporal temporal1 = LocalDate.parse(text1);
String text2 = "2020-09-01";
Temporal temporal2 = LocalDate.parse(text2);
// 方法返回为相差月份
long l = ChronoUnit.MONTHS.between(temporal1, temporal2);
System.out.println(l);
Stream分页
List<User> list = new ArrayList<>();
List<User> subList = list.stream().skip((pageNo - 1) * pageSize).limit(pageSize).
collect(Collectors.toList());
树状结构根据id递归查询子集
SELECT
t3.*
FROM (
SELECT
t1.*,
t2.*,
IF(FIND_IN_SET(parent_id, @pids) > 0, @pids := CONCAT(@pids, ',', id), '0') AS isChild
FROM (
SELECT * FROM admin_proeducontent_category ORDER BY parent_id,id
) AS t1,
( SELECT @pids := 'xxxxxxxxxxxxxx') AS t2
) t3
WHERE t3.isChild != '0'
如果mybatis报错则给mapper接口方法添加注解,@SqlParser(filter = true)
自定义排序上下移
<select id="getDownOne" resultMap="BaseResultMap">
SELECT * from oa_publish_train_course WHERE
( `sort` > #{originSort} OR `sort`=(SELECT MAX(`sort`) FROM oa_publish_train_course where publish_train_id = #{publishTrainId}))
AND publish_train_id = #{publishTrainId}
AND is_deleted = 0
ORDER BY `sort` ASC limit 1
</select>
<select id="getUpOne" resultMap="BaseResultMap">
SELECT * from oa_publish_train_course WHERE
( `sort` < #{originSort} OR `sort`=(SELECT MIN(`sort`) FROM oa_publish_train_course where publish_train_id = #{publishTrainId}))
AND publish_train_id = #{publishTrainId}
AND is_deleted = 0
ORDER BY `sort` DESC limit 1
</select>
@Override
@Transactional
public void moveUp(OaPublishTrainCourse request) {
try {
//获取原课程
OaPublishTrainCourse origin = this.baseMapper.selectById(request.getId());
Long originSort = origin.getSort();
//获取原课程的上一个课程
OaPublishTrainCourse up = this.baseMapper.getUpOne(originSort, origin.getPublishTrainId());
Long upSort = up.getSort();
//如果是同一个就不用改动位置
if(up.getId() == origin.getId())
return;
//不然就是替换两个sort
OaPublishTrainCourse originUpdate = new OaPublishTrainCourse();
originUpdate.setId(origin.getId());
originUpdate.setSort(upSort);
this.baseMapper.updateById(originUpdate);
OaPublishTrainCourse upUpdate = new OaPublishTrainCourse();
upUpdate.setId(up.getId());
upUpdate.setSort(originSort);
this.baseMapper.updateById(upUpdate);
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(DesignResultCode.ERR_DATA_OPER_ERROR);
}
}
@Override
@Transactional
public void moveDown(OaPublishTrainCourse request) {
try {
//获取原课程
OaPublishTrainCourse origin = this.baseMapper.selectById(request.getId());
Long originSort = origin.getSort();
//获取原课程的下一个课程
OaPublishTrainCourse down = this.baseMapper.getDownOne(originSort, origin.getPublishTrainId());
Long downSort = down.getSort();
//如果是同一个就不用改动位置
if(down.getId() == origin.getId())
return;
//不然就是替换两个sort
OaPublishTrainCourse originUpdate = new OaPublishTrainCourse();
originUpdate.setId(origin.getId());
originUpdate.setSort(downSort);
this.baseMapper.updateById(originUpdate);
OaPublishTrainCourse upUpdate = new OaPublishTrainCourse();
upUpdate.setId(down.getId());
upUpdate.setSort(originSort);
this.baseMapper.updateById(upUpdate);
} catch (NullPointerException e) {
throw new ServiceException(DesignResultCode.ERR_DATA_OPER_ERROR);
}
}
add时执行baseMapper.updateAddOne();
@Update("update oa_publish_train_course set `sort` = (`sort` + 1)")
int updateAddOne();
远程调用模型
远程调用 blade-resource模块 OssEndpoint类 /put-file接口
OaReserveTeam oaReserveTeam = ossClient.getTeam().getData();
=============
blade-resource-api模块 IOssClient接口
@FeignClient(value = "blade-customer", fallback = IOssFallback.class)
public interface IOssClient {
String API_PREFIX = "/reserveTeam";
String GET_TEAM = API_PREFIX + "/getTeam";
@ApiOperation(value="获取团队")
@GetMapping(GET_TEAM)
public R<OaReserveTeam> getTeam();
}
=============
blade-resource-api模块 IOssFallback类
@Component
public class IOssFallback implements IOssClient {
@Override
public R<OaReserveTeam> getTeam() {
return R.fail("客户端获取团队时远程调用失败");
}
}
=============
blade-customer模块 ReserveTeamController类
@GetMapping("/getTeam")
@ApiOperation("获取客户团队")
public R<OaReserveTeam> getTeam(){
OaReserveTeam oaReserveTeam = oaReserveTeamMapper
.selectOne(new LambdaQueryWrapper<OaReserveTeam>()
.eq(OaReserveTeam::getDeptId,AuthUtils.getDeptIdForCustomer()));
return R.data(oaReserveTeam);
}
邮箱验证码
/***
* 获取邮箱验证码
* @param sendTo
* @return 实体对象
*/
@ApiOperation(value="获取邮箱验证码", notes="获取邮箱验证码")
@ApiImplicitParam(name = "sendTo", value = "邮箱地址", required = true, dataType = "String", paramType = "query")
@GetMapping("/getEmailVerificationCode")
public R<?> getEmailVerificationCode(String sendTo){
StEmailList stEmailList = new StEmailList();
stEmailList.setSender("");
stEmailList.setSendTo(sendTo);
stEmailList.setPriority(10);
stEmailList.setCreatedOn(LocalDateTime.now());
stEmailList.setIsSend(0);
stEmailList.setSendTimes(0);
//查询模板写入内容
StTemplateBase stTemplate = stTemplateService.getOne(new QueryWrapper<StTemplateBase>().eq("template_key", "company_bind_email"));
stEmailList.setSubject(stTemplate.getName());
stEmailList.setMsgType(stTemplate.getType());
//生成邮箱验证码
String verificationCode = RandomUtil.getRandom();
stEmailList.setMsg(stTemplate.getContent().replace("${VerifyCode-company-email}",verificationCode));
stEmailListService.save(stEmailList);
//存入redis 设置过期时间5分钟
RedisUtil.redisService.add(Setting.COMPANY_BIND_EMAIL_KEY + sendTo, verificationCode, 5, TimeUnit.MINUTES);
return R.data("发送成功!");
}
邮箱服务5s轮询邮件列表中未发送的邮件执行发送
List<StEmailList> stEmailLists = stEmailListMapper.selectList(new QueryWrapper<StEmailList>().eq("is_send", 0).lt("send_times", 5).orderByDesc("priority"));
if (stEmailLists.size() == 0) {
return;
}
for (StEmailList item : stEmailLists) {
StEmailList newItem = new StEmailList();
newItem.setId(item.getId());
try {
//发送邮件
mailService.sendHtmlMail(item.getSendTo(), item.getSubject(), item.getMsg());
//发送成功
newItem.setIsSend(1);
newItem.setResult("true");
} catch (Exception e) {
e.printStackTrace();
logger.error("邮箱发送失败", e);
//发送失败
newItem.setIsSend(0);
newItem.setResult("false");
}
//更新
newItem.setSendTimes(item.getSendTimes() + 1);
newItem.setSendOn(LocalDateTime.now());
stEmailListMapper.updateById(newItem);
}
public void sendHtmlMail(String to,String subject,String content) throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content,true);
mailSender.send(mimeMessage);
}
下载文件
@GetMapping(value = "/downCert", produces = "application/octet-stream")
@ApiOperation(value = "下载", notes = "下载")
public void downCert(Long id, HttpServletResponse response) throws IOException {
// 获取
PaCertificateBase cert = service.getById(id);
Long fileId = cert.getFileId();
if (fileId != null) {
StFiles certFile = filesService.getById(fileId);
FileUtil.downloadFile(response, "证书文件_" + DateUtil.format(new Date(), "yyyyMMdd") + ".pdf", certFile.getFileUrl());
}
}
/**
* 下载本地文件
* @param response
* @param name
* @param filePath
*/
public static void downloadFile(HttpServletResponse response, String name, String filePath) throws IOException {
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(name, "UTF-8"));
response.setContentType("multipart/form-data");
InputStream in = getInputStreamFromUrl(filePath); //获取下载文件的输入流
int count = 0;
byte[] by = new byte[1024];
//通过response对象获取OutputStream流
OutputStream out = response.getOutputStream();
while((count = in.read(by)) != -1) {
out.write(by, 0, count);//将缓冲区的数据输出到浏览器
}
in.close();
out.flush();
out.close();
}
/**
* 通过网络地址获取文件InputStream
*
* @param fileUrl 文件下载链接
* @return
*/
private static InputStream getInputStreamFromUrl(String fileUrl) {
URL url = null;
InputStream is = null;
try {
url = new URL(fileUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
is = conn.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
DOC模板生成下载
/**
* 生成数据存证打印模板
*/
@ApiOperation(value="生成数据存证打印模板")
@GetMapping(value = "/exportPrintTemplate", produces = "application/octet-stream")
public void exportPrintTemplate(String id, HttpServletResponse response) throws Exception {
// 渲染数据
Map<String, String> params = service.queryApplicationData(id);
ClassPathResource classPathResource = new ClassPathResource("数据存证打印模板.docx");
InputStream inputStream = classPathResource.getInputStream();
response.setContentType("multipart/form-data");
response.addHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode("数据存证打印模板", "UTF-8")
+ "_" + DateUtil.formatDate(new Date(), "yyyyMMdd") + ".docx");
OutputStream out = response.getOutputStream();
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(params);
template.writeAndClose(out);
}
EasyPOI/POI版本
<!--easypoi 导出excel依赖-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.2.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
滑动验证码
<!-- AJ-Captcha -->
<dependency>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId>
<version>1.2.7</version>
</dependency>
OR
<dependency>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha</artifactId>
<version>1.2.7</version>
</dependency>
/**
* 获取滑动验证码
* @param data
* @param request
* @return
*/
@PostMapping("/captcha/get")
public ResponseModel captchaGet(@RequestBody CaptchaVO data, HttpServletRequest request) {
return captchaController.get(data, request);
}
/**
* 检查滑动验证码(do something)
* @param data
* @param request
* @return
*/
@PostMapping("/captcha/check")
public ResponseModel captchaCheck(@RequestBody CaptchaVO data, HttpServletRequest request) {
ResponseModel check = captchaController.check(data, request);
return check;
}
//repCode 0000 无异常,代表成功
//repCode 9999 服务器内部异常
//repCode 0011 参数不能为空
//repCode 6110 验证码已失效,请重新获取
//repCode 6111 验证失败
//repCode 6112 获取验证码失败,请联系管理员
aj:
captcha:
aes-status: false
water-mark: