Compare commits

...

10 Commits

571 changed files with 4651 additions and 27460 deletions

3
.gitignore vendored
View File

@ -3,7 +3,8 @@ target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
**/src/main/resources/static/keyPair/*
**/src/main/resources/static/keypair/*
**/logs/*
### STS ###
.apt_generated

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<version>1.1.2</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Api</artifactId>

View File

@ -1,6 +1,6 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudBrandDto;
import com.cpop.core.base.exception.UtilException;

View File

@ -1,10 +1,10 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudClassCardDto;
import com.cpop.api.cloudDb.core.dto.CloudClassCardRecordDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.entity.ExtendPage;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.exception.UtilException;
@ -50,17 +50,17 @@ public class CloudClassCardHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(customerId)) {
if (StrUtil.isNotBlank(customerId)) {
jsonBody.put("customerId", customerId);
}
if (StringUtils.isNotBlank(cardId)) {
if (StrUtil.isNotBlank(cardId)) {
jsonBody.put("cardId", cardId);
}
if (StringUtils.isNotBlank(cardType)) {
if (StrUtil.isNotBlank(cardType)) {
jsonBody.put("cardType", cardType);
}
if (cardStatus != null) {
@ -111,14 +111,14 @@ public class CloudClassCardHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(customerId)) {
if (StrUtil.isNotBlank(customerId)) {
jsonBody.put("customerId", customerId);
}
if (StringUtils.isNotBlank(cardId)) {
if (StrUtil.isNotBlank(cardId)) {
jsonBody.put("cardId", cardId);
}
//校区id

View File

@ -1,11 +1,10 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudClassDto;
import com.cpop.api.cloudDb.core.dto.CloudClassStudentDto;
import com.cpop.api.cloudDb.core.dto.CloudCourseDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import org.springframework.beans.factory.annotation.Autowired;
@ -45,11 +44,11 @@ public class CloudClassHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(classId)){
if (StrUtil.isNotBlank(classId)){
jsonBody.put("classId", classId);
}
//校区id
@ -90,11 +89,11 @@ public class CloudClassHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(classId)){
if (StrUtil.isNotBlank(classId)){
jsonBody.put("classId", classId);
}
//校区id

View File

@ -1,10 +1,10 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudCourseDto;
import com.cpop.api.cloudDb.core.dto.CloudCourseStudentListDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import lombok.extern.slf4j.Slf4j;
@ -12,7 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
/**
@ -48,14 +47,14 @@ public class CloudCourseHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(courseId)){
if (StrUtil.isNotBlank(courseId)){
jsonBody.put("courseId", courseId);
}
if (StringUtils.isNotBlank(classId)) {
if (StrUtil.isNotBlank(classId)) {
jsonBody.put("classId", classId);
}
//校区id
@ -95,23 +94,23 @@ public class CloudCourseHandler {
JSONObject jsonBody = new JSONObject();
jsonBody.put("_type", "courseStudent");
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(courseId)){
if (StrUtil.isNotBlank(courseId)){
jsonBody.put("courseId", courseId);
}
if (StringUtils.isNotBlank(customerId)){
if (StrUtil.isNotBlank(customerId)){
jsonBody.put("customerId", customerId);
}
if (StringUtils.isNotBlank(studentId)){
if (StrUtil.isNotBlank(studentId)){
jsonBody.put("studentId", studentId);
}
if (StringUtils.isNotBlank(cardId)){
if (StrUtil.isNotBlank(cardId)){
jsonBody.put("cardId", cardId);
}
if (StringUtils.isNotBlank(classId)){
if (StrUtil.isNotBlank(classId)){
jsonBody.put("classId", classId);
}
//校区id

View File

@ -1,10 +1,10 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudCustomerDto;
import com.cpop.api.cloudDb.core.dto.CloudStudentDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import lombok.extern.slf4j.Slf4j;
@ -46,11 +46,11 @@ public class CloudCustomerStudentHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(customerId)){
if (StrUtil.isNotBlank(customerId)){
jsonBody.put("customerId", customerId);
}
//校区id
@ -92,14 +92,14 @@ public class CloudCustomerStudentHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(customerId)) {
if (StrUtil.isNotBlank(customerId)) {
jsonBody.put("customerId", customerId);
}
if (StringUtils.isNotBlank(studentId)) {
if (StrUtil.isNotBlank(studentId)) {
jsonBody.put("studentId", studentId);
}
//校区id

View File

@ -1,9 +1,9 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudOrderDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.entity.ExtendPage;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
@ -48,17 +48,17 @@ public class CloudOrderHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(customerId)) {
if (StrUtil.isNotBlank(customerId)) {
jsonBody.put("customerId", customerId);
}
if (StringUtils.isNotBlank(cardId)) {
if (StrUtil.isNotBlank(cardId)) {
jsonBody.put("cardId", cardId);
}
if (StringUtils.isNotBlank(orderId)) {
if (StrUtil.isNotBlank(orderId)) {
jsonBody.put("ticketId", orderId);
}
//校区id

View File

@ -1,9 +1,9 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudStaffDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import org.springframework.beans.factory.annotation.Autowired;
@ -43,11 +43,11 @@ public class CloudStaffHandler {
jsonBody.put("page", pageNum);
jsonBody.put("limit", pageSize);
//开始日期结束日期
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
jsonBody.put("startTime", startDate);
jsonBody.put("endTime", endDate);
}
if (StringUtils.isNotBlank(staffId)){
if (StrUtil.isNotBlank(staffId)){
jsonBody.put("staffId", staffId);
}
//校区id

View File

@ -1,10 +1,10 @@
package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudStoreActiveDto;
import com.cpop.api.cloudDb.core.dto.CloudStoreDto;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -35,19 +35,19 @@ public class CloudStoreHandler {
jsonBody.put("_type", "storeEdit");
//云校区id
jsonBody.put("storeId", dto.getStoreCloudId());
if (StringUtils.isNotBlank(dto.getBrandCloudId())) {
if (StrUtil.isNotBlank(dto.getBrandCloudId())) {
jsonBody.put("brandId", dto.getBrandCloudId());
}
if (StringUtils.isNotBlank(dto.getStoreName())) {
if (StrUtil.isNotBlank(dto.getStoreName())) {
jsonBody.put("name", dto.getStoreName());
}
if (StringUtils.isNotBlank(dto.getPersonCharge())) {
if (StrUtil.isNotBlank(dto.getPersonCharge())) {
jsonBody.put("principalName", dto.getPersonCharge());
}
if (StringUtils.isNotBlank(dto.getPhone())) {
if (StrUtil.isNotBlank(dto.getPhone())) {
jsonBody.put("phone", dto.getPhone());
}
if (StringUtils.isNotBlank(dto.getStoreAddr())) {
if (StrUtil.isNotBlank(dto.getStoreAddr())) {
jsonBody.put("address", dto.getStoreAddr());
}
JSONObject jsonObject = restTemplate.postForObject(CloudDbUrl.COMMON_USE_URL, jsonBody, JSONObject.class);

View File

@ -1,13 +1,11 @@
package com.cpop.api.tencent.location.handler;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.tencent.location.core.constant.TencentApiUrl;
import com.cpop.core.utils.SpringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
/**
* 腾讯位置服务工具类
* @author DB

View File

@ -1,6 +1,6 @@
package com.cpop.api.tencent.wxWork.core.base;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**

View File

@ -1,10 +1,10 @@
package com.cpop.api.tencent.wxWork.handler;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.api.tencent.wxWork.core.config.WxWorkApiConfig;
import com.cpop.api.tencent.wxWork.webHook.WebHookSendTextRequest;
import com.cpop.core.utils.http.HttpUtils;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -39,9 +39,8 @@ public class WebHookSendHandler {
text.setContent(content);
text.setMentionedMobileList(phoneList);
request.setText(text);
Response response = HttpUtils.sendOkHttpPost(config.getWebhook() + key, JSONObject.toJSONString(request));
HttpResponse response = HttpRequest.post(config.getWebhook() + key).body(JSONObject.toJSONString(request)).execute();
response.close();
}
}

View File

@ -1,6 +1,6 @@
package com.cpop.api.tencent.wxWork.webHook;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONField;
import com.cpop.api.tencent.wxWork.core.base.WxWorkApiWebHookSendBase;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<version>1.1.2</version>
</parent>
<artifactId>Cpop-ClockIn-Demo</artifactId>

View File

@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.cpop.clockin.business.dto.StaffClassesDto;
import com.cpop.clockin.business.entity.*;
import com.cpop.clockin.business.mapper.ClockInStaffMapper;
import com.cpop.clockin.business.mapper.StaffClassesMapper;
import com.cpop.clockin.business.service.*;
import com.cpop.clockin.business.vo.ClassesVo;
import com.cpop.clockin.business.vo.StaffClassesVo;
@ -12,7 +13,6 @@ import com.cpop.core.utils.SqlUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.clockin.business.mapper.StaffClassesMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -143,7 +143,7 @@ public class StaffClassesServiceImpl extends ServiceImpl<StaffClassesMapper, Sta
Db.paginate("cp_oam_staff",pageAs(pageDomain.getPageSize(),pageDomain.getPageSize()),
QueryWrapper.create(),)*/
Page<ClockInStaff> clockInStaffPage = clockInStaffMapper.paginate(pageDomain.getPageNum(), pageDomain.getPageSize(), QueryWrapper.create().like("name",staffName));
Page<ClockInStaff> clockInStaffPage = clockInStaffMapper.paginate(pageDomain.getPage(), pageDomain.getPageSize(), QueryWrapper.create().like("name",staffName));
List<StaffClassesVo> staffClassesVoList = clockInStaffPage.getRecords().stream().map(entity -> {
StaffClassesVo vo = new StaffClassesVo();
vo.setStaffName(entity.getName());
@ -177,7 +177,7 @@ public class StaffClassesServiceImpl extends ServiceImpl<StaffClassesMapper, Sta
}).collect(Collectors.toList());
Page<StaffClassesVo> staffClassesVoPage = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
Page<StaffClassesVo> staffClassesVoPage = new Page<>(pageDomain.getPage(), pageDomain.getPageSize());
staffClassesVoPage.setRecords(staffClassesVoList);
staffClassesVoPage.setTotalRow(clockInStaffPage.getTotalRow());
staffClassesVoPage.setTotalPage(clockInStaffPage.getTotalPage());

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<version>1.1.2</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Core</artifactId>
@ -67,36 +67,16 @@
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/commons-io/commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!--easyExcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- okhttp3 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<!--quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -122,6 +102,16 @@
<groupId>com.gitee.anwena</groupId>
<artifactId>mongo-plus-boot-starter</artifactId>
</dependency>
<!--hutool工具-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--谷歌拓展集合类-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -1,9 +1,9 @@
package com.cpop.core.aspect;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.utils.RsaUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.config.CpopConfig;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
@ -34,7 +34,7 @@ import java.util.stream.Collectors;
public class SignatureCheckAspect {
@Autowired
private RsaUtils rsaUtils;
private CpopConfig cpopConfig;
private static final Map<String, String[]> APP_IDS = new HashMap<String, String[]>() {{
//数币
@ -67,11 +67,11 @@ public class SignatureCheckAspect {
String appId = null;
for (Field field : fatherFields) {
field.setAccessible(true);
if (StringUtils.equals("signature", field.getName())) {
if (StrUtil.equals("signature", field.getName())) {
signature = (String) field.get(object);
continue;
}
if (StringUtils.equals("appId", field.getName())) {
if (StrUtil.equals("appId", field.getName())) {
String[] strings = APP_IDS.get((String) field.get(object));
if (null == strings){
throw new ServiceException("appId匹配失败,请核实appId");
@ -99,7 +99,7 @@ public class SignatureCheckAspect {
//按照字母排序
String sign = signString.stream().sorted().collect(Collectors.joining("&")) + appId;
String md5DigestAsHex = DigestUtils.md5DigestAsHex(sign.getBytes());
if (!StringUtils.equals(md5DigestAsHex,signature)){
if (!StrUtil.equals(md5DigestAsHex,signature)){
throw new ServiceException("签名匹配失败,请核实签名");
}
}

View File

@ -1,9 +1,12 @@
package com.cpop.core.aspect;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.utils.RsaUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.config.CpopConfig;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
@ -35,7 +38,7 @@ import java.util.Map;
public class SimpleSignatureCheckAspect {
@Autowired
private RsaUtils rsaUtils;
private CpopConfig cpopConfig;
private static final Map<String, String[]> APP_IDS = new HashMap<String, String[]>() {{
//果酱内部
@ -62,21 +65,22 @@ public class SimpleSignatureCheckAspect {
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
assert request != null;
String signature = request.getHeader("signature");
if (StringUtils.isBlank(signature)){
if (StrUtil.isBlank(signature)){
throw new ServiceException("签名为空,请核实签名");
}
String appId = request.getHeader("appId");
if (StringUtils.isBlank(appId)){
if (StrUtil.isBlank(appId)){
throw new ServiceException("appId为空,请核实签名");
}
String dateTime = request.getHeader("dateTime");
if (StringUtils.isBlank(dateTime)){
if (StrUtil.isBlank(dateTime)){
throw new ServiceException("时间为空,请核实签名");
}
String decrypt = rsaUtils.decrypt(signature, stringToKey(APP_IDS.get(appId)[1]));
RSA rsa = SecureUtil.rsa(APP_IDS.get(appId)[1], null);
String decrypt = rsa.decryptStr(signature, KeyType.PrivateKey);
String sign = appId + dateTime;
String md5DigestAsHex = DigestUtils.md5DigestAsHex(sign.getBytes());
if (!StringUtils.equals(md5DigestAsHex, decrypt)) {
if (!StrUtil.equals(md5DigestAsHex, decrypt)) {
throw new ServiceException("签名匹配失败,请核实签名");
}
}

View File

@ -1,7 +1,5 @@
package com.cpop.core.base.entity;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.fasterxml.jackson.databind.JavaType;
@ -11,7 +9,6 @@ import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**

View File

@ -1,13 +1,16 @@
package com.cpop.core.base.entity;
import com.cpop.core.utils.StringUtils;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
/**
* 分页数据
*
* @author DB
* @version 1.0.0
* @since 2024/05/23
*/
@Getter
public class PageDomain {
/**
* 当前记录起始索引
@ -17,6 +20,7 @@ public class PageDomain {
/**
* 每页显示记录数
*/
private Integer pageSize;
/**
@ -34,33 +38,50 @@ public class PageDomain {
*/
private Boolean reasonable = true;
/**
* 获得订单
*
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public String getOrderBy() {
if (StringUtils.isEmpty(orderByColumn)) {
if (StrUtil.isEmpty(orderByColumn)) {
return "";
}
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum() {
return page;
return StrUtil.toUnderlineCase(orderByColumn) + " " + isAsc;
}
/**
* 设置页码
*
* @param pageNum 页面num
* @author DB
* @since 2024/05/23
*/
public void setPageNum(Integer pageNum) {
this.page = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
/**
* 设置页面大小
*
* @param pageSize 页面大小
* @author DB
* @since 2024/05/23
*/
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public String getOrderByColumn() {
return orderByColumn;
}
/**
* 按列设置顺序
*
* @param orderByColumn 按列排序
* @author DB
* @since 2024/05/23
*/
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
@ -70,11 +91,11 @@ public class PageDomain {
}
public Boolean getBoolAsc() {
return StringUtils.equals(isAsc, "asc");
return StrUtil.equals(isAsc, "asc");
}
public void setIsAsc(String isAsc) {
if (StringUtils.isNotEmpty(isAsc)) {
if (StrUtil.isNotEmpty(isAsc)) {
// 兼容前端排序类型
if ("ascending".equals(isAsc)) {
isAsc = "asc";
@ -85,13 +106,13 @@ public class PageDomain {
}
}
public Boolean getReasonable() {
if (StringUtils.isNull(reasonable)) {
return Boolean.TRUE;
}
return reasonable;
}
/**
* 设置合理
*
* @param reasonable 合理
* @author DB
* @since 2024/05/23
*/
public void setReasonable(Boolean reasonable) {
this.reasonable = reasonable;
}

View File

@ -1,19 +0,0 @@
package com.cpop.core.base.entity;
import lombok.Getter;
/**
* 权限组
*/
@Getter
public class Permission {
/**
* 权限
*/
private String permission;
public void setPermission(String permission) {
this.permission = permission;
}
}

View File

@ -1,56 +0,0 @@
package com.cpop.core.base.enums;
/**
* @author DB
*/
public enum CycleEnum {
/**
*
*/
DAY(1, "每天"),
/**
*
*/
MONTH(2, ""),
/**
*
*/
WEEK(3, ""),
/**
*
*/
YEAR(4, "");
private int codeId;
private String message;
CycleEnum(int codeId, String message) {
this.codeId = codeId;
this.message = message;
}
public static CycleEnum getCycle(int code) {
for (CycleEnum c : CycleEnum.values()) {
if (c.codeId == code) {
return c;
}
}
return null;
}
public int getCodeId() {
return codeId;
}
public void setCodeId(int codeId) {
this.codeId = codeId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -1,6 +1,6 @@
package com.cpop.core.base.exception;
import com.cpop.core.utils.StringUtils;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.utils.MessageUtils;
import lombok.Getter;
@ -63,7 +63,7 @@ public class BaseException extends RuntimeException {
@Override
public String getMessage() {
String message = null;
if (!StringUtils.isEmpty(code)) {
if (!StrUtil.isEmpty(code)) {
message = MessageUtils.message(code, args);
}
if (message == null) {

View File

@ -1,9 +1,26 @@
package com.cpop.core.config;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;
import com.cpop.core.base.exception.UtilException;
import lombok.Data;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* 读取项目相关配置
*
@ -81,5 +98,220 @@ public class CpopConfig {
public String getUploadPath() {
return getProfile() + "/upload";
}
/**
* jwt
*/
private Jwt jwt;
/**
* jwt设置
*
* @param jwt jwt
* @author DB
* @since 2024/05/23
*/
public void setJwt(Jwt jwt) {
this.jwt = jwt;
}
/**
* jwt
*
* @author DB
* @version 1.0.0
* @since 2024/05/23
*/
@Data
public static class Jwt {
/**
* 白名单
*/
private String whiteList;
}
/**
* 网关配置
*/
private Gateway gateway;
/**
* 设置网关
*
* @param gateway 网关
* @author DB
* @since 2024/05/23
*/
public void setGateway(Gateway gateway) {
this.gateway = gateway;
}
/**
* 网关
*
* @author DB
* @version 1.0.0
* @since 2024/05/23
*/
@Data
public static class Gateway {
/**
* rsa密钥对
*/
private RsaKeypair rsaKeypair;;
/**
* rsa密钥对
*
* @author DB
* @version 1.0.0
* @since 2024/05/23
*/
@Data
public static class RsaKeypair {
/**
* 算法
*/
private String algorithm;
/**
* 关键尺寸
*/
private Integer keySize;
/**
* 公钥文件
*/
private String publicKeyFile;
/**
* 私钥文件
*/
private String privateKeyFile;
}
}
/**
* 获取登录rsa
*
* @return {@link RSA }
* @author DB
* @since 2024/05/23
*/
public RSA getLoginRsa(){
//rsa解密
Gateway.RsaKeypair rsaKeypair = gateway.getRsaKeypair();
Map<String, String> keyPair = getKeyPair(rsaKeypair.getPublicKeyFile(), rsaKeypair.getPrivateKeyFile());
return SecureUtil.rsa(keyPair.get("privateKey"), keyPair.get("publicKey"));
}
/**
* 获取密钥对
*
* @param publicKeyFile 公钥文件
* @param privateKeyFile 私钥文件
* @return {@link Map }<{@link String }, {@link String }>
* @author DB
* @since 2024/05/23
*/
private Map<String, String> getKeyPair(String publicKeyFile, String privateKeyFile){
Map<String, String> keyPairMap = new HashMap<>(2);
File publicFile = new File(publicKeyFile);
File privateFile = new File(privateKeyFile);
//判断是否存在公钥和私钥文件
if (!publicFile.exists() || !privateFile.exists()) {
generateKeyPairToFiles(publicKeyFile, privateKeyFile);
}
ObjectInputStream oisPublic = null;
ObjectInputStream oisPrivate = null;
Key publicKey = null;
Key privateKey = null;
try {
oisPublic = new ObjectInputStream(Files.newInputStream(Paths.get(publicKeyFile)));
oisPrivate = new ObjectInputStream(Files.newInputStream(Paths.get(privateKeyFile)));
publicKey = (Key) oisPublic.readObject();
privateKey = (Key) oisPrivate.readObject();
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
//公钥字符串
keyPairMap.put("publicKey", publicKeyBase64);
//私钥字符串
keyPairMap.put("privateKey", privateKeyBase64);
} catch (IOException | ClassNotFoundException e) {
throw new UtilException(e.getMessage());
} finally {
try {
assert oisPrivate != null;
oisPrivate.close();
oisPublic.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return keyPairMap;
}
/**
* 生成文件密钥对
*
* @param publicKeyFile 公钥文件
* @param privateKeyFile 私钥文件
* @author DB
* @since 2024/05/23
*/
private void generateKeyPairToFiles(String publicKeyFile, String privateKeyFile) {
ObjectOutputStream oosPublicKey = null;
ObjectOutputStream oosPrivateKey = null;
try {
Map<String, Key> keyPairMap = generateKeyPair();
Key publicKey = keyPairMap.get("publicKey");
Key privateKey = keyPairMap.get("privateKey");
oosPublicKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(publicKeyFile)));
oosPrivateKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(privateKeyFile)));
oosPublicKey.writeObject(publicKey);
oosPrivateKey.writeObject(privateKey);
} catch (NoSuchAlgorithmException | IOException e) {
throw new UtilException(e.getMessage());
} finally {
try {
//清空缓存关闭文件输出流
assert oosPublicKey != null;
oosPublicKey.close();
assert oosPrivateKey != null;
oosPrivateKey.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 生成密钥对
*
* @return {@link Map }<{@link String }, {@link Key }>
* @throws NoSuchAlgorithmException 生成失败异常
* @author DB
* @since 2024/05/23
*/
private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
KeyPair keyPair = SecureUtil.generateKeyPair(gateway.getRsaKeypair().getAlgorithm(), gateway.getRsaKeypair().getKeySize());
//得到公钥
Key publicKey = keyPair.getPublic();
//得到私钥
Key privateKey = keyPair.getPrivate();
Map<String, Key> keyPairMap = new HashMap<>();
keyPairMap.put("publicKey", publicKey);
keyPairMap.put("privateKey", privateKey);
return keyPairMap;
}
}

View File

@ -1,58 +0,0 @@
package com.cpop.core.config;
import com.cpop.core.filter.XssFilter;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.DispatcherType;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* Filter配置
*
* @author DB
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "xss")
public class FilterConfig {
/**
* 排除链接多个用逗号分隔
*/
private String excludes;
/**
* 匹配链接
*/
private String urlPatterns;
/**
* xss过滤器
* @return FilterRegistrationBean
* @author DB
* @since 2023/4/17 9:17
**/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes);
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@ -1,38 +0,0 @@
package com.cpop.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author DB
* @Description: 生成密钥对的配置文件
* @create: 2023-08-04 23:06
*/
@Data
@Component
@ConfigurationProperties(prefix = "cpop.gateway.rsa-keypair")
public class GenerateKeyPairConfig {
/**
* 加密方式
*/
private String algorithm;
/**
* 初始化大小
*/
private Integer keySize;
/**
* 公钥文件
*/
private String publicKeyFile;
/**
* 私钥文件
*/
private String privateKeyFile;
}

View File

@ -1,7 +1,7 @@
package com.cpop.core.config;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.base.entity.FastJson2JsonRedisSerializer;
import com.cpop.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -40,7 +40,7 @@ public class RedisConfig extends CachingConfigurerSupport {
public RedisConnectionFactory wxOpenRedisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort());
configuration.setDatabase(redisProperties.getDatabase());
if (StringUtils.isNotBlank(redisProperties.getPassword())) {
if (StrUtil.isNotBlank(redisProperties.getPassword())) {
configuration.setPassword(redisProperties.getPassword());
}
return new JedisConnectionFactory(configuration);

View File

@ -0,0 +1,136 @@
package com.cpop.core.config;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.constant.Constants;
import com.cpop.core.filter.RepeatableFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.Collections;
/**
* Sa令牌配置
*
* @author DB
* @version 1.0.0
* @since 2023-08-05 8:01
*/
@Configuration
@RequiredArgsConstructor
public class SaTokenConfigure implements WebMvcConfigurer {
/**
* jambox配置
*/
@Autowired(required = false)
private CpopConfig cpopConfig;
/**
* 获取servlet过滤器
*
* @return {@link SaServletFilter }
* @author DB
* @since 2024/05/23
*/
@Bean
public SaServletFilter getSaServletFilter() {
RepeatableFilter repeatableFilter = new RepeatableFilter();
repeatableFilter
// 指定 拦截路由 放行路由
//.addInclude("/**").addExclude(jamboxConfig.getJwt().getWhiteList().split(","))
// 认证函数: 每次请求执行
//.setAuth(obj -> {
// 登录认证 -- 拦截所有路由并排除/user/doLogin 用于开放登录
//SaRouter.match("/**", "/user/doLogin", StpUtil::checkLogin);
// 更多拦截处理方式请参考路由拦截式鉴权章节 */
//})
// 异常处理函数每次认证函数发生异常时执行此函数
//.setError(e -> SaResult.error(e.getMessage()))
// 前置函数在每次认证函数之前执行BeforeAuth 不受 includeList excludeList 的限制所有请求都会进入
.setBeforeAuth(r -> {
// ---------- 设置一些安全响应头 ----------
SaHolder.getResponse()
// 服务器名称
.setServer("Jambox")
// 是否可以在iframe显示视图 DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
.setHeader("X-Frame-Options", "SAMEORIGIN")
// 是否启用浏览器默认XSS防护 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时停止渲染页面
.setHeader("X-XSS-Protection", "1; mode=block")
// 禁用浏览器内容嗅探
.setHeader("X-Content-Type-Options", "nosniff")
;
});
return repeatableFilter;
}
/**
* 注册 Sa-Token 拦截器打开注解式鉴权功能
*
* @param registry 拦截器注册
* @author DB
* @since 2024/3/20
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册 Sa-Token 拦截器打开注解式鉴权功能
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
.addPathPatterns("/**")
.excludePathPatterns(Arrays.asList(cpopConfig.getJwt().getWhiteList().split(",")));
}
/**
* Sa-Token 整合 jwt (Simple 简单模式)
* @author DB
* @since 2024/3/20
* @return StpLogic
*/
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForSimple();
}
/**
* 配置跨源访问(CORS)
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
configuration.applyPermitDefaultValues();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
/**
* 资源映射
*
* @param registry 注册
* @author DB
* @since 2023/5/27 13:57
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//本地文件上传路径
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
.addResourceLocations("file:" + cpopConfig.getProfile() + "/");
}
}

View File

@ -1,31 +0,0 @@
package com.cpop.core.config;
import com.cpop.core.utils.ServletUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
/**
* 服务相关配置
*
* @author DB
*/
@Component
public class ServerConfig {
/**
* 获取完整的请求路径包括域名端口上下文访问路径
*
* @return 服务地址
*/
public String getUrl() {
HttpServletRequest request = ServletUtils.getRequest();
return getDomain(request);
}
public static String getDomain(HttpServletRequest request) {
StringBuffer url = request.getRequestURL();
String contextPath = request.getServletContext().getContextPath();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
}
}

View File

@ -213,4 +213,75 @@ public interface Constants {
*/
String QRCODE_HEADER = "data:image/png;base64,";
/**
* 默认文件名长度
*/
Integer DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认大小 50M
*/
Long DEFAULT_MAX_SIZE = 50L * 1024 * 1024;
/**
* png图像
*/
String IMAGE_PNG = "image/png";
/**
* jpg图像
*/
String IMAGE_JPG = "image/jpg";
/**
* jpeg图像
*/
String IMAGE_JPEG = "image/jpeg";
/**
* bmp图像
*/
String IMAGE_BMP = "image/bmp";
/**
* gif图像
*/
String IMAGE_GIF = "image/gif";
/**
* 映像扩展
*/
String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
/**
* flash扩展
*/
String[] FLASH_EXTENSION = {"swf", "flv"};
/**
* 媒体扩展
*/
String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb"};
/**
* 视频扩展
*/
String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
/**
* 默认允许扩展
*/
String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf"};
}

View File

@ -1,6 +1,10 @@
package com.cpop.core.filter;
import com.cpop.core.utils.StringUtils;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
@ -15,17 +19,30 @@ import java.io.IOException;
* @author DB
*/
@Component
public class RepeatableFilter implements Filter {
public class RepeatableFilter extends SaServletFilter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
this.beforeAuth.run((Object)null);
SaRouter.match(this.includeList).notMatch(this.excludeList).check((r) -> {
this.auth.run((Object)null);
});
} catch (StopMatchException ignored) {
} catch (Throwable var7) {
String result = var7 instanceof BackResultException ? var7.getMessage() : String.valueOf(this.error.run(var7));
if (response.getContentType() == null) {
response.setContentType("text/plain; charset=utf-8");
}
response.getWriter().print(result);
}
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
if (request instanceof HttpServletRequest && StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper) {

View File

@ -1,17 +1,16 @@
package com.cpop.core.filter;
import com.cpop.core.utils.http.HttpHelper;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
@ -19,6 +18,7 @@ import java.nio.charset.StandardCharsets;
*
* @author DB
*/
@Slf4j
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
@ -27,7 +27,38 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
body = HttpHelper.getBodyString(request).getBytes(StandardCharsets.UTF_8);
body = getBodyString(request).getBytes(StandardCharsets.UTF_8);
}
/**
* 获取主体字符串
*
* @param request 请求
* @return {@link String }
* @author DB
* @since 2024/05/24
*/
private String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream()) {
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
log.warn("getBodyString出现问题");
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
@Override

View File

@ -1,61 +0,0 @@
package com.cpop.core.filter;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 防止XSS攻击的过滤器
*
* @author DB
*/
public class XssFilter implements Filter {
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes)) {
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++) {
excludes.add(url[i]);
}
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp)) {
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches("GET") || method.matches("DELETE")) {
return true;
}
return StringUtils.matches(url, excludes);
}
@Override
public void destroy() {
}
}

View File

@ -1,98 +0,0 @@
package com.cpop.core.filter;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.html.EscapeUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* XSS过滤处理
*
* @author DB
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++) {
// 防xss攻击和过滤前后空格
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 非json类型直接返回
if (!isJsonRequest()) {
return super.getInputStream();
}
// 为空直接返回
String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);
if (StringUtils.isEmpty(json)) {
return super.getInputStream();
}
// xss过滤
json = EscapeUtil.clean(json).trim();
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public int available() throws IOException {
return jsonBytes.length;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
}
};
}
/**
* 是否是Json请求
*/
public boolean isJsonRequest() {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}

View File

@ -0,0 +1,247 @@
package com.cpop.core.handler;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.base.exception.UtilException;
import com.cpop.core.base.exception.file.InvalidExtensionException;
import com.cpop.core.config.CpopConfig;
import com.cpop.core.constant.Constants;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
* 上传文件工具类
* @author DB
* @version 1.1.0
* @since 2024-05-23 11:49
*/
@Component
public class UploadHandler {
@Autowired
private CpopConfig cpopConfig;
/**
* 上传文件
*
* @param file 文件
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public String uploadFile(MultipartFile file) {
//判断文件名长度
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > Constants.DEFAULT_FILE_NAME_LENGTH) {
throw new UtilException("文件名过长");
}
//文件大小校验
try {
assertAllowed(file, Constants.DEFAULT_ALLOWED_EXTENSION);
} catch (FileSizeLimitExceededException | InvalidExtensionException e) {
throw new UtilException(e);
}
//编码文件名
String fileName = extractFilename(file);
//获取绝对文件
String absPath = getAbsoluteFile(cpopConfig.getUploadPath(), fileName).getAbsolutePath();
try {
//文件传输
file.transferTo(Paths.get(absPath));
} catch (IOException e) {
throw new UtilException(e);
}
// 上传并返回新文件名称
String pathFileName = getPathFileName(cpopConfig.getUploadPath(), fileName);
//强制将http变成https
//String https = serverConfig.getUrl().replace("http:", "https:");
//String url = https + fileName;
return NetUtil.getLocalHostName() + pathFileName;
}
/**
* 获取文件名称
*
* @param fileName 路径名称
* @return 没有文件路径的名称
* @author DB
* @since 2024/05/23
*/
public String getName(String fileName) {
if (fileName == null) {
return null;
}
int lastUnixPos = fileName.lastIndexOf('/');
int lastWindowsPos = fileName.lastIndexOf('\\');
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
/**
* 获取路径文件名
*
* @param uploadDir 上传dir
* @param fileName 文件名称
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
private String getPathFileName(String uploadDir, String fileName) {
int dirLastIndex = cpopConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
/**
* 编码文件名
*
* @param file 文件
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public String extractFilename(MultipartFile file) {
return StrUtil.format("{}/{}_{}.{}", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")),
FilenameUtils.getBaseName(file.getOriginalFilename()), IdUtil.getSnowflakeNextId(), getExtension(file));
}
/**
* 获取绝对文件
*
* @param uploadDir 上传dir
* @param fileName 文件名称
* @return {@link File }
* @author DB
* @since 2024/05/23
*/
public File getAbsoluteFile(String uploadDir, String fileName) {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
}
return desc;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @param allowedExtension 允许扩展
* @throws FileSizeLimitExceededException 文件大小限制超出异常
* @throws InvalidExtensionException 无效扩展异常
* @author DB
* @since 2024/05/23
*/
private void assertAllowed(MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (size > Constants.DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException("文件过大", size, Constants.DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == Constants.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == Constants.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == Constants.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == Constants.VIDEO_EXTENSION) {
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
* @author DB
* @since 2024/05/23
*/
private String getExtension(MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StrUtil.isEmpty(extension)) {
extension = getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
/**
* 允许扩展
*
* @param extension 扩展
* @param allowedExtension 允许扩展
* @return boolean
* @author DB
* @since 2024/05/23
*/
public boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
/**
* 得到扩展
*
* @param prefix 前缀
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
private String getExtension(String prefix) {
return switch (prefix) {
case Constants.IMAGE_PNG -> "png";
case Constants.IMAGE_JPG -> "jpg";
case Constants.IMAGE_JPEG -> "jpeg";
case Constants.IMAGE_BMP -> "bmp";
case Constants.IMAGE_GIF -> "gif";
default -> "";
};
}
/**
* 获取内容类型
*
* @param extension 扩展
* @return {@link String }
* @author DB
* @since 2024/05/24
*/
public String getContentType(String extension) {
return switch (extension) {
case "png" -> Constants.IMAGE_PNG;
case "jpg" -> Constants.IMAGE_JPG;
case "jpeg" -> Constants.IMAGE_JPEG;
case "bmp" -> Constants.IMAGE_BMP;
case "gif" -> Constants.IMAGE_GIF;
default -> "";
};
}
}

View File

@ -1,6 +1,7 @@
package com.cpop.core.strategy.json;
import com.cpop.core.utils.StringUtils;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
@ -30,8 +31,9 @@ public class ArrayToStringDeserializer extends JsonDeserializer<String> {
} else if (treeNode instanceof DoubleNode) {
return ((DoubleNode) treeNode).asText();
} else if (treeNode instanceof ArrayNode) {
JSONArray array = JSONArray.parseArray((treeNode).toString());
//字符串数组会多出两个引号需要手动去除
return StringUtils.replace(StringUtils.join((ArrayNode) treeNode, ","), "\"", "");
return StrUtil.join(",", array);
} else if (treeNode instanceof TextNode) {
return ((TextNode) treeNode).asText();
}

View File

@ -1,30 +0,0 @@
package com.cpop.core.utils;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
public class JsonUtils {
private static final ObjectMapper JSON = new ObjectMapper();
static {
JSON.setSerializationInclusion(Include.NON_NULL);
JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
}
public static String toJson(Object obj) {
try {
return JSON.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.error(e.getMessage());
}
return null;
}
}

View File

@ -1,12 +1,10 @@
package com.cpop.core.utils;
import com.cpop.core.base.exception.UtilException;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
@ -32,11 +30,7 @@ public class QuartzUtils {
*/
public String getJobInfo(String name, String group) throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(name, group);
Trigger trigger = scheduler.getTrigger(triggerKey);
if (trigger == null) {
throw new UtilException("获取定时任务失败");
}
CronTrigger cronTrigger = (CronTrigger) trigger;
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
return String.format("time:%s,state:%s", cronTrigger.getCronExpression(),
scheduler.getTriggerState(triggerKey).name());
}
@ -53,20 +47,15 @@ public class QuartzUtils {
public boolean modifyJob(String name, String group, String time) throws SchedulerException {
Date date = null;
TriggerKey triggerKey = new TriggerKey(name, group);
Trigger triggerResult = scheduler.getTrigger(triggerKey);
if (triggerResult != null) {
CronTrigger cronTrigger = (CronTrigger) triggerResult;
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group)
.withSchedule(cronScheduleBuilder).build();
date = scheduler.rescheduleJob(triggerKey, trigger);
}
return date != null;
} else {
return false;
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group)
.withSchedule(cronScheduleBuilder).build();
date = scheduler.rescheduleJob(triggerKey, trigger);
}
return date != null;
}
/**

View File

@ -1,242 +0,0 @@
package com.cpop.core.utils;
import com.cpop.core.base.exception.UtilException;
import com.cpop.core.config.GenerateKeyPairConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* @author DB
* @Description: Rsa相关工具类
* @create 2023-08-04 23:09
*/
@Component
public class RsaUtils {
@Autowired
private GenerateKeyPairConfig keyPairConfig;
// region 私有方法
/**
* 生成密钥对
* @return 返回map集合其中包含publicKey与privateKey
* @throws NoSuchAlgorithmException
*/
private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
//RSA算法要求有一个可信任的随机数源
SecureRandom secureRandom = new SecureRandom();
//为RSA算法创建一个KeyPairGenerator对象
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyPairConfig.getAlgorithm());
//利用上面的随机数据源初始化这个KeyPairGenerator对象
keyPairGenerator.initialize(keyPairConfig.getKeySize(), secureRandom);
//生成密匙对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//得到公钥
Key publicKey = keyPair.getPublic();
//得到私钥
Key privateKey = keyPair.getPrivate();
Map<String, Key> keyPairMap = new HashMap<>();
keyPairMap.put("publicKey", publicKey);
keyPairMap.put("privateKey", privateKey);
return keyPairMap;
}
/**
* 获取文件中获取密钥对象
* @param fileName 文件名
* @return 密钥对象
*/
private Key getKeyFromFile(String fileName) {
Key key = null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(Files.newInputStream(Paths.get(fileName)));
key = (Key) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new UtilException(e.getMessage());
} finally {
try {
assert ois != null;
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return key;
}
/**
* 将密钥对生成到文件中
*/
private void generateKeyPairToFiles() {
generateKeyPairToFiles(keyPairConfig.getPublicKeyFile(),keyPairConfig.getPrivateKeyFile());
}
private void generateKeyPairToFiles(String publicKeyFile, String privateKeyFile) {
ObjectOutputStream oosPublicKey = null;
ObjectOutputStream oosPrivateKey = null;
try {
Map<String, Key> keyPairMap = generateKeyPair();
Key publicKey = keyPairMap.get("publicKey");
Key privateKey = keyPairMap.get("privateKey");
oosPublicKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(publicKeyFile)));
oosPrivateKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(privateKeyFile)));
oosPublicKey.writeObject(publicKey);
oosPrivateKey.writeObject(privateKey);
} catch (NoSuchAlgorithmException | IOException e) {
throw new UtilException(e.getMessage());
} finally {
try {
//清空缓存关闭文件输出流
assert oosPublicKey != null;
oosPublicKey.close();
assert oosPrivateKey != null;
oosPrivateKey.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 初始化密钥对文件
* @return 返回密钥对信息publicKey公钥字符串privateKey私钥字符串
*/
public Map<String, String> initKeyPair() {
return initKeyPair(keyPairConfig.getPublicKeyFile(),keyPairConfig.getPrivateKeyFile());
}
public Map<String, String> initKeyPair(String publicKeyFile, String privateKeyFile){
Map<String, String> keyPairMap = new HashMap<>();
File publicFile = new File(publicKeyFile);
File privateFile = new File(privateKeyFile);
//判断是否存在公钥和私钥文件
if (!publicFile.exists() || !privateFile.exists()) {
generateKeyPairToFiles(publicKeyFile, privateKeyFile);
}
ObjectInputStream oisPublic = null;
ObjectInputStream oisPrivate = null;
Key publicKey = null;
Key privateKey = null;
try {
oisPublic = new ObjectInputStream(Files.newInputStream(Paths.get(publicKeyFile)));
oisPrivate = new ObjectInputStream(Files.newInputStream(Paths.get(privateKeyFile)));
publicKey = (Key) oisPublic.readObject();
privateKey = (Key) oisPrivate.readObject();
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
//公钥字符串
keyPairMap.put("publicKey", publicKeyBase64);
//私钥字符串
keyPairMap.put("privateKey", privateKeyBase64);
} catch (IOException | ClassNotFoundException e) {
throw new UtilException(e.getMessage());
} finally {
try {
assert oisPrivate != null;
oisPrivate.close();
oisPublic.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return keyPairMap;
}
/**
* 加密方法
* @param source 源数据
* @return 加密后的字符串
*/
public String encrypt(String source, Key publicKey) {
Base64.Encoder encoder = Base64.getEncoder();
String encryptSource = null;
try {
//得到Cipher对象来实现对源数据的RSA加密
Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = source.getBytes();
//执行加密操作
encryptSource = encoder.encodeToString(cipher.doFinal(bytes));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
BadPaddingException e) {
throw new UtilException(e.getMessage());
}
return encryptSource;
}
/**
* 加密方法
* @param source 源数据
* @return 加密后的字符串
*/
public String encrypt(String source) {
return encrypt(source, getKeyFromFile(keyPairConfig.getPublicKeyFile()));
}
/**
* 解密方法
* @param source 密文
* @return 解密后的字符串
*/
public String decrypt(String source) {
return decrypt(source,keyPairConfig.getPrivateKeyFile());
}
public String decrypt(String source, String privateKeyFile) {
Key privateKey = getKeyFromFile(privateKeyFile);
Base64.Decoder decoder = Base64.getDecoder();
String decryptSource = null;
try {
//得到Cipher对象对已用公钥加密的数据进行RSA解密
Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//执行解密操作
byte[] bytes = decoder.decode(source);
decryptSource = new String(cipher.doFinal(bytes), StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
IllegalBlockSizeException | BadPaddingException e) {
throw new UtilException(e.getMessage());
}
return decryptSource;
}
public String decrypt(String source, Key privateKey) {
Base64.Decoder decoder = Base64.getDecoder();
String decryptSource = null;
try {
//得到Cipher对象对已用公钥加密的数据进行RSA解密
Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//执行解密操作
byte[] bytes = decoder.decode(source);
decryptSource = new String(cipher.doFinal(bytes), StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
IllegalBlockSizeException | BadPaddingException e) {
throw new UtilException(e.getMessage());
}
return decryptSource;
}
}

View File

@ -1,7 +1,9 @@
package com.cpop.core.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.core.utils.text.Convert;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@ -12,22 +14,36 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.BufferedReader;
import java.io.IOException;
/**
* 客户端工具类
*
* @author DB
* @version 1.1.0
* @since 2024/05/23
*/
public class ServletUtils {
/**
* 获取String参数
* 获取参数
*
* @param name 参数key
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public static String getParameter(String name) {
return getRequest().getParameter(name);
}
/**
* 获取String参数
* 获取参数
*
* @param name 参数key
* @param defaultValue 默认值
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public static String getParameter(String name, String defaultValue) {
return Convert.toStr(getRequest().getParameter(name), defaultValue);
@ -35,10 +51,15 @@ public class ServletUtils {
/**
* 获取Integer参数
*
* @param name 参数key
* @return {@link Integer }
* @author DB
* @since 2024/05/23
*/
public static Integer getParameterToInt(String name) {
String parameter = getRequest().getParameter(name);
if (StringUtils.isBlank(parameter)){
if (StrUtil.isBlank(parameter)){
//尝试从请求体中获取
BufferedReader reader;
try {
@ -64,6 +85,12 @@ public class ServletUtils {
/**
* 获取Integer参数
*
* @param name 参数key
* @param defaultValue 默认值
* @return {@link Integer }
* @author DB
* @since 2024/05/23
*/
public static Integer getParameterToInt(String name, Integer defaultValue) {
return Convert.toInt(getRequest().getParameter(name), defaultValue);
@ -71,6 +98,11 @@ public class ServletUtils {
/**
* 获取Boolean参数
*
* @param name 参数key
* @return {@link Boolean }
* @author DB
* @since 2024/05/23
*/
public static Boolean getParameterToBool(String name) {
return Convert.toBool(getRequest().getParameter(name));
@ -78,6 +110,12 @@ public class ServletUtils {
/**
* 获取Boolean参数
*
* @param name 参数key
* @param defaultValue 默认值
* @return {@link Boolean }
* @author DB
* @since 2024/05/23
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue) {
return Convert.toBool(getRequest().getParameter(name), defaultValue);
@ -85,6 +123,10 @@ public class ServletUtils {
/**
* 获取request
*
* @return {@link HttpServletRequest }
* @author DB
* @since 2024/05/23
*/
public static HttpServletRequest getRequest() {
return getRequestAttributes().getRequest();
@ -92,6 +134,10 @@ public class ServletUtils {
/**
* 获取response
*
* @return {@link HttpServletResponse }
* @author DB
* @since 2024/05/23
*/
public static HttpServletResponse getResponse() {
return getRequestAttributes().getResponse();
@ -99,11 +145,22 @@ public class ServletUtils {
/**
* 获取session
*
* @return {@link HttpSession }
* @author DB
* @since 2024/05/23
*/
public static HttpSession getSession() {
return getRequest().getSession();
}
/**
* 获取请求属性
*
* @return {@link ServletRequestAttributes }
* @author DB
* @since 2024/05/23
*/
public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
@ -114,9 +171,10 @@ public class ServletUtils {
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
* @author DB
* @since 2024/05/23
*/
public static String renderString(HttpServletResponse response, String string) {
public static void renderString(HttpServletResponse response, String string) {
try {
response.setStatus(200);
response.setContentType("application/json");
@ -125,15 +183,18 @@ public class ServletUtils {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 否是Ajax异步请求
* ajax请求
*
* @param request
* @param request 请求
* @return {@link Boolean }
* @author DB
* @since 2024/05/23
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
public static Boolean isAjaxRequest(HttpServletRequest request) {
String accept = request.getHeader("accept");
if (accept != null && accept.contains("application/json")) {
return true;
@ -145,12 +206,51 @@ public class ServletUtils {
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
if (StrUtil.containsAnyIgnoreCase(uri, ".json", ".xml")) {
return true;
}
String ajax = request.getParameter("__ajax");
return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
return StrUtil.containsAnyIgnoreCase(ajax, "json", "xml");
}
/**
* 获取IP地址
*
* @param request 请求
* @return {@link String }
* @author DB
* @since 2024/05/24
*/
public static String getIpAddr(HttpServletRequest request)
{
if (request == null)
{
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.removeHtmlTag(ip);
}
}

View File

@ -1,11 +1,8 @@
package com.cpop.core.utils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.entity.BaseEntity;
import com.cpop.core.base.exception.BaseException;
import com.mybatisflex.core.service.IService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@ -14,11 +11,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* spring工具类 方便在非spring管理环境中获取bean
*
@ -133,8 +125,7 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
* @return 当前的环境配置
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
return getActiveProfiles()[0];
}
/**
@ -153,37 +144,4 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
return entity.replaceAll("", "") + "Service";
}
public <T extends Object, E> List<T> copyProperties(List<E> sources, Class<T> clazz) {
List<T> list = new ArrayList<>();
if (sources == null || sources.isEmpty()) {
return list;
}
for (E item : sources) {
T t = null;
try {
t = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
throw new BaseException(e.getMessage());
}
BeanUtils.copyProperties(item, t);
list.add(t);
}
return list;
}
/**
* StringToList
*
* @param longs
* @return
*/
public List<Long> stringToLongList(String longs) {
if (StringUtils.isBlank(longs)) {
return null;
}
String[] split = longs.split(",");
return Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList());
}
}

View File

@ -1,5 +1,6 @@
package com.cpop.core.utils;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.base.entity.PageDomain;
import com.cpop.core.base.exception.UtilException;
@ -53,6 +54,10 @@ public class SqlUtils {
/**
* 封装分页对象
*
* @return {@link PageDomain }
* @author DB
* @since 2024/05/23
*/
public PageDomain getPageDomain() {
PageDomain pageDomain = new PageDomain();
@ -64,15 +69,27 @@ public class SqlUtils {
return pageDomain;
}
/**
* 构建页请求
*
* @return {@link PageDomain }
* @author DB
* @since 2024/05/23
*/
public PageDomain buildPageRequest() {
return getPageDomain();
}
/**
* 检查字符防止注入绕过
*
* @param value 价值
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public String escapeOrderBySql(String value) {
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
if (StrUtil.isNotEmpty(value) && !isValidOrderBySql(value)) {
throw new UtilException("参数不符合规范,不能进行查询");
}
return value;
@ -80,6 +97,11 @@ public class SqlUtils {
/**
* 验证 order by 语法是否符合规范
*
* @param value 价值
* @return boolean
* @author DB
* @since 2024/05/23
*/
public boolean isValidOrderBySql(String value) {
return value.matches(SQL_PATTERN);
@ -87,10 +109,14 @@ public class SqlUtils {
/**
* 设置请求排序数据
*
* @return {@link String }
* @author DB
* @since 2024/05/23
*/
public String startOrderBy() {
PageDomain pageDomain = getPageDomain();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) {
if (StrUtil.isNotEmpty(pageDomain.getOrderBy())) {
return escapeOrderBySql(pageDomain.getOrderBy());
}else {
throw new UtilException("获取排序参数失败");

View File

@ -1,582 +0,0 @@
package com.cpop.core.utils;
import com.cpop.core.constant.Constants;
import com.cpop.core.utils.text.StrFormatter;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.AntPathMatcher;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* 字符串工具类
*
* @author DB
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/**
* 空字符串
*/
private static final String NULL_STR = "";
/**
* 下划线
*/
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll) {
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll) {
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
* * @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects) {
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects) {
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map) {
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str) {
return isNull(str) || NULL_STR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object) {
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object) {
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object) {
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str) {
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start) {
if (str == null) {
return NULL_STR;
}
if (start < 0) {
start = str.length() + start;
}
if (start < 0) {
start = 0;
}
if (start > str.length()) {
return NULL_STR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end) {
if (str == null) {
return NULL_STR;
}
if (end < 0) {
end = str.length() + end;
}
if (start < 0) {
start = str.length() + start;
}
if (end > str.length()) {
end = str.length();
}
if (start > end) {
return NULL_STR;
}
if (start < 0) {
start = 0;
}
if (end < 0) {
end = 0;
}
return str.substring(start, end);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params) {
if (isEmpty(params) || isEmpty(template)) {
return template;
}
return StrFormatter.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean isHttp(String link) {
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static Set<String> str2Set(String str, String sep) {
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str)) {
return list;
}
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str)) {
return list;
}
String[] split = str.split(sep);
for (String string : split) {
if (filterBlank && StringUtils.isBlank(string)) {
continue;
}
if (trim) {
string = string.trim();
}
list.add(string);
}
return list;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
if (isEmpty(cs) || isEmpty(searchCharSequences)) {
return false;
}
for (CharSequence testStr : searchCharSequences) {
if (containsIgnoreCase(cs, testStr)) {
return true;
}
}
return false;
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str) {
if (str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (i > 0) {
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
} else {
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1)) {
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
sb.append(SEPARATOR);
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs) {
if (str != null && strs != null) {
for (String s : strs) {
if (str.equalsIgnoreCase(trim(s))) {
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains("_")) {
// 不含下划线仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法 例如user_name->userName
*/
public static String toCamelCase(String s) {
if (s == null) {
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs) {
if (isEmpty(str) || isEmpty(strs)) {
return false;
}
for (String pattern : strs) {
if (isMatch(pattern, str)) {
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url) {
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
/**
* 首字母大写(进行字母的ascii编码前移效率是最高的)
*
* @param fieldName 需要转化的字符串
*/
public static String getMethodName(String fieldName) {
char[] chars = fieldName.toCharArray();
chars[0] = toUpperCase(chars[0]);
return String.valueOf(chars);
}
/**
* 字符转成大写
*
* @param c 需要转化的字符
*/
public static char toUpperCase(char c) {
if (97 <= c && c <= 122) {
c ^= 32;
}
return c;
}
/**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度
*/
public static String padL(final Number num, final int size)
{
return padL(num.toString(), size, '0');
}
/**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串由原字符串左补齐或截取得到
*/
public static String padL(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
/**
*
* @param aString 要截取的字符串
* @param startIndex 开始下标
* @param endIndex 截取长度
*/
public static String substringByte(String aString,int startIndex,int endIndex) {
byte[] bytes = aString.getBytes(StandardCharsets.UTF_8);
int subLen = endIndex - startIndex;
if (startIndex < 0) {
return "startIndex异常";
}
if (endIndex > bytes.length) {
return "endIndex异常";
}
if (subLen <= 0) {
return "startIndex或endIndex异常";
}
byte[] subBytes = new byte[subLen];
int i = 0;
while (startIndex < endIndex) {
subBytes[i++] = bytes[startIndex++];
}
return new String(subBytes, StandardCharsets.UTF_8);
}
/**
* 字符串是否再匹配项内
* @author DB
* @since 2024/2/5
* @param string 字符串
* @param searchStrings 匹配项
* @return boolean
*/
public static boolean startWithAny(final CharSequence string, final CharSequence... searchStrings) {
if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
return false;
}
for (final CharSequence searchString : searchStrings) {
if (StringUtils.startsWith(string, searchString)) {
return true;
}
}
return false;
}
}

View File

@ -1,193 +0,0 @@
package com.cpop.core.utils.bean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Bean 工具类
*
* @author DB
*/
public class BeanUtils extends org.springframework.beans.BeanUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class);
/**
* Bean方法名中属性名开始的下标
*/
private static final int BEAN_METHOD_PROP_INDEX = 3;
/**
* 匹配getter方法的正则表达式
*/
private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
/**
* 匹配setter方法的正则表达式
*/
private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
/**
* Bean属性复制工具方法
*
* @param dest 目标对象
* @param src 源对象
*/
public static void copyBeanProp(Object dest, Object src) {
try {
copyProperties(src, dest);
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
}
/**
* 实体类转换
* @param source 资源
* @param target 目标
* @param <T> 目标类型
* @return 转换结果
*/
public static <T> T sourceToTarget(Object source, Class<T> target){
if(source == null){
return null;
}
T targetObject = null;
try {
targetObject = target.newInstance();
BeanUtils.copyProperties(source, targetObject);
} catch (Exception e) {
LOGGER.error("实体类转换失败: ", e);
}
return targetObject;
}
/**
* 获取对象的setter方法
*
* @param obj 对象
* @return 对象的setter方法列表
*/
public static List<Method> getSetterMethods(Object obj) {
// setter方法列表
List<Method> setterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找setter方法
for (Method method : methods) {
Matcher m = SET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 1)) {
setterMethods.add(method);
}
}
// 返回setter方法列表
return setterMethods;
}
/**
* 获取对象的getter方法
*
* @param obj 对象
* @return 对象的getter方法列表
*/
public static List<Method> getGetterMethods(Object obj) {
// getter方法列表
List<Method> getterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找getter方法
for (Method method : methods) {
Matcher m = GET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 0)) {
getterMethods.add(method);
}
}
// 返回getter方法列表
return getterMethods;
}
/**
* 检查Bean方法名中的属性名是否相等<br>
* 如getName()和setName()属性名一样getName()和setAge()属性名不一样
*
* @param m1 方法名1
* @param m2 方法名2
* @return 属性名一样返回true否则返回false
*/
public static boolean isMethodPropEquals(String m1, String m2) {
return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
}
/**
* 对象转换
*
* @param sourceObject 原Object
* @param destinationClass 转换class
* @param <T> 转换实体类
* @param <E> 原实体类
* @return T
*/
public static <T, E> T mapToClass(E sourceObject, Class<T> destinationClass) {
T targetObject = instantiateClass(destinationClass);
copyProperties(sourceObject, targetObject);
return targetObject;
}
/**
* List转换
*
* @param sourceList 原List
* @param destinationClass 转换class
* @param <T> 转换实体类
* @param <E> 原实体类
* @return List<T>
*/
public static <T, E> List<T> mapToList(List<E> sourceList, Class<T> destinationClass) {
List<T> destinationList = new ArrayList<>(sourceList.size());
for (E sourceObject : sourceList) {
T targetObject = instantiateClass(destinationClass);
copyProperties(sourceObject, targetObject);
destinationList.add(targetObject);
}
return destinationList;
}
/**
* @param origin
* @param t
* @author LOST.yuan
* @Description map转对象
* @date 11:52 2022/8/23
**/
public static <T> void mapToObj(Map<String, String> origin, T t) {
Class<?> clazz = t.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
Object o = origin.get(fieldName);
if (o == null) {
continue;
}
String value = o.toString();
try {
field.set(t, value);
} catch (IllegalAccessException e) {
LOGGER.error(e.getMessage());
}
}
}
}

View File

@ -1,71 +0,0 @@
package com.cpop.core.utils.file;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
/**
* 文件类型工具类
*
* @author DB
*/
public class FileTypeUtils {
public FileTypeUtils() {
}
private static class FileTypeUtilsInstance {
private static final FileTypeUtils INSTANCE = new FileTypeUtils();
}
public static FileTypeUtils getInstance() {
return FileTypeUtilsInstance.INSTANCE;
}
/**
* 获取文件类型
*
* @param file 文件名
* @return 后缀不含".")
*/
public String getFileType(File file) {
if (null == file) {
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
* @param fileName 文件名
* @return 后缀不含".")
*/
public String getFileType(String fileName) {
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0) {
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀不含".")
*/
public String getFileExtendName(byte[] photoByte) {
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
strFileExtendName = "GIF";
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
strFileExtendName = "JPG";
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
strFileExtendName = "BMP";
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
strFileExtendName = "PNG";
}
return strFileExtendName;
}
}

View File

@ -1,209 +0,0 @@
package com.cpop.core.utils.file;
import com.cpop.core.config.CpopConfig;
import com.cpop.core.constant.Constants;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.file.FileNameLengthLimitExceededException;
import com.cpop.core.base.exception.file.FileSizeLimitExceededException;
import com.cpop.core.base.exception.file.InvalidExtensionException;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.uuid.Seq;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
* 文件上传工具类
*
* @author DB
*/
public class FileUploadUtils {
public FileUploadUtils() {
}
private static class FileUploadUtilsInstance {
private static final FileUploadUtils INSTANCE = new FileUploadUtils();
}
public static FileUploadUtils getInstance() {
return FileUploadUtilsInstance.INSTANCE;
}
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = SpringUtils.getBean(CpopConfig.class).getProfile();
public void setDefaultBaseDir(String defaultBaseDir) {
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public String getDefaultBaseDir() {
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public final String upload(MultipartFile file) throws IOException {
try {
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public final String upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException {
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
/**
* 编码文件名
*/
public final String extractFilename(MultipartFile file) {
return StringUtils.format("{}/{}_{}.{}", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
public final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
}
return desc;
}
public final String getPathFileName(String uploadDir, String fileName) throws IOException {
int dirLastIndex = SpringUtils.getBean(CpopConfig.class).getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public final boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public final String getExtension(MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)) {
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
}

View File

@ -1,310 +0,0 @@
package com.cpop.core.utils.file;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.config.CpopConfig;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.uuid.IdUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* 文件处理工具类
*
* @author DB
*/
public class FileUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
public FileUtils() {
}
private static class FileUtilsInstance {
private static final FileUtils INSTANCE = new FileUtils();
}
public static FileUtils getInstance() {
return FileUtilsInstance.INSTANCE;
}
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
* @return
*/
public void writeBytes(String filePath, OutputStream os) throws IOException {
FileInputStream fis = null;
try {
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0) {
os.write(b, 0, length);
}
} catch (IOException e) {
throw e;
} finally {
IOUtils.close(os);
IOUtils.close(fis);
}
}
/**
* 写数据到文件中
*
* @param data 数据
* @return 目标文件
* @throws IOException IO异常
*/
public String writeImportBytes(byte[] data) throws IOException {
return writeBytes(data, SpringUtils.getBean(CpopConfig.class).getImportPath());
}
/**
* 写数据到文件中
*
* @param data 数据
* @param uploadDir 目标文件
* @return 目标文件
* @throws IOException IO异常
*/
public String writeBytes(byte[] data, String uploadDir) throws IOException {
FileOutputStream fos = null;
String pathName = "";
try {
String extension = getFileExtendName(data);
pathName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) + "/" + IdUtils.fastUUID() + "." + extension;
File file = FileUploadUtils.getInstance().getAbsoluteFile(uploadDir, pathName);
fos = new FileOutputStream(file);
fos.write(data);
} finally {
IOUtils.close(fos);
}
return FileUploadUtils.getInstance().getPathFileName(uploadDir, pathName);
}
/**
* 删除文件
*
* @param filePath 文件
* @return
*/
public boolean deleteFile(String filePath) {
boolean flag = false;
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
flag = file.delete();
}
return flag;
}
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public boolean isValidFilename(String filename) {
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public boolean checkAllowDownload(String resource) {
// 禁止目录上跳级别
if (StringUtils.contains(resource, "..")) {
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getInstance().getFileType(resource))) {
return true;
}
// 不在允许下载的文件规则
return false;
}
/**
* 下载文件名重新编码
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名
*/
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
*/
public void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public String percentEncode(String s) throws UnsupportedEncodingException {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
/**
* 获取图像后缀
*
* @param photoByte 图像数据
* @return 后缀名
*/
public String getFileExtendName(byte[] photoByte) {
String strFileExtendName = "jpg";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
strFileExtendName = "gif";
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
strFileExtendName = "jpg";
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
strFileExtendName = "bmp";
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
strFileExtendName = "png";
}
return strFileExtendName;
}
/**
* 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
*
* @param fileName 路径名称
* @return 没有文件路径的名称
*/
public String getName(String fileName) {
if (fileName == null) {
return null;
}
int lastUnixPos = fileName.lastIndexOf('/');
int lastWindowsPos = fileName.lastIndexOf('\\');
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
/**
* 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi
*
* @param fileName 路径名称
* @return 没有文件路径和后缀的名称
*/
public String getNameNotSuffix(String fileName) {
if (fileName == null) {
return null;
}
return FilenameUtils.getBaseName(fileName);
}
/**
* @Description: 读取Excel
* @param filePath
* @param list
* @return
* @author DB
* @Date: 2023/7/14 0014 13:53
*/
public void readExcel(String filePath, List<T> list) {
//excel文件路径
File file = new File(filePath);
EasyExcel.read(file, T.class, new ReadListener<T>() {
@Override
public void invoke(T t, AnalysisContext analysisContext) {
list.add(t);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
LOGGER.info("read finished");
}
}).sheet("sheet1").doRead();
}
/**
* 文件转上传文件格式
* @author DB
* @since 2023/12/08
* @param file 文件
* @return MultipartFile 上传文件
*/
public MultipartFile getMultipartFile(File file) throws IOException {
FileInputStream fileInputStream = new FileInputStream(file);
return new MockMultipartFile(
"file",
file.getName(),
"text/plain",
fileInputStream);
}
}

View File

@ -1,57 +0,0 @@
package com.cpop.core.utils.file;
/**
* 媒体类型工具类
*
* @author DB
*/
public class MimeTypeUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb"};
public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf"};
public static String getExtension(String prefix) {
switch (prefix) {
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}

View File

@ -1,133 +0,0 @@
package com.cpop.core.utils.html;
import com.cpop.core.utils.StringUtils;
/**
* 转义和反转义工具类
*
* @author DB
*/
public class EscapeUtil {
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
private static final char[][] TEXT = new char[64][];
static {
for (int i = 0; i < 64; i++) {
TEXT[i] = new char[]{(char) i};
}
// special HTML characters
// 单引号
TEXT['\''] = "&#039;".toCharArray();
// 双引号
TEXT['"'] = "&#34;".toCharArray();
// &
TEXT['&'] = "&#38;".toCharArray();
// 小于号
TEXT['<'] = "&#60;".toCharArray();
// 大于号
TEXT['>'] = "&#62;".toCharArray();
}
/**
* 转义文本中的HTML字符为安全的字符
*
* @param text 被转义的文本
* @return 转义后的文本
*/
public static String escape(String text) {
return encode(text);
}
/**
* 还原被转义的HTML特殊字符
*
* @param content 包含转义符的HTML内容
* @return 转换后的字符串
*/
public static String unescape(String content) {
return decode(content);
}
/**
* 清除所有HTML标签但是不删除标签内的内容
*
* @param content 文本
* @return 清除标签后的文本
*/
public static String clean(String content) {
return new HTMLFilter().filter(content);
}
/**
* Escape编码
*
* @param text 被编码的文本
* @return 编码后的字符
*/
private static String encode(String text) {
if (StringUtils.isEmpty(text)) {
return StringUtils.EMPTY;
}
final StringBuilder tmp = new StringBuilder(text.length() * 6);
char c;
for (int i = 0; i < text.length(); i++) {
c = text.charAt(i);
if (c < 256) {
tmp.append("%");
if (c < 16) {
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
} else {
tmp.append("%u");
if (c <= 0xfff) {
// issue#I49JU8@Gitee
tmp.append("0");
}
tmp.append(Integer.toString(c, 16));
}
}
return tmp.toString();
}
/**
* Escape解码
*
* @param content 被转义的内容
* @return 解码后的字符串
*/
public static String decode(String content) {
if (StringUtils.isEmpty(content)) {
return content;
}
StringBuilder tmp = new StringBuilder(content.length());
int lastPos = 0, pos = 0;
char ch;
while (lastPos < content.length()) {
pos = content.indexOf("%", lastPos);
if (pos == lastPos) {
if (content.charAt(pos + 1) == 'u') {
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
tmp.append(ch);
lastPos = pos + 6;
} else {
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
tmp.append(ch);
lastPos = pos + 3;
}
} else {
if (pos == -1) {
tmp.append(content.substring(lastPos));
lastPos = content.length();
} else {
tmp.append(content.substring(lastPos, pos));
lastPos = pos;
}
}
}
return tmp.toString();
}
}

View File

@ -1,499 +0,0 @@
package com.cpop.core.utils.html;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* HTML过滤器用于去除XSS漏洞隐患
*
* @author DB
*/
public final class HTMLFilter {
/**
* regex flag union representing /si modifiers in php
**/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("\"");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
/**
* set of allowed html elements, along with allowed attributes for each element
**/
private final Map<String, List<String>> vAllowed;
/**
* counts of open tags for each (allowable) html element
**/
private final Map<String, Integer> vTagCounts = new HashMap<>();
/**
* html elements which must always be self-closing (e.g. "<img />")
**/
private final String[] vSelfClosingTags;
/**
* html elements which must always have separate opening and closing tags (e.g. "<b></b>")
**/
private final String[] vNeedClosingTags;
/**
* set of disallowed html elements
**/
private final String[] vDisallowed;
/**
* attributes which should be checked for valid protocols
**/
private final String[] vProtocolAtts;
/**
* allowed protocols
**/
private final String[] vAllowedProtocols;
/**
* tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
**/
private final String[] vRemoveBlanks;
/**
* entities allowed within html markup
**/
private final String[] vAllowedEntities;
/**
* flag determining whether comments are allowed in input String.
*/
private final boolean stripComment;
private final boolean encodeQuotes;
/**
* flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
* becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/**
* Default constructor.
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
// no ftp.
vAllowedProtocols = new String[]{"http", "mailto", "https"};
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = false;
}
/**
* Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
@SuppressWarnings("unchecked")
public HTMLFilter(final Map<String, Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
// ---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
// ---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
s = escapeComments(s);
s = balanceHTML(s);
s = checkTags(s);
s = processRemoveBlanks(s);
// s = validateEntities(s);
return s;
}
public boolean isAlwaysMakeTags() {
return alwaysMakeTags;
}
public boolean isStripComments() {
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
// (.*?)
final String match = m.group(1);
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
// 不追加结束标签
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
final StringBuilder sBuilder = new StringBuilder(buf.toString());
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
sBuilder.append("</").append(key).append(">");
}
}
s = sBuilder.toString();
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) {
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) {
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (!inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
// debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
final StringBuilder params = new StringBuilder();
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<>();
final List<String> paramValues = new ArrayList<>();
while (m2.find()) {
paramNames.add(m2.group(1)); // ([a-z0-9]+)
paramValues.add(m2.group(3)); // (.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); // ([a-z0-9]+)
paramValues.add(m3.group(3)); // ([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\"");
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1);
if (s.startsWith("#//")) {
s = "#" + s.substring(3);
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); // ([^&;]*)
final String two = m.group(2); // (?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s) {
if (encodeQuotes) {
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); // (>|^)
final String two = m.group(2); // ([^<]+?)
final String three = m.group(3); // (<|$)
// 不替换双引号为&quot;防止json格式无效 regexReplace(P_QUOTE, "&quot;", two)
m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
}
m.appendTail(buf);
return buf.toString();
} else {
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}

View File

@ -1,51 +0,0 @@
package com.cpop.core.utils.http;
import jakarta.servlet.ServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 通用http工具封装
*
* @author DB
*/
public class HttpHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
/**
* 获取请求体信息失败
* @author DB
* @since 2024/2/1
* @param request 请求
* @return String
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream()) {
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
LOGGER.warn("getBodyString出现问题");
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGGER.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
}

View File

@ -1,376 +0,0 @@
package com.cpop.core.utils.http;
import com.cpop.core.constant.Constants;
import com.cpop.core.utils.StringUtils;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
/**
* 通用http发送方法
*
* @author DB
*/
public class HttpUtils {
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url) {
return sendGet(url, StringUtils.EMPTY);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
return sendGet(url, param, Constants.UTF8);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType) {
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try {
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
log.info("recv - {}", result);
} catch (ConnectException e) {
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception ex) {
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url) {
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
log.info("rev - {}", result);
} catch (ConnectException e) {
log.error("调用HttpUtils.sendPost ConnectException, url=" + url, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendPost IOException, url=" + url, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendPost Exception, url=" + url, e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
log.error("调用in.close Exception, url=" + url, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
log.info("recv - {}", result);
} catch (ConnectException e) {
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param, File file) throws IOException {
URL urlObj = new URL(url);
//连接
HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
String result = null;
con.setDoInput(true);
con.setDoOutput(true);
// post方式不能使用缓存
con.setUseCaches(false);
// 设置请求头信息
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
// 设置边界
String BOUNDARY = "----------" + System.currentTimeMillis();
con.setRequestProperty("Content-Type",
"multipart/form-data; boundary="
+ BOUNDARY);
// 请求正文信息
// 第一部分
StringBuilder sb = new StringBuilder();
// 必须多两道线
sb.append("--");
sb.append(BOUNDARY);
sb.append("\r\n");
sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"").append(file.length()).append("\";filename=\"").append(file.getName()).append("\"\r\n");
sb.append("Content-Type:application/octet-stream\r\n\r\n");
byte[] head = sb.toString().getBytes(StandardCharsets.UTF_8);
// 获得输出流
OutputStream out = new DataOutputStream(con.getOutputStream());
// 输出表头
out.write(head);
// 文件正文部分
// 把文件已流文件的方式 推入到url中
DataInputStream in = new DataInputStream(Files.newInputStream(file.toPath()));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
in.close();
// 结尾部分
// 定义最后数据分隔线
byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8);
out.write(foot);
out.flush();
out.close();
StringBuilder buffer = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
// 定义BufferedReader输入流来读取URL的响应
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
} catch (IOException e) {
System.out.println("发送POST请求出现异常" + e);
e.printStackTrace();
}
return result;
}
public static String sendSSLPost(String url, String param) {
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try {
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null) {
if (!"".equals(ret.trim())) {
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
} catch (ConnectException e) {
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
/**
* 获取请求路径参数
* @param url 请求路径
*/
public static Map<String,Object> getQueryParams(String url) {
try {
Map<String, Object> params = new HashMap<String, Object>();
for (String param : url.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
params.put(key, value);
}
return params;
} catch (UnsupportedEncodingException ex) {
throw new AssertionError(ex);
}
}
/**
* okhttpPost请求
* @param url 地址
* @param jsonBody 请求体
*/
public static Response sendOkHttpPost(String url,String jsonBody) throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.Companion.parse("application/json;charset=utf-8");
RequestBody body = RequestBody.Companion.create(jsonBody, mediaType);
Request request = new Request
.Builder()
.url(url)
.post(body)
.addHeader("Content-Type", "application/json")
.build();
return client.newCall(request).execute();
}
/**
* okhttpGet请求
* @param url 地址
*/
public static Response sendOkHttpGet(String url) throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder().build();
Request request = new Request.Builder().url(url).get().build();
return client.newCall(request).execute();
}
}

View File

@ -1,50 +0,0 @@
package com.cpop.core.utils.ip;
import com.alibaba.fastjson2.JSONObject;
import com.cpop.core.constant.Constants;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
/**
* 获取地址类
*
* @author DB
*/
public class AddressUtils {
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
// IP地址查询
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
@Value("${jambox.address-enabled}")
private static Boolean isAddressEnabled;
// 未知地址
public static final String UN_KNOW = "XX XX";
public static String getRealAddressByIp(String ip) {
// 内网不查询
if (IpUtils.internalIp(ip)) {
return "内网IP";
}
if (isAddressEnabled) {
try {
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
if (StringUtils.isEmpty(rspStr)) {
log.error("获取地理位置异常 {}", ip);
return UN_KNOW;
}
JSONObject obj = JSONObject.parseObject(rspStr);
String region = obj.getString("pro");
String city = obj.getString("city");
return String.format("%s %s", region, city);
} catch (Exception e) {
log.error("获取地理位置异常 {}", ip);
}
}
return UN_KNOW;
}
}

View File

@ -1,196 +0,0 @@
package com.cpop.core.utils.ip;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.html.EscapeUtil;
import jakarta.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 获取IP方法
*
* @author DB
*/
public class IpUtils
{
public static String getIpAddr(HttpServletRequest request)
{
if (request == null)
{
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip);
}
public static boolean internalIp(String ip)
{
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
private static boolean internalIp(byte[] addr)
{
if (StringUtils.isNull(addr) || addr.length < 2)
{
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0)
{
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4)
{
return true;
}
case SECTION_5:
switch (b1)
{
case SECTION_6:
return true;
}
default:
return false;
}
}
/**
* 将IPv4地址转换成字节
*
* @param text IPv4地址
* @return byte 字节
*/
public static byte[] textToNumericFormatV4(String text)
{
if (text.length() == 0)
{
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try
{
long l;
int i;
switch (elements.length)
{
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i)
{
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i)
{
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
}
catch (NumberFormatException e)
{
return null;
}
return bytes;
}
public static String getHostIp()
{
try
{
return InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException e)
{
}
return "127.0.0.1";
}
public static String getHostName()
{
try
{
return InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
}
return "未知";
}
}

View File

@ -1,91 +0,0 @@
package com.cpop.core.utils.text;
import com.cpop.core.utils.StringUtils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author DB
*/
public class CharsetKit {
/**
* ISO-8859-1
*/
public static final String ISO_8859_1 = "ISO-8859-1";
/**
* UTF-8
*/
public static final String UTF_8 = "UTF-8";
/**
* GBK
*/
public static final String GBK = "GBK";
/**
* ISO-8859-1
*/
public static final Charset CHARSET_ISO_8859_1 = StandardCharsets.ISO_8859_1;
/**
* UTF-8
*/
public static final Charset CHARSET_UTF_8 = StandardCharsets.UTF_8;
/**
* GBK
*/
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset) {
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset) {
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset) {
if (null == srcCharset) {
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset) {
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) {
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset() {
return Charset.defaultCharset().name();
}
}

View File

@ -1,854 +0,0 @@
package com.cpop.core.utils.text;
import com.cpop.core.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.Set;
/**
* 类型转换器
*
* @author DB
*/
public class Convert {
/**
* 转换为字符串<br>
* 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static String toStr(Object value, String defaultValue) {
if (null == value) {
return defaultValue;
}
if (value instanceof String) {
return (String) value;
}
return value.toString();
}
/**
* 转换为字符串<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static String toStr(Object value) {
return toStr(value, null);
}
/**
* 转换为字符<br>
* 如果给定的值为null或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Character toChar(Object value, Character defaultValue) {
if (null == value) {
return defaultValue;
}
if (value instanceof Character) {
return (Character) value;
}
final String valueStr = toStr(value, null);
return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
}
/**
* 转换为字符<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Character toChar(Object value) {
return toChar(value, null);
}
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Byte toByte(Object value, Byte defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Byte) {
return (Byte) value;
}
if (value instanceof Number) {
return ((Number) value).byteValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Byte.parseByte(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Byte toByte(Object value) {
return toByte(value, null);
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Short toShort(Object value, Short defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Short) {
return (Short) value;
}
if (value instanceof Number) {
return ((Number) value).shortValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Short.parseShort(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Short toShort(Object value) {
return toShort(value, null);
}
/**
* 转换为Number<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Number toNumber(Object value, Number defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Number) {
return (Number) value;
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return NumberFormat.getInstance().parse(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Number<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Number toNumber(Object value) {
return toNumber(value, null);
}
/**
* 转换为int<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Integer toInt(Object value, Integer defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Integer) {
return (Integer) value;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Integer.parseInt(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为int<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Integer toInt(Object value) {
return toInt(value, null);
}
/**
* 转换为Integer数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String str) {
return toIntArray(",", str);
}
/**
* 转换为Long数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String str) {
return toLongArray(",", str);
}
/**
* 转换为Integer数组<br>
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String split, String str) {
if (StringUtils.isEmpty(str)) {
return new Integer[]{};
}
String[] arr = str.split(split);
final Integer[] ints = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
final Integer v = toInt(arr[i], 0);
ints[i] = v;
}
return ints;
}
/**
* 转换为Long数组<br>
*
* @param split 分隔符
* @param str 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String split, String str) {
if (StringUtils.isEmpty(str)) {
return new Long[]{};
}
String[] arr = str.split(split);
final Long[] longs = new Long[arr.length];
for (int i = 0; i < arr.length; i++) {
final Long v = toLong(arr[i], null);
longs[i] = v;
}
return longs;
}
/**
* 转换为String数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static String[] toStrArray(String str) {
return toStrArray(",", str);
}
/**
* 转换为String数组<br>
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static String[] toStrArray(String split, String str) {
return str.split(split);
}
/**
* 转换为long<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Long toLong(Object value, Long defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Long) {
return (Long) value;
}
if (value instanceof Number) {
return ((Number) value).longValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
// 支持科学计数法
return new BigDecimal(valueStr.trim()).longValue();
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为long<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Long toLong(Object value) {
return toLong(value, null);
}
/**
* 转换为double<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Double toDouble(Object value, Double defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Double) {
return (Double) value;
}
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
// 支持科学计数法
return new BigDecimal(valueStr.trim()).doubleValue();
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为double<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Double toDouble(Object value) {
return toDouble(value, null);
}
/**
* 转换为Float<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Float toFloat(Object value, Float defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Float) {
return (Float) value;
}
if (value instanceof Number) {
return ((Number) value).floatValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Float.parseFloat(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Float<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Float toFloat(Object value) {
return toFloat(value, null);
}
/**
* 转换为boolean<br>
* String支持的值为truefalseyesokno1,0 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Boolean toBool(Object value, Boolean defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
valueStr = valueStr.trim().toLowerCase();
switch (valueStr) {
case "true":
return true;
case "false":
return false;
case "yes":
return true;
case "ok":
return true;
case "no":
return false;
case "1":
return true;
case "0":
return false;
default:
return defaultValue;
}
}
/**
* 转换为boolean<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Boolean toBool(Object value) {
return toBool(value, null);
}
/**
* 转换为Enum对象<br>
* 如果给定的值为空或者转换失败返回默认值<br>
*
* @param clazz Enum的Class
* @param value
* @param defaultValue 默认值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue) {
if (value == null) {
return defaultValue;
}
if (clazz.isAssignableFrom(value.getClass())) {
@SuppressWarnings("unchecked")
E myE = (E) value;
return myE;
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Enum.valueOf(clazz, valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Enum对象<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
*
* @param clazz Enum的Class
* @param value
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) {
return toEnum(clazz, value, null);
}
/**
* 转换为BigInteger<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof BigInteger) {
return (BigInteger) value;
}
if (value instanceof Long) {
return BigInteger.valueOf((Long) value);
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return new BigInteger(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为BigInteger<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigInteger toBigInteger(Object value) {
return toBigInteger(value, null);
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof BigDecimal) {
return (BigDecimal) value;
}
if (value instanceof Long) {
return new BigDecimal((Long) value);
}
if (value instanceof Double) {
return new BigDecimal((Double) value);
}
if (value instanceof Integer) {
return new BigDecimal((Integer) value);
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return new BigDecimal(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value) {
return toBigDecimal(value, null);
}
/**
* 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj) {
return str(obj, CharsetKit.CHARSET_UTF_8);
}
/**
* 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charsetName 字符集
* @return 字符串
*/
public static String str(Object obj, String charsetName) {
return str(obj, Charset.forName(charsetName));
}
/**
* 将对象转为字符串<br>
* 1Byte数组和ByteBuffer会被转换为对应字符串的数组 2对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charset 字符集
* @return 字符串
*/
public static String str(Object obj, Charset charset) {
if (null == obj) {
return null;
}
if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof byte[]) {
return str((byte[]) obj, charset);
} else if (obj instanceof Byte[]) {
byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
return str(bytes, charset);
} else if (obj instanceof ByteBuffer) {
return str((ByteBuffer) obj, charset);
}
return obj.toString();
}
/**
* 将byte数组转为字符串
*
* @param bytes byte数组
* @param charset 字符集
* @return 字符串
*/
public static String str(byte[] bytes, String charset) {
return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
}
/**
* 解码字节码
*
* @param data 字符串
* @param charset 字符集如果此字段为空则解码的结果取决于平台
* @return 解码后的字符串
*/
public static String str(byte[] data, Charset charset) {
if (data == null) {
return null;
}
if (null == charset) {
return new String(data);
}
return new String(data, charset);
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, String charset) {
if (data == null) {
return null;
}
return str(data, Charset.forName(charset));
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, Charset charset) {
if (null == charset) {
charset = Charset.defaultCharset();
}
return charset.decode(data).toString();
}
// ----------------------------------------------------------------------- 全角半角转换
/**
* 半角转全角
*
* @param input String.
* @return 全角字符串.
*/
public static String toSBC(String input) {
return toSBC(input, null);
}
/**
* 半角转全角
*
* @param input String
* @param notConvertSet 不替换的字符集合
* @return 全角字符串.
*/
public static String toSBC(String input, Set<Character> notConvertSet) {
char c[] = input.toCharArray();
for (int i = 0; i < c.length; i++) {
if (null != notConvertSet && notConvertSet.contains(c[i])) {
// 跳过不替换的字符
continue;
}
if (c[i] == ' ') {
c[i] = '\u3000';
} else if (c[i] < '\177') {
c[i] = (char) (c[i] + 65248);
}
}
return new String(c);
}
/**
* 全角转半角
*
* @param input String.
* @return 半角字符串
*/
public static String toDBC(String input) {
return toDBC(input, null);
}
/**
* 替换全角为半角
*
* @param text 文本
* @param notConvertSet 不替换的字符集合
* @return 替换后的字符
*/
public static String toDBC(String text, Set<Character> notConvertSet) {
char c[] = text.toCharArray();
for (int i = 0; i < c.length; i++) {
if (null != notConvertSet && notConvertSet.contains(c[i])) {
// 跳过不替换的字符
continue;
}
if (c[i] == '\u3000') {
c[i] = ' ';
} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
c[i] = (char) (c[i] - 65248);
}
}
String returnString = new String(c);
return returnString;
}
/**
* 数字金额大写转换 先写个完整的然后将如零拾替换成零
*
* @param n 数字
* @return 中文大写数字
*/
public static String digitUppercase(double n) {
String[] fraction = {"", ""};
String[] digit = {"", "", "", "", "", "", "", "", "", ""};
String[][] unit = {{"", "", "亿"}, {"", "", "", ""}};
String head = n < 0 ? "" : "";
n = Math.abs(n);
String s = "";
for (int i = 0; i < fraction.length; i++) {
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
}
if (s.length() < 1) {
s = "";
}
int integerPart = (int) Math.floor(n);
for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
String p = "";
for (int j = 0; j < unit[1].length && n > 0; j++) {
p = digit[integerPart % 10] + unit[1][j] + p;
integerPart = integerPart / 10;
}
s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "") + unit[0][i] + s;
}
return head + s.replaceAll("(零.)*零元", "").replaceFirst("(零.)+", "").replaceAll("(零.)+", "").replaceAll("^整$", "零元整");
}
}

View File

@ -1,77 +0,0 @@
package com.cpop.core.utils.text;
import com.cpop.core.utils.StringUtils;
/**
* 字符串格式化
*
* @author DB
*/
public class StrFormatter {
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray) {
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++) {
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1) {
if (handledPosition == 0) {
return strPattern;
} else { // 字符串模板剩余部分不再包含占位符加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
} else {
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
// 转义符之前还有一个转义符占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
} else {
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
} else {
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

View File

@ -1,44 +0,0 @@
package com.cpop.core.utils.uuid;
/**
* ID生成器工具类
*
* @author DB
*/
public class IdUtils {
/**
* 获取随机UUID
*
* @return 随机UUID
*/
public static String randomUUID() {
return UUID.randomUUID().toString();
}
/**
* 简化的UUID去掉了横线
*
* @return 简化的UUID去掉了横线
*/
public static String simpleUUID() {
return UUID.randomUUID().toString(true);
}
/**
* 获取随机UUID使用性能更好的ThreadLocalRandom生成UUID
*
* @return 随机UUID
*/
public static String fastUUID() {
return UUID.fastUUID().toString();
}
/**
* 简化的UUID去掉了横线使用性能更好的ThreadLocalRandom生成UUID
*
* @return 简化的UUID去掉了横线
*/
public static String fastSimpleUUID() {
return UUID.fastUUID().toString(true);
}
}

View File

@ -1,92 +0,0 @@
package com.cpop.core.utils.uuid;
import com.cpop.core.utils.StringUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author DB 序列生成类
*/
public class Seq {
/**
* 通用序列类型
*/
public static final String commSeqType = "COMMON";
/**
* 上传序列类型
*/
public static final String uploadSeqType = "UPLOAD";
/**
* 通用接口序列数
*/
private static AtomicInteger commSeq = new AtomicInteger(1);
/**
* 上传接口序列数
*/
private static AtomicInteger uploadSeq = new AtomicInteger(1);
/**
* 机器标识
*/
private static final String machineCode = "A";
/**
* 获取通用序列号
*
* @return 序列值
*/
public static String getId() {
return getId(commSeqType);
}
/**
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
*
* @return 序列值
*/
public static String getId(String type) {
AtomicInteger atomicInt = commSeq;
if (uploadSeqType.equals(type)) {
atomicInt = uploadSeq;
}
return getId(atomicInt, 3);
}
/**
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
*
* @param atomicInt 序列数
* @param length 数值长度
* @return 序列值
*/
public static String getId(AtomicInteger atomicInt, int length) {
String result = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
result += machineCode;
result += getSeq(atomicInt, length);
return result;
}
/**
* 序列循环递增字符串[1, 10 (length)幂次方), 用0左补齐length位数
*
* @return 序列值
*/
private synchronized static String getSeq(AtomicInteger atomicInt, int length) {
// 先取值再+1
int value = atomicInt.getAndIncrement();
// 如果更新后值>=10 (length)幂次方则重置为1
int maxSeq = (int) Math.pow(10, length);
if (atomicInt.get() >= maxSeq) {
atomicInt.set(1);
}
// 转字符串用0左补齐
return StringUtils.padL(value, length);
}
}

View File

@ -1,447 +0,0 @@
package com.cpop.core.utils.uuid;
import com.cpop.core.base.exception.UtilException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* 提供通用唯一识别码universally unique identifierUUID实现
*
* @author DB
*/
public final class UUID implements java.io.Serializable, Comparable<UUID> {
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*/
private static class Holder {
static final SecureRandom numberGenerator = getSecureRandom();
}
/**
* 此UUID的最高64有效位
*/
private final long mostSigBits;
/**
* 此UUID的最低64有效位
*/
private final long leastSigBits;
/**
* 私有构造
*
* @param data 数据
*/
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++) {
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8; i < 16; i++) {
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使用指定的数据构造新的 UUID
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64
* @param leastSigBits 用于 {@code UUID} 的最低有效 64
*/
public UUID(long mostSigBits, long leastSigBits) {
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的本地线程伪随机数生成器生成该 UUID
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastUUID() {
return randomUUID(false);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的强伪随机数生成器生成该 UUID
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID() {
return randomUUID(true);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的强伪随机数生成器生成该 UUID
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID(boolean isSecure) {
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
//clear version
randomBytes[6] &= 0x0f;
//set to version 4
randomBytes[6] |= 0x40;
//clear variant
randomBytes[8] &= 0x3f;
//set to IETF variant
randomBytes[8] |= 0x80;
return new UUID(randomBytes);
}
/**
* 根据指定的字节数组获取类型 3基于名称的UUID 的静态工厂
*
* @param name 用于构造 UUID 的字节数组
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameUUIDFromBytes(byte[] name) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
//clear version
md5Bytes[6] &= 0x0f;
//set to version 3
md5Bytes[6] |= 0x30;
//clear variant
md5Bytes[8] &= 0x3f;
//set to IETF variant
md5Bytes[8] |= 0x80;
return new UUID(md5Bytes);
}
/**
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}
*
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name {@link #toString} 中描述的字符串表示形式不符抛出此异常
*/
public static UUID fromString(String name) {
String[] components = name.split("-");
if (components.length != 5) {
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0; i < 5; i++) {
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* 返回此 UUID 128 位值中的最低有效 64
*
* @return UUID 128 位值中的最低有效 64
*/
public long getLeastSignificantBits() {
return leastSigBits;
}
/**
* 返回此 UUID 128 位值中的最高有效 64
*
* @return UUID 128 位值中最高有效 64
*/
public long getMostSignificantBits() {
return mostSigBits;
}
/**
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的
* <p>
* 版本号具有以下含意:
* <ul>
* <li>1 基于时间的 UUID
* <li>2 DCE 安全 UUID
* <li>3 基于名称的 UUID
* <li>4 随机生成的 UUID
* </ul>
*
* @return {@code UUID} 的版本号
*/
public int version() {
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* 与此 {@code UUID} 相关联的变体号变体号描述 {@code UUID} 的布局
* <p>
* 变体号具有以下含意
* <ul>
* <li>0 NCS 向后兼容保留
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 用于此类
* <li>6 保留微软向后兼容
* <li>7 保留供以后定义使用
* </ul>
*
* @return {@code UUID} 相关联的变体号
*/
public int variant() {
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* 与此 UUID 相关联的时间戳值
*
* <p>
* 60 位的时间戳值根据此 {@code UUID} time_lowtime_mid time_hi 字段构造<br>
* 所得到的时间戳以 100 毫微秒为单位 UTC通用协调时间 1582 10 15 日零时开始
*
* <p>
* 时间戳值仅在在基于时间的 UUID version 类型为 1中才有意义<br>
* 如果此 {@code UUID} 不是基于时间的 UUID则此方法抛出 UnsupportedOperationException
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 1 UUID
*/
public long timestamp() throws UnsupportedOperationException {
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48
| ((mostSigBits >> 16) & 0x0FFFFL) << 32
| mostSigBits >>> 32;
}
/**
* 与此 UUID 相关联的时钟序列值
*
* <p>
* 14 位的时钟序列值根据此 UUID clock_seq 字段构造clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性
* <p>
* {@code clockSequence} 值仅在基于时间的 UUID version 类型为 1中才有意义 如果此 UUID 不是基于时间的 UUID则此方法抛出
* UnsupportedOperationException
*
* @return {@code UUID} 的时钟序列
* @throws UnsupportedOperationException 如果此 UUID version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException {
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* 与此 UUID 相关的节点值
*
* <p>
* 48 位的节点值根据此 UUID node 字段构造此字段旨在用于保存机器的 IEEE 802 地址该地址用于生成此 UUID 以保证空间唯一性
* <p>
* 节点值仅在基于时间的 UUID version 类型为 1中才有意义<br>
* 如果此 UUID 不是基于时间的 UUID则此方法抛出 UnsupportedOperationException
*
* @return {@code UUID} 的节点值
* @throws UnsupportedOperationException 如果此 UUID version 不为 1
*/
public long node() throws UnsupportedOperationException {
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* 返回此{@code UUID} 的字符串表现形式
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return {@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString() {
return toString(false);
}
/**
* 返回此{@code UUID} 的字符串表现形式
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple 是否简单模式简单模式为不带'-'的UUID字符串
* @return {@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple) {
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (!isSimple) {
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (!isSimple) {
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (!isSimple) {
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (!isSimple) {
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
/**
* 返回此 UUID 的哈希码
*
* @return UUID 的哈希码值
*/
@Override
public int hashCode() {
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
/**
* 将此对象与指定对象比较
* <p>
* 当且仅当参数不为 {@code null}而是一个 UUID 对象具有与此 UUID 相同的 varriant包含相同的值每一位均相同结果才为 {@code true}
*
* @param obj 要与之比较的对象
* @return 如果对象相同则返回 {@code true}否则返回 {@code false}
*/
@Override
public boolean equals(Object obj) {
if ((null == obj) || (obj.getClass() != UUID.class)) {
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
// Comparison Operations
/**
* 将此 UUID 与指定的 UUID 比较
*
* <p>
* 如果两个 UUID 不同且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段则第一个 UUID 大于第二个 UUID
*
* @param val 与此 UUID 比较的 UUID
* @return 在此 UUID 小于等于或大于 val 分别返回 -10 1
*/
@Override
public int compareTo(UUID val) {
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 :
(this.mostSigBits > val.mostSigBits ? 1 :
(Long.compare(this.leastSigBits, val.leastSigBits))));
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val
* @param digits
* @return
*/
private static String digits(long val, int digits) {
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase() {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom}类提供加密的强随机数生成器 (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom() {
try {
return SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new UtilException(e);
}
}
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数能够解决多个线程发生的竞争争夺
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom() {
return ThreadLocalRandom.current();
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<version>1.1.2</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Generator</artifactId>

View File

@ -1,6 +1,6 @@
package com.cpop.generator;
import com.cpop.core.utils.StringUtils;
import cn.hutool.core.util.StrUtil;
import com.cpop.core.base.entity.BaseEntity;
import com.cpop.core.base.entity.BaseInsertListener;
import com.cpop.core.base.entity.BaseUpdateListener;
@ -27,31 +27,31 @@ public class CpopGenerator {
* 数据库 URL
*/
// private static final String URL = "jdbc:mysql://localhost:3306/cpop-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
private static final String URL = "jdbc:mysql://localhost:3306/cpop_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
private static final String URL = "jdbc:mysql://bj-cynosdbmysql-grp-anccz88g.sql.tencentcdb.com:24808/cpop_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
/**
* 数据库用户名
*/
private static final String USERNAME = "root";
private static final String USERNAME = "cpop_dev";
/**
* 数据库密码
*/
private static final String PASSWORD = "Admin@123";
private static final String PASSWORD = "Ch5WkZRsCATsnMXw";
//private static final String PASSWORD = "Customer0401";
/**
* 输出路径
*/
private static final String EXPORT_URL = "/Cpop-Jambox";
private static final String EXPORT_URL = "/Cpop-Oam";
/**
* 模块
*/
private static final String EXPORT_ITEM = "jambox";
private static final String EXPORT_ITEM = "oam";
/**
* 表前缀
*/
private static final String TABLE_PREFIX = "cp_j_";
private static final String TABLE_PREFIX = "cp_sys_";
/**
* 主入口
@ -87,7 +87,7 @@ public class CpopGenerator {
System.out.println("请输入表名,多个英文逗号分割:");
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
if (StrUtil.isNotBlank(ipt)) {
return ipt;
}
}

View File

@ -5,7 +5,7 @@
#set(entityClassName = table.buildEntityClassName())
package #(packageConfig.entityPackage);
#for(importClass : table.buildImports())
#for(importClass : table.buildImports(false))
import #(importClass);
#end
#if(withActiveRecord)

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<relativePath>../../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Jambox-Web</artifactId>
<name>Cpop-Jambox-Web</name>
<description>果酱盒子-Web</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Jambox</artifactId>
</dependency>
<!--Mysql-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>Cpop-Oam-Web</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,20 +0,0 @@
package com.cpop.jambox.web;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @author DB
*/
@SpringBootApplication(scanBasePackages = {"com.cpop.**"})
@MapperScan("com.cpop.**.mapper")
@EnableAsync
public class CpopJamboxWebApplication {
public static void main(String[] args) {
SpringApplication.run(CpopJamboxWebApplication.class, args);
}
}

View File

@ -1,80 +0,0 @@
# 项目相关配置
cpop:
# 文件路径 示例( Windows配置W:/WorkSpace/java/uploadPathLinux配置 /home/baseFramework/uploadPath
profile: E:/Cpop/uploadPath
jwt:
#白名单
whiteList: /login,/miniLogin,/getCaptcha,/profile/**,/doc.html,/webjars/**,/favicon.ico,/v2/api-docs/**,/swagger-resources
gateway:
rsa-keypair:
# 公钥文件
publicKeyFile: E:\Cpop\Cpop-Union\Cpop-Core\src\main\resources\static\keyPair\publicKey
# 公钥文件
privateKeyFile: E:\Cpop\Cpop-Union\Cpop-Core\src\main\resources\static\keyPair\privateKey
# DataSource Config
spring:
application:
name: Cpop-Jambox-Dev
datasource:
url: jdbc:mysql://localhost:3306/cpop-union?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: root
#redis配置
redis:
#地址
host: localhost
#端口
port: 6379
#数据库
database: 0
#密码
password:
#连接超时
timeout: 5000
lettuce:
pool:
#
min-idle: 0
#
max-idle: 8
#
max-active: 8
#
max-wait: -1ms
data:
mongodb:
host: localhost
port: 27017
database: cpop-union
server:
port: 9421
servlet:
context-path: /Cpop-Jambox
#Mybatis-Flex
mybatis-flex:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
knife4j:
enable: true
openapi:
title: PuPu-OAM开发API
description: PuPu-OAM开发API
email:
concat: DB
url: https://api.jamboxsys.com
version: 1.0.0
license: Apache 2.0
license-url: https://stackoverflow.com/
terms-of-service-url: https://api.jamboxsys.com
group:
#jambox
jambox:
group-name: Jambox
api-rule: package
api-rule-resources:
- com.cpop.jambox

View File

@ -1,60 +0,0 @@
# 项目相关配置
cpop:
# 文件路径 示例( Windows配置W:/WorkSpace/java/uploadPathLinux配置 /home/baseFramework/uploadPath
profile: /root/jambox-union/jambox-oam/uploadPath/upload
jwt:
#白名单
whiteList: /login,/getCaptcha,/profile/**
#拦截
gateway:
rsa-keypair:
# 公钥文件
publicKeyFile: /root/jambox-union/jambox-oam/script/secretKey/publicKey
# 公钥文件
privateKeyFile: /root/jambox-union/jambox-oam/script/secretKey/privateKey
# DataSource Config
spring:
application:
name: Cpop-Jambox-Prod
datasource:
url: jdbc:mysql://sh-cynosdbmysql-grp-fggo83js.sql.tencentcdb.com:20965/cpop-union?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: Customer0401
#redis配置
redis:
#地址
host: 106.52.49.102
#端口
port: 6333
#数据库
database: 5
#密码
password: Jambox.123*
#连接超时
timeout: 5000
lettuce:
pool:
#
min-idle: 0
#
max-idle: 8
#
max-active: 8
#
max-wait: -1ms
data:
mongodb:
host: localhost
port: 27017
database: rock-blade
server:
port: 9421
servlet:
context-path: /Cpop-Jambox
#Mybatis-Flex
mybatis-flex:
configuration:
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl

View File

@ -1,81 +0,0 @@
# 项目相关配置
cpop:
# 文件路径 示例( Windows配置W:/WorkSpace/java/uploadPathLinux配置 /home/baseFramework/uploadPath
profile: /root/jambox-union/jambox-oam/uploadPath/upload
jwt:
#白名单
whiteList: /login,/getCaptcha,/profile/**,/doc.html,/webjars/**,/favicon.ico,/v2/api-docs/**,/swagger-resources
#拦截
gateway:
rsa-keypair:
# 公钥文件
publicKeyFile: /root/jambox-union/jambox-oam/script/secretKey/publicKey
# 公钥文件
privateKeyFile: /root/jambox-union/jambox-oam/script/secretKey/privateKey
# DataSource Config
spring:
application:
name: Cpop-Jambox-Test
datasource:
url: jdbc:mysql://sh-cynosdbmysql-grp-fggo83js.sql.tencentcdb.com:20965/cpop-union?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: Customer0401
#redis配置
redis:
#地址
host: 106.52.49.102
#端口
port: 6333
#数据库
database: 5
#密码
password: Jambox.123*
#连接超时
timeout: 5000
lettuce:
pool:
#
min-idle: 0
#
max-idle: 8
#
max-active: 8
#
max-wait: -1ms
data:
mongodb:
host: localhost
port: 27017
database: rock-blade
server:
port: 9421
servlet:
context-path: /Cpop-Jambox
#Mybatis-Flex
mybatis-flex:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
knife4j:
enable: true
openapi:
title: Cpop-Jambox开发API
description: Cpop-Jambox开发API
email:
concat: DB
url: https://api.jamboxsys.com
version: 1.0.0
license: Apache 2.0
license-url: https://stackoverflow.com/
terms-of-service-url: https://api.jamboxsys.com
group:
#jambox
jambox:
group-name: Jambox
api-rule: package
api-rule-resources:
- com.cpop.jambox

View File

@ -1,118 +0,0 @@
# 项目相关配置
cpop:
# 名称
name: Cpop-Jambox
# 版本
version: 1.0.0
#JWT
jwt:
#密钥
secret: abcdefghijklmnopqrstuvwxyz
#过期时间
expire: 604800
#token头
header: Authorization
#拦截
gateway:
rsa-keypair:
# 加密方式
algorithm: RSA
# 初始化大小
keySize: 2048
#Spring
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
servlet:
multipart:
#文件最大传输
max-file-size: 1024MB
max-request-size: 300MB
profiles:
active: dev,jambox,api,sdk
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
#hikari数据源特性配置
hikari:
#最大连接数,默认值10.
maximum-pool-size: 10
#最小空闲连接默认值10.
minimum-idle: 10
#连接超时时间(毫秒),默认值30秒.
connection-timeout: 30000
#空闲连接超时时间默认值600000(10分钟),只有空闲连接数大于最大连接数且空闲时间超过该值,才会被释放;如果大于等于 max-lifetime 且 max-lifetime>0,则会被重置为0.
idle-timeout: 600000
#连接最大存活时间,默认值30分钟.设置应该比mysql设置的超时时间短
max-lifetime: 3000000
#连接测试查询
connection-test-query: select 1
messages:
#i18n
basename: static/i18n/messages
encoding: UTF-8
cacheDuration: 3600
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: embedded
#定时任务启动开关true-开 false-关
auto-startup: true
#延迟1秒启动定时任务
startup-delay: 1s
#启动时更新己存在的Job
overwrite-existing-jobs: true
properties:
org:
quartz:
scheduler:
instanceName: CpopJamboxScheduler
instanceId: AUTO
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: false
misfireThreshold: 12000
clusterCheckinInterval: 15000
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 1
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
#Mybatis-Flex
mybatis-flex:
global-config:
key-config:
key-type: generator
value: snowFlakeId
# 逻辑删除数据存在标记值 默认值:0
normal-value-of-logic-delete: 0
# 逻辑删除数据删除标记值 默认值:0
deleted-value-of-logic-delete: 1
# 全局逻辑删除默认字段
logic-delete-column: is_delete
# 线程池配置参数
task:
pool:
# 设置核心线程数
corePoolSize: 10
# 设置最大线程数
maxPoolSize: 20
# 设置空闲线程存活时间(秒
keepAliveSeconds: 300
# 设置队列容量
queueCapacity: 100
# 设置线程名称前缀
threadNamePrefix: "Cpop-Jambox-AsyncNotify-"
# 设置线程池等待终止时间(秒)
awaitTerminationSeconds: 60
logging:
level:
#swagger日志
springfox: error

View File

@ -1,4 +0,0 @@
#\u767B\u5F55\u4FE1\u606F
#\u7CFB\u7EDF\u57FA\u7840\u4FE1\u606F
i18n_baseInfo_success=Success
i18n_baseInfo_failed=Failed

View File

@ -1,4 +0,0 @@
#\u767B\u5F55\u4FE1\u606F
#\u7CFB\u7EDF\u57FA\u7840\u4FE1\u606F
i18n_baseInfo_success=\u6210\u529F
i18n_baseInfo_failed=\u5931\u8D25

View File

@ -1,13 +0,0 @@
package com.cpop.jambox.web;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class CpopJamboxWebApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.1.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Jambox</artifactId>
<name>Cpop-Jambox</name>
<description>果酱</description>
<dependencies>
<!--核心包-->
<dependency>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Core</artifactId>
</dependency>
<!--系统包-->
<dependency>
<groupId>com.cpop</groupId>
<artifactId>Cpop-System</artifactId>
</dependency>
<!--支付-->
<dependency>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Pay</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,93 +0,0 @@
/*
Navicat Premium Data Transfer
Source Server : Localhost
Source Server Type : MySQL
Source Server Version : 80032
Source Host : localhost:3306
Source Schema : cpop-union
Target Server Type : MySQL
Target Server Version : 80032
File Encoding : 65001
Date: 15/09/2023 15:04:20
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for pp_j_brand
-- ----------------------------
DROP TABLE IF EXISTS `cp_j_brand`;
CREATE TABLE `cp_j_brand` (
`id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
`brand_cloud_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '云函数id',
`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '品牌名',
`background_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '背景地址',
`consultant_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '顾问名',
`open_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'openId',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`create_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人id',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`update_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人id',
`is_delete` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除(0否1是)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '品牌表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for pp_j_brand_staff
-- ----------------------------
DROP TABLE IF EXISTS `cp_j_brand_staff`;
CREATE TABLE `cp_j_brand_staff` (
`id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
`brand_staff_cloud_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '云id',
`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
`phone_number` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
`position` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '身份(定位)',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`create_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人id',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`update_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人id',
`is_delete` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除(0否1是)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '品牌管理员表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for pp_j_brand_staff_mid_campus
-- ----------------------------
DROP TABLE IF EXISTS `cp_j_brand_staff_mid_campus`;
CREATE TABLE `cp_j_brand_staff_mid_campus` (
`brand_staff_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '品牌管理员id',
`brand_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '品牌id',
`campus_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '校区id',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`create_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人id',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`update_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人id'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '管理员-品牌-校区表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for pp_j_campus
-- ----------------------------
DROP TABLE IF EXISTS `cp_j_campus`;
CREATE TABLE `cp_j_campus` (
`id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
`campus_cloud_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '云校区id',
`brand_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '品牌id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '校区名',
`responsible_person` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '负责人',
`responsible_person_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '负责人手机号',
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址',
`open_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'openId',
`expire` datetime(0) NULL DEFAULT NULL COMMENT '到期时间',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`create_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人id',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`update_user_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人id',
`is_delete` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除(0否1是)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '校区表' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -1,174 +0,0 @@
SET NAMES utf8mb4;
--
-- Set default database
--
USE cpop_test;
DROP TABLE IF EXISTS `cp_j_web_product`;
DROP TABLE IF EXISTS `cp_j_web_navigation`;
DROP TABLE IF EXISTS `cp_j_web_development`;
DROP TABLE IF EXISTS `cp_j_web_cooperation_type`;
DROP TABLE IF EXISTS `cp_j_web_cooperation`;
DROP TABLE IF EXISTS `cp_j_web_company_intro`;
DROP TABLE IF EXISTS `cp_j_web_business_intro`;
DROP TABLE IF EXISTS `cp_j_web_business_data`;
--
-- Create table `cp_j_web_product`
--
CREATE TABLE cp_j_web_product (
id VARCHAR(48) NOT NULL,
product_name VARCHAR(255) DEFAULT NULL COMMENT '产品名称',
img_url TEXT DEFAULT NULL COMMENT '图片',
intro TEXT DEFAULT NULL COMMENT '产品介绍',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 核心产品表';
--
-- Create table `cp_j_web_navigation`
--
CREATE TABLE cp_j_web_navigation (
id VARCHAR(48) NOT NULL,
navigation_name VARCHAR(50) DEFAULT NULL COMMENT '导航栏名称',
path VARCHAR(50) DEFAULT NULL COMMENT '路径',
parent_id INT DEFAULT NULL COMMENT '父级ID',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 导航栏表';
--
-- Create table `cp_j_web_development`
--
CREATE TABLE cp_j_web_development (
id VARCHAR(48) NOT NULL,
title VARCHAR(100) DEFAULT NULL COMMENT '标题',
img_url TEXT DEFAULT NULL COMMENT '图片',
link VARCHAR(255) DEFAULT NULL COMMENT '跳转链接',
publish_time DATETIME DEFAULT NULL COMMENT '发布时间',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 发展历程表';
--
-- Create table `cp_j_web_cooperation_type`
--
CREATE TABLE cp_j_web_cooperation_type (
id VARCHAR(48) NOT NULL,
type_name VARCHAR(255) DEFAULT NULL COMMENT '种类名称',
sort INT DEFAULT NULL COMMENT '排序',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 合作类别表';
--
-- Create table `cp_j_web_cooperation`
--
CREATE TABLE cp_j_web_cooperation (
id VARCHAR(48) NOT NULL,
img_url TEXT DEFAULT NULL COMMENT '图片',
type_id VARCHAR(48) DEFAULT NULL COMMENT '合作类别id',
sort INT DEFAULT NULL COMMENT '排序',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 合作平台表';
--
-- Create table `cp_j_web_company_intro`
--
CREATE TABLE cp_j_web_company_intro (
id VARCHAR(48) NOT NULL,
title VARCHAR(255) DEFAULT NULL COMMENT '标题',
content VARCHAR(255) DEFAULT NULL COMMENT '内容',
img_one TEXT DEFAULT NULL COMMENT '图片一',
img_two TEXT DEFAULT NULL COMMENT '图片二',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 公司简介表';
--
-- Create table `cp_j_web_business_intro`
--
CREATE TABLE cp_j_web_business_intro (
id VARCHAR(48) NOT NULL,
intro TEXT DEFAULT NULL COMMENT '业务介绍',
img_url TEXT DEFAULT NULL COMMENT '图片',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 业务介绍表';
--
-- Create table `cp_j_web_business_data`
--
CREATE TABLE cp_j_web_business_data (
id VARCHAR(48) NOT NULL,
data_name VARCHAR(50) DEFAULT NULL COMMENT '数据名称',
data VARCHAR(50) DEFAULT NULL COMMENT '数据',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_user_id VARCHAR(48) DEFAULT NULL COMMENT '创建人id',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_user_id VARCHAR(48) DEFAULT NULL COMMENT '更新人id',
is_delete TINYINT DEFAULT NULL COMMENT '逻辑删除0否1是',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '果酱模块化官网 业务数据表';

View File

@ -1,154 +0,0 @@
package com.cpop.jambox.business.bo;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-16 16:29
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "CardTemplateUnionBo对象", description = "课卡模板统一入口")
public class CardTemplateUnionBo {
/**
* 主键
*/
@ApiModelProperty(value = "主键")
private String id;
/**
* 旧课卡模板id
*/
@ApiModelProperty(value = "旧课卡模板id")
private String oldTemplateId;
/**
* 云品牌id
*/
@ApiModelProperty(value = "云品牌id")
private String brandCloudId;
/**
* 云校区id
*/
@ApiModelProperty(value = "云校区id")
private String storeCloudId;
/**
* 模板名
*/
@NotBlank(message = "模板名不能为空")
@ApiModelProperty(value = "模板名",required = true)
private String name;
/**
* 有效日期数
*/
@ApiModelProperty(value = "有效日期数")
private Integer validDay;
/**
* 结束日期
*/
@ApiModelProperty(value = "结束日期")
private LocalDate endDate;
/**
* 价格
*/
@NotNull(message = "价格不能为空")
@ApiModelProperty(value = "价格")
private BigDecimal price;
/**
* 课时
*/
@ApiModelProperty("课时")
private Integer classNumber;
/**
* 周预约数
*/
@ApiModelProperty(value = "周预约数")
private Integer weekAppointment;
/**
* 日预约数
*/
@ApiModelProperty(value = "日预约数")
private Integer dayAppointment;
/**
* 缓冲天数
*/
@ApiModelProperty(value = "缓冲天数")
private Integer bufferDay;
/**
* 模板类型(0:课时卡,1:时限卡,2:储值卡)
*/
@ApiModelProperty(value = "模板类型(0:课时卡,1:时限卡,2:储值卡)")
private Integer templateType;
/**
* 使用范围
*/
@ApiModelProperty(value = "使用范围(旧Type字段)")
private String scopeUse;
/**
* 支付类型(0:微信支付;1:先学后付次付;2:旧放心学合约支付;3:数字人民币支付;4:线下支付;5:先学后付月付;)
*/
@NotEmpty(message = "支付类型不能为空")
@ApiModelProperty(value = "支付类型(0:微信支付;1:先学后付次付;2:旧放心学合约支付;3:数字人民币支付;4:线下支付;5:先学后付月付;)")
private List<Integer> payType;
/**
* 是否是会员(0否1是)
*/
@ApiModelProperty(value = "是否是会员(0否1是)")
private Boolean isMember;
/**
* 是否是引流卡
*/
@ApiModelProperty(value = "是否是引流卡(0否1是)")
private Boolean isDrainage;
/**
* 先学后付支付
*/
@ApiModelProperty("先学后付支付(次付)")
private LearnNowPayLaterPlanBo learnNowPayLaterPay;
/**
* 先学后付支付
*/
@ApiModelProperty("先学后付(月付)")
private LearnNowPayLaterPlanBo learnNowPayLaterMonthPay;
/**
* 放心学旧合同
*/
@ApiModelProperty("放心学旧合同")
private EasyLearnOldContractBo easyLearnOldContract;
/**
* 放心学数币
*/
@ApiModelProperty("放心学数币")
private EasyLearnDigitalCurrencyBo easyLearnDigitalCurrency;
}

View File

@ -1,31 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-19 9:44
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "EasyLearnDigitalCurrencyBo对象", description = "放心学数币参数")
public class EasyLearnDigitalCurrencyBo {
/**
* 是否是数币活动
*/
private Boolean isActivity;
/**
* 活动码
*/
private String activityCode;
/**
* 活动描述
*/
private String activityDesc;
}

View File

@ -1,37 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-19 9:36
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "EasyLearnOldContractBo对象", description = "放心学旧合同参数")
public class EasyLearnOldContractBo {
/**
* 期数
*/
@ApiModelProperty("期数")
private Integer stageNum;
/**
* 押金
*/
@ApiModelProperty("押金")
private BigDecimal deposit;
/**
* 首期缓冲天数
*/
@ApiModelProperty("首期缓冲天数")
private Integer firstBufferDay;
}

View File

@ -1,58 +0,0 @@
package com.cpop.jambox.business.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2023-12-15 9:26
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "EasyLearnPageBo对象", description = "放心学分页查询参数")
public class EasyLearnPageBo {
/**
* 结束日期
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "结束日期")
private LocalDate endDate;
/**
* 开始日期
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "开始日期")
private LocalDate startDate;
/**
* 顾问
*/
@ApiModelProperty(value = "顾问")
private String staffName;
/**
* 品牌与校区模糊查询
*/
@ApiModelProperty(value = "品牌与校区模糊查询")
private String brandOrStore;
/**
* 订单类型(0先学后付;1月付;2微信支付;3数币支付;4机构会员)
*/
@NotNull(message = "类型不能为空")
@ApiModelProperty(value = "类型(0先学后付;1月付;2微信支付;3数币支付;4机构会员)",required = true)
private Integer orderType;
}

View File

@ -1,89 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-09 9:15
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "EasyLearnUnifiedPayBo对象", description = "统一支付参数")
public class EasyLearnUnifiedPayBo {
/**
* 品牌或校区id
*/
@NotBlank(message = "云品牌或云校区id不能为空")
@ApiModelProperty(value = "云品牌或云校区id",required = true)
private String brandOrStoreCloudId;
/**
* 联合支付外部订单id
*/
@NotBlank(message = "联合支付外部订单id不能为空")
@ApiModelProperty(value = "联合支付外部订单id",required = true)
private String unionPayOutOrderId;
/**
* 客户名
*/
@NotBlank(message = "客户名不能为空")
@ApiModelProperty(value = "客户名",required = true)
private String customerName;
/**
* 客户电话
*/
@NotBlank(message = "客户电话不能为空")
@ApiModelProperty(value = "客户电话",required = true)
private String customerPhone;
/**
* 总金额
*/
@NotNull(message = "总金额不能为空")
@ApiModelProperty(value = "总金额",required = true)
private BigDecimal totalAmount;
/**
* 总支付金额
*/
@NotNull(message = "总支付金额不能为空")
@ApiModelProperty(value = "总支付金额",required = true)
private BigDecimal totalPayAmount;
/**
* 订单类型
*/
@NotNull(message = "联合支付类型不能为空")
@ApiModelProperty(value = "联合支付类型(PREPAYMENT:预付;REPAYMENT:还款;MEMBER:会员)",required = true)
private String easyLearnUnionPay;
/**
* 分账比率
*/
@ApiModelProperty(value = "分账比率(不传不分帐)")
private Double rate;
/**
* openId
*/
@NotBlank(message = "openId不能为空")
@ApiModelProperty(value = "openId", required = true)
private String openId;
/**
* 订单名
*/
@ApiModelProperty("订单内容(课卡名/商品名)")
private String orderContent;
}

View File

@ -1,97 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author DB
* @version 1.0.0
* @since 2023-12-28 15:44
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "EasyLearnUnionPayBo对象", description = "统一支付参数")
public class EasyLearnUnionPayBo {
/**
* 品牌或校区id
*/
@NotBlank(message = "云品牌或云校区id不能为空")
@ApiModelProperty(value = "云品牌或云校区id",required = true)
private String brandOrStoreCloudId;
/**
* 联合支付外部订单id
*/
@NotBlank(message = "联合支付外部订单id不能为空")
@ApiModelProperty(value = "联合支付外部订单id",required = true)
private String unionPayOutOrderId;
/**
* 客户名
*/
@NotBlank(message = "客户名不能为空")
@ApiModelProperty(value = "客户名",required = true)
private String customerName;
/**
* 客户电话
*/
@NotBlank(message = "客户电话不能为空")
@ApiModelProperty(value = "客户电话",required = true)
private String customerPhone;
/**
* 总金额
*/
@NotNull(message = "总金额不能为空")
@ApiModelProperty(value = "总金额",required = true)
private BigDecimal totalAmount;
/**
* 总支付金额
*/
@NotNull(message = "总支付金额不能为空")
@ApiModelProperty(value = "总支付金额",required = true)
private BigDecimal totalPayAmount;
/**
* 订单类型
*/
@NotBlank(message = "联合支付类型不能为空")
@ApiModelProperty(value = "联合支付类型(WX_PAY:微信支付;PREPAYMENT:预付;REPAYMENT:还款;MEMBER:会员)",required = true)
private String easyLearnUnionPay;
/**
* 分账比率
*/
@ApiModelProperty(value = "分账比率(不传不分帐)")
private Double rate;
/**
* openId
*/
@NotBlank(message = "openId不能为空")
@ApiModelProperty(value = "openId", required = true)
private String openId;
/**
* 订单名
*/
@ApiModelProperty("订单内容(课卡名/商品名)")
private String orderContent;
/**
* 顾问
*/
@ApiModelProperty("顾问")
private String counselor;
}

View File

@ -1,114 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-08 9:23
*/
@Data
@ApiModel(value = "先学后付次付")
public class LearnNowPayLaterOncePayDto {
/**
* 支付分计划名称
*/
@NotBlank(message = "支付分计划名称不能为空")
@ApiModelProperty(value = "支付分计划名称", required = true)
private String planName;
/**
* 支付分计划有效期(单位天)
*/
@NotNull(message = "支付分计划有效期不能为空")
@ApiModelProperty(value = "支付分计划有效期(单位天)", required = true)
private Integer planDuration;
/**
* 支付分计划扣费次数
*/
@NotNull(message = "支付分计划扣费次数不能为空")
@ApiModelProperty(value = "支付分计划扣费次数", required = true)
private Integer deductionQuantity;
/**
* 支付分计划原总金额(单位分)
*/
@NotNull(message = "支付分计划原总金额不能为空")
@ApiModelProperty(value = "支付分计划原总金额(单位分)", required = true)
private Integer totalOriginalPrice;
public void setTotalOriginalPrice(String totalOriginalPrice) {
double price = Double.parseDouble(totalOriginalPrice) * 100;
this.totalOriginalPrice = (int) price;
}
/**
* 支付分计划实际扣费总金额(单位分)
*/
@NotNull(message = "支付分计划实际扣费总金额不能为空")
@ApiModelProperty(value = "支付分计划实际扣费总金额(单位分)", required = true)
private Integer totalActualPrice;
public void setTotalActualPrice(String totalActualPrice) {
double price = Double.parseDouble(totalActualPrice) * 100;
this.totalActualPrice = (int) price;
}
/**
* 支付分计划明细列表
*/
@NotEmpty(message = "支付分计划明细列表不能为空")
@ApiModelProperty(value = "支付分计划明细列表", required = true)
private List<PlanDetail> planDetailList;
@Data
public static class PlanDetail {
/**
* 计划明细原支付金额(单位分)
*/
@NotNull(message = "计划明细原支付金额不能为空")
@ApiModelProperty(value = "计划明细原支付金额(单位分)",required = true)
private Integer originalPrice;
public void setOriginalPrice(String originalPrice) {
double price = Double.parseDouble(originalPrice) * 100;
this.originalPrice = (int) price;
}
/**
* 计划明细优惠说明
*/
@NotBlank(message = "计划明细优惠说明不能为空")
@ApiModelProperty(value = "计划明细优惠说明",required = true)
private String planDiscountDescription;
/**
* 计划明细实际支付金额(单位分)
*/
@NotNull(message = "计划明细实际支付金额不能为空")
@ApiModelProperty(value = "计划明细实际支付金额(单位分)",required = true)
private Integer actualPrice;
public void setActualPrice(String actualPrice) {
double price = Double.parseDouble(actualPrice) * 100;
this.actualPrice = (int) price;
}
/**
* 计划明细名称
*/
@NotBlank(message = "计划明细名称不能为空")
@ApiModelProperty(value = "计划明细名称",required = true)
private String planDetailName;
}
}

View File

@ -1,70 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-05 16:13
*/
@Data
@ApiModel("先学后付计划")
public class LearnNowPayLaterPlanBo {
/**
* 支付分计划名称
*/
@ApiModelProperty("支付分计划名称")
private String planName;
/**
* 支付分计划有效期(单位天)
*/
@ApiModelProperty("支付分计划有效期(单位天)")
private Integer planDuration;
/**
* 支付分计划扣费次数
*/
@ApiModelProperty("支付分计划扣费次数")
private Integer deductionQuantity;
/**
* 支付分计划原总金额(单位分)
*/
@ApiModelProperty("支付分计划原总金额")
private Integer totalOriginalPrice;
public void setTotalOriginalPrice(BigDecimal totalOriginalPrice) {
this.totalOriginalPrice = totalOriginalPrice.scaleByPowerOfTen(2).intValue();
}
/**
* 支付分计划实际扣费总金额(单位分)
*/
@ApiModelProperty("支付分计划实际扣费总金额(单位分)")
private Integer totalActualPrice;
public void setTotalActualPrice(BigDecimal totalActualPrice) {
this.totalActualPrice = totalActualPrice.scaleByPowerOfTen(2).intValue();
}
/**
* 支付分计划明细列表
*/
@ApiModelProperty("支付分计划明细列表")
private List<LearnNowPayLaterPlanDetailBo> planDetailList;
/**
* 课次
*/
@ApiModelProperty("支付分计划原总金额")
private String classHour;
}

View File

@ -1,49 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-08 9:54
*/
@Data
@ApiModel(value = "先学后付计划详情")
public class LearnNowPayLaterPlanDetailBo {
/**
* 计划明细优惠说明
*/
@ApiModelProperty("计划明细优惠说明")
private String planDiscountDescription;
/**
* 计划明细原支付金额(单位分)
*/
@ApiModelProperty("计划明细原支付金额(单位分)")
private Integer originalPrice;
public void setOriginalPrice(BigDecimal originalPrice) {
this.originalPrice = originalPrice.scaleByPowerOfTen(2).intValue();
}
/**
* 计划明细实际支付金额(单位分)
*/
@ApiModelProperty("计划明细实际支付金额(单位分)")
private Long actualPrice;
public void setActualPrice(BigDecimal actualPrice) {
this.actualPrice = actualPrice.scaleByPowerOfTen(2).longValue();
}
/**
* 计划明细名称
*/
@ApiModelProperty("计划明细名称")
private String planDetailName;
}

View File

@ -1,61 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-20 12:33
*/
@Data
@ApiModel(value = "先学后付用户核销")
public class LearnNowPayLaterServiceOrderBo {
/**
* 支付分订单在商户侧的订单号必须和创建签约计划时传入的该笔订单对应的商户侧计划明细使用订单号(merchant\_plan\_detail\_no)一致
*/
@NotBlank(message = "待创建服务订单对应的用户的签约计划不能为空")
@ApiModelProperty(value = "待创建服务订单对应的用户的签约计划",required = true)
private String signPlanId;
/**
* 待创建服务订单对应的用户的签约计划详情序号
*/
@NotNull(message = "planDetailNo不能为空")
@ApiModelProperty(value = "待创建服务订单对应的用户的签约计划详情序号",required = true)
private Integer planDetailNo;
/**
* 服务商公众号下的用户标识
*/
@NotBlank(message = "openid不能为空")
@ApiModelProperty(value = "服务商公众号下的用户标识",required = true)
private String openid;
/**
* 卡号
*/
@NotBlank(message = "cardNo不能为空")
@ApiModelProperty(value = "卡号",required = true)
private String cardNo;
/**
* 课程信息
*/
@NotBlank(message = "课程信息不能为空")
@ApiModelProperty(value = "课程信息",required = true)
private String serviceIntroduction;
/**
* 核销金额
*/
@NotNull(message = "核销金额不能为空")
@ApiModelProperty(value = "核销金额",required = true)
private Integer price;
}

View File

@ -1,31 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-20 15:01
*/
@Data
@ApiModel(value = "停止用户签约计划")
public class LearnNowPayLaterStopUserSignPlansBo {
/**
* 签约计划id
*/
@NotBlank(message = "签约计划id不能为空")
@ApiModelProperty(value = "签约计划id",required = true)
private String signPlanId;
/**
* 取消理由
*/
@NotBlank(message = "取消理由不能为空")
@ApiModelProperty(value = "取消理由",required = true)
private String stopReason;
}

View File

@ -1,77 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-19 22:40
*/
@Data
@ApiModel(value = "先学后付用户签约计划")
public class LearnNowPayLaterUserSignPlansBo {
/**
* 支付分id
*/
@NotBlank(message = "支付分id不能为空")
@ApiModelProperty(value = "支付分id",required = true)
private String id;
/**
* 云校区id
*/
@NotBlank(message = "云校区id不能为空")
@ApiModelProperty(value = "云校区id",required = true)
private String storeCloudId;
/**
* 子商户下用户openid
*/
@NotBlank(message = "子商户下用户openid不能为空")
@ApiModelProperty(value = "子商户下用户openid",required = true)
private String subOpenId;
/**
* 支付分计划名称
*/
@NotBlank(message = "支付分计划名称不能为空")
@ApiModelProperty(value = "支付分计划名称",required = true)
private String planName;
/**
* 客户名
*/
@NotBlank(message = "客户名不能为空")
@ApiModelProperty(value = "客户名",required = true)
private String customerName;
/**
* 客户手机号
*/
@NotBlank(message = "客户手机号不能为空")
@ApiModelProperty(value = "客户手机号", required = true)
private String customerPhone;
/**
* 模板id
*/
@ApiModelProperty(value = "模板id")
private String templateId;
/**
* 旧模板id
*/
@ApiModelProperty(value = "旧模板id")
private String oldTemplateId;
/**
* 顾问名
*/
@ApiModelProperty(value = "顾问名")
private String counselor;
}

View File

@ -1,83 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* @author DB
* @version 1.0.0
* @since 2023-12-21 17:15
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "OncePlaceOrderBo对象", description = "一次性支付参数")
public class OncePlaceOrderBo {
/**
* 品牌id
*/
@NotBlank(message = "品牌id不能为空")
@ApiModelProperty(value = "品牌id",required = true)
private String brandCloudId;
/**
* 校区id
*/
@NotBlank(message = "校区id不能为空")
@ApiModelProperty(value = "校区id",required = true)
private String storeCloudId;
/**
* 客户名
*/
@NotBlank(message = "客户名不能为空")
@ApiModelProperty(value = "客户名",required = true)
private String customerName;
/**
* 客户电话
*/
@NotBlank(message = "客户电话不能为空")
@ApiModelProperty(value = "客户电话",required = true)
private String customerPhone;
/**
* 云id
*/
@NotBlank(message = "云订单id不能为空")
@ApiModelProperty(value = "云订单id",required = true)
private String orderCloudId;
/**
* 总金额
*/
@NotNull(message = "总金额不能为空")
@ApiModelProperty(value = "总金额",required = true)
private BigDecimal totalAmount;
/**
* 总支付金额
*/
@NotNull(message = "总支付金额不能为空")
@ApiModelProperty(value = "总支付金额",required = true)
private BigDecimal totalPayAmount;
/**
* openId
*/
@ApiModelProperty("openId")
private String openId;
/**
* 订单名
*/
@ApiModelProperty("订单内容(课卡名/商品名)")
private String orderContent;
}

View File

@ -1,21 +0,0 @@
package com.cpop.jambox.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author DB
* @version 1.0.0
* @since 2024-01-08 9:20
*/
@Data
@ApiModel(value = "联合支付")
public class UnionPayDto {
/**
* 先学后付次付
*/
@ApiModelProperty("先学后付次付")
private LearnNowPayLaterOncePayDto learnNowPayLaterOncePayDto;
}

View File

@ -1,110 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.BusinessData;
import com.cpop.jambox.business.service.BusinessDataService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 业务数据表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 业务数据表接口")
@RequestMapping("/backstage/businessData")
public class BackstageBusinessDataController {
@Autowired
private BusinessDataService businessDataService;
/**
* 添加果酱模块化官网 业务数据表
*
* @param businessData 果酱模块化官网 业务数据表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 业务数据表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 业务数据表") BusinessData businessData) {
businessDataService.save(businessData);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 业务数据表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 业务数据表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 业务数据表主键") Serializable id) {
businessDataService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 业务数据表
*
* @param businessData 果酱模块化官网 业务数据表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 业务数据表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 业务数据表主键") BusinessData businessData) {
businessDataService.updateById(businessData);
return R.ok();
}
/**
* 查询所有果酱模块化官网 业务数据表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 业务数据表")
public R<List<BusinessData>> list() {
return R.ok(businessDataService.list());
}
/**
* 根据果酱模块化官网 业务数据表主键获取详细信息
*
* @param id 果酱模块化官网 业务数据表主键
* @return 果酱模块化官网 业务数据表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 业务数据表")
public R<BusinessData> getInfo(@PathVariable @ApiParam("果酱模块化官网 业务数据表主键") Serializable id) {
return R.ok(businessDataService.getById(id));
}
/**
* 分页查询果酱模块化官网 业务数据表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 业务数据表")
public R<Page<BusinessData>> page(@ApiParam("分页信息") Page<BusinessData> page) {
return R.ok(businessDataService.page(page));
}
}

View File

@ -1,110 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.BusinessIntro;
import com.cpop.jambox.business.service.BusinessIntroService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 业务介绍表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 业务介绍表接口")
@RequestMapping("/backstage/businessIntro")
public class BackstageBusinessIntroController {
@Autowired
private BusinessIntroService businessIntroService;
/**
* 添加果酱模块化官网 业务介绍表
*
* @param businessIntro 果酱模块化官网 业务介绍表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 业务介绍表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 业务介绍表") BusinessIntro businessIntro) {
businessIntroService.save(businessIntro);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 业务介绍表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 业务介绍表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 业务介绍表主键") Serializable id) {
businessIntroService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 业务介绍表
*
* @param businessIntro 果酱模块化官网 业务介绍表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 业务介绍表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 业务介绍表主键") BusinessIntro businessIntro) {
businessIntroService.updateById(businessIntro);
return R.ok();
}
/**
* 查询所有果酱模块化官网 业务介绍表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 业务介绍表")
public R<List<BusinessIntro>> list() {
return R.ok(businessIntroService.list());
}
/**
* 根据果酱模块化官网 业务介绍表主键获取详细信息
*
* @param id 果酱模块化官网 业务介绍表主键
* @return 果酱模块化官网 业务介绍表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 业务介绍表")
public R<BusinessIntro> getInfo(@PathVariable @ApiParam("果酱模块化官网 业务介绍表主键") Serializable id) {
return R.ok(businessIntroService.getById(id));
}
/**
* 分页查询果酱模块化官网 业务介绍表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 业务介绍表")
public R<Page<BusinessIntro>> page(@ApiParam("分页信息") Page<BusinessIntro> page) {
return R.ok(businessIntroService.page(page));
}
}

View File

@ -1,110 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.CompanyIntro;
import com.cpop.jambox.business.service.CompanyIntroService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 公司简介表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 公司简介表接口")
@RequestMapping("/backstage/companyIntro")
public class BackstageCompanyIntroController {
@Autowired
private CompanyIntroService companyIntroService;
/**
* 添加果酱模块化官网 公司简介表
*
* @param companyIntro 果酱模块化官网 公司简介表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 公司简介表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 公司简介表") CompanyIntro companyIntro) {
companyIntroService.save(companyIntro);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 公司简介表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 公司简介表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 公司简介表主键") Serializable id) {
companyIntroService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 公司简介表
*
* @param companyIntro 果酱模块化官网 公司简介表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 公司简介表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 公司简介表主键") CompanyIntro companyIntro) {
companyIntroService.updateById(companyIntro);
return R.ok();
}
/**
* 查询所有果酱模块化官网 公司简介表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 公司简介表")
public R<List<CompanyIntro>> list() {
return R.ok(companyIntroService.list());
}
/**
* 根据果酱模块化官网 公司简介表主键获取详细信息
*
* @param id 果酱模块化官网 公司简介表主键
* @return 果酱模块化官网 公司简介表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 公司简介表")
public R<CompanyIntro> getInfo(@PathVariable @ApiParam("果酱模块化官网 公司简介表主键") Serializable id) {
return R.ok(companyIntroService.getById(id));
}
/**
* 分页查询果酱模块化官网 公司简介表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 公司简介表")
public R<Page<CompanyIntro>> page(@ApiParam("分页信息") Page<CompanyIntro> page) {
return R.ok(companyIntroService.page(page));
}
}

View File

@ -1,113 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.Cooperation;
import com.cpop.jambox.business.service.CooperationService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 合作平台表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 合作平台表接口")
@RequestMapping("/backstage/cooperation")
public class BackstageCooperationController {
@Autowired
private CooperationService cooperationService;
/**
* 添加果酱模块化官网 合作平台表
*
* @param cooperation 果酱模块化官网 合作平台表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 合作平台表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 合作平台表") Cooperation cooperation) {
cooperationService.save(cooperation);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 合作平台表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 合作平台表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 合作平台表主键") Serializable id) {
cooperationService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 合作平台表
*
* @param cooperation 果酱模块化官网 合作平台表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 合作平台表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 合作平台表主键") Cooperation cooperation) {
cooperationService.updateById(cooperation);
return R.ok();
}
/**
* 查询所有果酱模块化官网 合作平台表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 合作平台表")
public R<List<Cooperation>> list() {
return R.ok(cooperationService.selectTypeNameList());
}
/**
* 根据果酱模块化官网 合作平台表主键获取详细信息
*
* @param id 果酱模块化官网 合作平台表主键
* @return 果酱模块化官网 合作平台表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 合作平台表")
public R<Cooperation> getInfo(@PathVariable @ApiParam("果酱模块化官网 合作平台表主键") Serializable id) {
return R.ok(cooperationService.getById(id));
}
/**
* 分页查询果酱模块化官网 合作平台表
*
* @author: Yxz
* @date: 2024/1/21 15:42
* @param: [typeId]
* @return: com.cpop.core.base.entity.R<com.mybatisflex.core.paginate.Page<com.cpop.jambox.business.entity.website.Cooperation>>
**/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 合作平台表")
public R<Page<Cooperation>> page(@ApiParam("平台类型") String typeId) {
Page<Cooperation> cooperationPage = cooperationService.getPage(typeId);
return R.ok(cooperationPage);
}
}

View File

@ -1,112 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.cpop.jambox.business.vo.CooperationTypeVo;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.CooperationType;
import com.cpop.jambox.business.service.CooperationTypeService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 合作类别表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 合作类别表接口")
@RequestMapping("/backstage/cooperationType")
public class BackstageCooperationTypeController {
@Autowired
private CooperationTypeService cooperationTypeService;
/**
* 添加果酱模块化官网 合作类别表
*
* @param cooperationType 果酱模块化官网 合作类别表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 合作类别表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 合作类别表") CooperationType cooperationType) {
cooperationTypeService.save(cooperationType);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 合作类别表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 合作类别表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 合作类别表主键") Serializable id) {
cooperationTypeService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 合作类别表
*
* @param cooperationType 果酱模块化官网 合作类别表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 合作类别表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 合作类别表主键") CooperationType cooperationType) {
cooperationTypeService.updateById(cooperationType);
return R.ok();
}
/**
* 查询所有果酱模块化官网 合作类别表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 合作类别表")
public R<List<CooperationTypeVo>> list() {
List<CooperationTypeVo> cooperationTypeVoList = cooperationTypeService.getList();
return R.ok(cooperationTypeVoList);
}
/**
* 根据果酱模块化官网 合作类别表主键获取详细信息
*
* @param id 果酱模块化官网 合作类别表主键
* @return 果酱模块化官网 合作类别表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 合作类别表")
public R<CooperationType> getInfo(@PathVariable @ApiParam("果酱模块化官网 合作类别表主键") Serializable id) {
return R.ok(cooperationTypeService.getById(id));
}
/**
* 分页查询果酱模块化官网 合作类别表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 合作类别表")
public R<Page<CooperationType>> page(@ApiParam("分页信息") Page<CooperationType> page) {
return R.ok(cooperationTypeService.page(page));
}
}

View File

@ -1,110 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.Development;
import com.cpop.jambox.business.service.DevelopmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.List;
/**
* 果酱模块化官网 发展历程表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 发展历程表接口")
@RequestMapping("/backstage/development")
public class BackstageDevelopmentController {
@Autowired
private DevelopmentService developmentService;
/**
* 添加果酱模块化官网 发展历程表
*
* @param development 果酱模块化官网 发展历程表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 发展历程表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 发展历程表") Development development) {
developmentService.save(development);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 发展历程表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 发展历程表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 发展历程表主键") Serializable id) {
developmentService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 发展历程表
*
* @param development 果酱模块化官网 发展历程表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 发展历程表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 发展历程表主键") Development development) {
developmentService.updateById(development);
return R.ok();
}
/**
* 查询所有果酱模块化官网 发展历程表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 发展历程表")
public R<List<Development>> list() {
return R.ok(developmentService.list());
}
/**
* 根据果酱模块化官网 发展历程表主键获取详细信息
*
* @param id 果酱模块化官网 发展历程表主键
* @return 果酱模块化官网 发展历程表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 发展历程表")
public R<Development> getInfo(@PathVariable @ApiParam("果酱模块化官网 发展历程表主键") Serializable id) {
return R.ok(developmentService.getById(id));
}
/**
* 分页查询果酱模块化官网 发展历程表
*
* @author: Yxz
* @date: 2024/1/24 14:41
* @param: [title, startDate, endDate]
* @return: com.cpop.core.base.entity.R<com.mybatisflex.core.paginate.Page<com.cpop.jambox.business.entity.website.Development>>
**/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 发展历程表")
public R<Page<Development>> page(@ApiParam("标题") String title,
@RequestParam(value = "startDate",required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(value = "endDate",required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
Page<Development> developmentPage = developmentService.selectPage(title,startDate,endDate);
return R.ok(developmentPage);
}
}

View File

@ -1,128 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.alibaba.excel.EasyExcel;
import com.cpop.core.base.entity.R;
import com.cpop.jambox.business.bo.*;
import com.cpop.jambox.business.dto.EasyLearnPageDto;
import com.cpop.jambox.business.service.EasyLearnOrderService;
import com.cpop.jambox.business.vo.EasyLearnPageVo;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
/**
* 果酱-放心学订单表 控制层
*
* @author DB
* @since 2023-12-14
*/
@RestController
@Api(tags = "果酱-放心学订单表接口")
@RequestMapping("/backstage/easyLearn")
public class BackstageEasyLearnController {
@Autowired
private EasyLearnOrderService easyLearnOrderService;
/**
* 获取放心学分页
* @author DB
* @since 2023/12/15
* @param bo 查询参数
* @return R<Page<EasyLearnPageVo>>
*/
@ApiOperation("查询放心学分页")
@GetMapping("/getEasyLearnPage")
public R<Page<EasyLearnPageVo>> getEasyLearnPage(@Validated EasyLearnPageBo bo) {
Page<EasyLearnPageVo> page = easyLearnOrderService.getEasyLearnPage(bo);
return R.ok(page);
}
/**
* 导出放心学数据
* @author DB
* @since 2023/12/15
* @param response 响应
* @param bo 请求参数
*/
@GetMapping("/getEasyLearnXml")
@ApiOperation("导出放心学数据")
public void getEasyLearnXml(HttpServletResponse response, @ApiParam("分页查询条件") @Validated EasyLearnPageBo bo) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyExcel没有关系
String fileFullName = "放心学";
switch (bo.getOrderType()) {
case 0:
fileFullName = fileFullName + " 先学后付-次付 ";
break;
case 1:
fileFullName = fileFullName + " 先学后付-月付 ";
break;
case 2:
fileFullName = fileFullName + " 微信支付 ";
break;
case 3:
fileFullName = fileFullName + " 数字人民币 ";
break;
case 4:
fileFullName = fileFullName + " 机构会员 ";
break;
default:
}
String fileName = URLEncoder.encode(fileFullName + "数据", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), EasyLearnPageDto.class).sheet("记录").doWrite(easyLearnOrderService.getEasyLearnXml(bo));
}
/**
* 一次性支付下单
* @author DB
* @since 2023/10/23 12:15
* @param bo 下单请求对象
* @return com.cpop.core.base.entity.R<java.lang.Void>
*/
@PostMapping("/oncePlaceOrder")
@ApiOperation("一次性支付下单")
public R<Object> oncePlaceOrder(@RequestBody @Validated @ApiParam("一次性支付") OncePlaceOrderBo bo) {
return R.ok(easyLearnOrderService.oncePlaceOrder(bo));
}
/**
* 放心学统一支付
* @author DB
* @since 2023/12/28
* @param bo 请求参数
* @return R<Object>
*/
@Deprecated
@PostMapping("/unionPay")
@ApiOperation("放心学统一支付")
public R<Object> unionPay(@RequestBody @Validated EasyLearnUnionPayBo bo) {
return R.ok(easyLearnOrderService.unionPay(bo));
}
/**
* 放心学统一支付
* @author DB
* @since 2024/1/9
* @param bo 请求参数
* @return R<Object>
*/
@PostMapping("/unifiedPay")
@ApiOperation("放心学统一支付(测试)")
public R<Object> unifiedPay(@RequestBody @Validated @ApiParam("放心学统一支付") EasyLearnUnifiedPayBo bo) {
return R.ok(easyLearnOrderService.unifiedPay(bo));
}
}

View File

@ -1,113 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.cpop.jambox.business.vo.NavigationVo;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.jambox.business.entity.website.Navigation;
import com.cpop.jambox.business.service.NavigationService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 导航栏表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 导航栏表接口")
@RequestMapping("/backstage/navigation")
public class BackstageNavigationController {
@Autowired
private NavigationService navigationService;
/**
* 添加果酱模块化官网 导航栏表
*
* @param navigation 果酱模块化官网 导航栏表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 导航栏表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 导航栏表") Navigation navigation) {
navigationService.save(navigation);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 导航栏表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 导航栏表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 导航栏表主键") Serializable id) {
navigationService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 导航栏表
*
* @param navigation 果酱模块化官网 导航栏表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 导航栏表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 导航栏表主键") Navigation navigation) {
navigationService.updateById(navigation);
return R.ok();
}
/**
* 查询所有果酱模块化官网 导航栏表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 导航栏表")
public R<List<NavigationVo>> list() {
List<NavigationVo> navigationVoList = navigationService.getList();
return R.ok(navigationVoList);
}
/**
* 根据果酱模块化官网 导航栏表主键获取详细信息
*
* @param id 果酱模块化官网 导航栏表主键
* @return 果酱模块化官网 导航栏表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 导航栏表")
public R<Navigation> getInfo(@PathVariable @ApiParam("果酱模块化官网 导航栏表主键") Serializable id) {
return R.ok(navigationService.getById(id));
}
/**
* 分页查询果酱模块化官网 导航栏表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 导航栏表")
public R<Page<Navigation>> page(@ApiParam("分页信息") Page<Navigation> page) {
return R.ok(navigationService.page(page));
}
}

View File

@ -1,110 +0,0 @@
package com.cpop.jambox.business.controller.backstage;
import com.cpop.core.base.entity.R;
import com.cpop.jambox.business.entity.website.WebProduct;
import com.cpop.jambox.business.service.WebProductService;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 果酱模块化官网 核心产品表 控制层
*
* @author Yxz
* @since 2024-01-19
*/
@RestController
@Api(tags = "果酱模块化官网 核心产品表接口")
@RequestMapping("/backstage/webProduct")
public class BackstageWebProductController {
@Autowired
private WebProductService productService;
/**
* 添加果酱模块化官网 核心产品表
*
* @param product 果酱模块化官网 核心产品表
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存果酱模块化官网 核心产品表")
public R<Void> save(@RequestBody @ApiParam("果酱模块化官网 核心产品表") WebProduct product) {
productService.save(product);
return R.ok();
}
/**
* 根据主键删除果酱模块化官网 核心产品表
*
* @param id 主键
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键果酱模块化官网 核心产品表")
public R<Void> remove(@PathVariable @ApiParam("果酱模块化官网 核心产品表主键") Serializable id) {
productService.removeById(id);
return R.ok();
}
/**
* 根据主键更新果酱模块化官网 核心产品表
*
* @param product 果酱模块化官网 核心产品表
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新果酱模块化官网 核心产品表")
public R<Void> update(@RequestBody @ApiParam("果酱模块化官网 核心产品表主键") WebProduct product) {
productService.updateById(product);
return R.ok();
}
/**
* 查询所有果酱模块化官网 核心产品表
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有果酱模块化官网 核心产品表")
public R<List<WebProduct>> list() {
return R.ok(productService.list());
}
/**
* 根据果酱模块化官网 核心产品表主键获取详细信息
*
* @param id 果酱模块化官网 核心产品表主键
* @return 果酱模块化官网 核心产品表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取果酱模块化官网 核心产品表")
public R<WebProduct> getInfo(@PathVariable @ApiParam("果酱模块化官网 核心产品表主键") Serializable id) {
return R.ok(productService.getById(id));
}
/**
* 分页查询果酱模块化官网 核心产品表
*
* @param page 分页对象
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询果酱模块化官网 核心产品表")
public R<Page<WebProduct>> page(@ApiParam("分页信息") Page<WebProduct> page) {
return R.ok(productService.page(page));
}
}

Some files were not shown because too many files have changed in this diff Show More