screen-api/pom.xml
@@ -74,6 +74,11 @@ </dependency> <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.8</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.3.0</version> screen-api/src/main/java/com/moral/api/Swagger2.java
@@ -5,10 +5,15 @@ import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Arrays; import java.util.Collections; import java.util.List; @Configuration @@ -17,6 +22,13 @@ @Bean public Docket petApi() { return new Docket(DocumentationType.SWAGGER_2) .securityContexts(Arrays.asList(SecurityContext.builder() .securityReferences(Arrays.asList(SecurityReference.builder() .reference("token") .scopes(new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")}) .build())) .build())) .securitySchemes(Arrays.asList(new ApiKey("token", "token", "header"))) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.moral.api")) @@ -31,4 +43,5 @@ .build(); } } screen-api/src/main/java/com/moral/api/config/Interceptor/UserHelper.java
New file @@ -0,0 +1,49 @@ package com.moral.api.config.Interceptor; import com.alibaba.fastjson.JSON; import com.moral.api.pojo.vo.user.QxUser; import com.moral.api.utils.BeanConverts; import com.moral.api.utils.StringUtils; import com.moral.constant.ResponseCodeEnum; import com.moral.exception.TokenException; import com.moral.util.TokenUtils; import net.sf.cglib.beans.BeanMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * @ClassName UserHelper * @Description TODO * @Author @cjl * @Date 2023-09-21 15:47 * @Version 1.0 */ public class UserHelper { public static QxUser getCurrentUser(){ Map<String, Object> userInfo = new HashMap<>(); try { userInfo = (Map<String, Object>) TokenUtils.getUserInfo(); }catch (Exception e){ } if (Objects.isNull(userInfo)||Objects.isNull(userInfo.get("userId"))) { return null; } try { String s = JSON.toJSONString(userInfo); return JSON.parseObject(s, QxUser.class); } catch (Exception e) { e.printStackTrace(); } return null; } } screen-api/src/main/java/com/moral/api/controller/DictController.java
@@ -1,10 +1,7 @@ package com.moral.api.controller; import com.moral.api.entity.CityConfigAqi; import com.moral.api.pojo.enums.ChangeEnum; import com.moral.api.pojo.enums.InvestigationEnum; import com.moral.api.pojo.enums.StateEnum; import com.moral.api.pojo.enums.YesOrNo; import com.moral.api.pojo.enums.*; import com.moral.api.pojo.vo.DictionaryVo; import com.moral.constant.ResultMessage; import io.swagger.annotations.Api; @@ -32,6 +29,7 @@ .setChangeEnum(ChangeEnum.values()) .setInvestigationEnum(InvestigationEnum.values()) .setYesOrNo(YesOrNo.values()) .setFileTableEnum(FileTableEnum.values()) ; return ResultMessage.ok(dictionaryVo); } screen-api/src/main/java/com/moral/api/controller/FileTableController.java
New file @@ -0,0 +1,64 @@ package com.moral.api.controller; import com.moral.api.pojo.vo.file.FileVo; import com.moral.api.service.FileTableService; import com.moral.constant.ResultMessage; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * <p> * 附件表 前端控制器 * </p> * * @author moral * @since 2023-09-21 */ @RestController @RequestMapping("/file") @Api(tags = {"附件"}) public class FileTableController { private final FileTableService fileTableService; public FileTableController(FileTableService fileTableService) { this.fileTableService = fileTableService; } @PostMapping("/upload") @ApiOperation("文件上传") public ResultMessage<FileVo> upload(@RequestParam("file") @ApiParam(name = "file", value = "上传文件") MultipartFile file, @RequestParam("sysCode") @ApiParam(name = "sysCode", value = "系统代码") Integer sysCode){ return ResultMessage.ok(fileTableService.upload(file,sysCode)); } @PostMapping("/multipleUpload") @ApiOperation("多文件批量上传") public ResultMessage<List<FileVo>> upload(@RequestParam("file") @ApiParam(name = "file", value = "上传文件") List<MultipartFile> file, @RequestParam("sysCode") @ApiParam(name = "sysCode", value = "系统代码") Integer sysCode){ return ResultMessage.ok(fileTableService.upload(file,sysCode)); } @GetMapping("/preview/{id}") @ApiOperation("文件预览") public void preview(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) { fileTableService.preview(id, request, response); } @GetMapping("/preview/cover/{id}") @ApiOperation("封面图片预览") public void coverPreview(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) { fileTableService.coverPreview(id, request, response); } } screen-api/src/main/java/com/moral/api/entity/FileTable.java
New file @@ -0,0 +1,92 @@ package com.moral.api.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; import java.util.Date; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * <p> * 附件表 * </p> * * @author moral * @since 2023-09-21 */ @Data @Accessors(chain = true) @EqualsAndHashCode(callSuper = false) public class FileTable extends Model<FileTable> { private static final long serialVersionUID = 1L; /** * 主键id */ @TableId(value = "file_id", type = IdType.AUTO) private Integer fileId; /** * 模块 */ private Integer fileModule; /** * 关联主键id */ private Integer relationId; /** * 附件名称 */ private String fileName; /** * 附件类型1图片2视频 */ private Integer fileType; /** * 附件路径地址 */ private String fileAddress; /** * 附件大小 */ private Integer fileSize; /** * 是否删除 */ private Integer isDel; /** * 创建人id */ private Integer createId; /** * 创建人姓名 */ private String createName; /** * 创建时间 */ private Date createTime; @Override protected Serializable pkVal() { return this.fileId; } } screen-api/src/main/java/com/moral/api/mapper/FileTableMapper.java
New file @@ -0,0 +1,16 @@ package com.moral.api.mapper; import com.moral.api.entity.FileTable; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * <p> * 附件表 Mapper 接口 * </p> * * @author moral * @since 2023-09-21 */ public interface FileTableMapper extends BaseMapper<FileTable> { } screen-api/src/main/java/com/moral/api/pojo/enums/FileTableEnum.java
New file @@ -0,0 +1,63 @@ package com.moral.api.pojo.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.moral.api.exception.BusinessException; import lombok.Getter; import java.util.HashMap; import java.util.Map; /** * @ClassName StateEnum * @Description TODO * @Author @lizijie * @Date 2023-09-20 11:11 * @Version 1.0 */ @Getter @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum FileTableEnum implements IntegerValueEnum { /** *交办单基础 */ ALLOCATION_FOUNDATION(1010201, "交办单基础"), /** *交办单整改 */ ALLOCATION_RECTIFICATION(1010202, "交办单整改"), /** *交办单审批 */ ALLOCATION_APPROVE(1010203, "交办单审批"), ; @EnumValue public final Integer value; public final String name; FileTableEnum(Integer value, String name) { this.value = value; this.name = name; } private static Map<Integer, FileTableEnum> valueMap = new HashMap<>(); static { for (FileTableEnum v : FileTableEnum.values()) { valueMap.put(v.value, v); } } @JsonCreator public static FileTableEnum getByValue(Integer value) { if (value == null) { return null; } FileTableEnum result = valueMap.get(value); if (result == null) { throw new BusinessException("枚举转换异常" + value); } return result; } } screen-api/src/main/java/com/moral/api/pojo/enums/FileType.java
New file @@ -0,0 +1,69 @@ package com.moral.api.pojo.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import com.fasterxml.jackson.annotation.JsonCreator; import lombok.Getter; import java.util.HashMap; import java.util.Map; /** * @ClassName FileType * @Description * @Author fan * @Date 2021/2/1 13:48 * @Version 1.0 **/ @Getter public enum FileType { /** * 其他 */ NON(-1), /** * 图片 */ PICTURE(1), /** * word */ WORD(2), /** * excel */ EXCEL(3), /** */ PDF(4), /** * 压缩包 */ ZIP(5), ; @EnumValue private final Integer value; FileType(Integer value) { this.value = value; } private static final Map<Integer, FileType> VALUE_MAP = new HashMap<>(); static { for (FileType var : values()) { VALUE_MAP.put(var.getValue(), var); } } @JsonCreator public static FileType getEnumByCode(Integer value) { FileType fileType = VALUE_MAP.get(value); if (fileType == null) { throw new RuntimeException("enum not find element, [" + value + "]"); } return fileType; } } screen-api/src/main/java/com/moral/api/pojo/enums/StateEnum.java
@@ -22,11 +22,11 @@ /** *未生效 */ NOT_EFFECTIVE(10, "未生效"), NOT_EFFECTIVE(0, "未生效"), /** *已生效 */ TAKE_EFFECT(20, "已生效"); TAKE_EFFECT(1, "已生效"); @EnumValue public final Integer value; screen-api/src/main/java/com/moral/api/pojo/vo/DictionaryVo.java
@@ -33,6 +33,8 @@ private List<Map<String, Object>> ChangeEnum; private List<Map<String, Object>> YesOrNo; private List<Map<String, Object>> FileTableEnum; @@ -62,5 +64,9 @@ return this; } public DictionaryVo setFileTableEnum(com.moral.api.pojo.enums.FileTableEnum[] enumResult) { this.FileTableEnum = enumArray2Map(enumResult); return this; } } screen-api/src/main/java/com/moral/api/pojo/vo/file/FileVo.java
New file @@ -0,0 +1,26 @@ package com.moral.api.pojo.vo.file; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * @ClassName FileVo * @Description TODO * @Author @cjl * @Date 2023-09-21 14:51 * @Version 1.0 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @ApiModel(description="FileVo - 文件VO对象") public class FileVo { @ApiModelProperty(value = "ID") private Integer fileId; @ApiModelProperty(value = "文件名称") private String fileName; } screen-api/src/main/java/com/moral/api/pojo/vo/user/QxUser.java
New file @@ -0,0 +1,30 @@ package com.moral.api.pojo.vo.user; import lombok.Data; import lombok.experimental.Accessors; /** * @ClassName QxUser * @Description TODO * @Author @cjl * @Date 2023-09-21 15:59 * @Version 1.0 */ @Data @Accessors(chain = true) public class QxUser { /** * 人员id */ private Integer userId; /** * 人员性名 */ private String userName; /** * 账户 */ private String account; } screen-api/src/main/java/com/moral/api/service/FileTableService.java
New file @@ -0,0 +1,29 @@ package com.moral.api.service; import com.moral.api.entity.FileTable; import com.baomidou.mybatisplus.extension.service.IService; import com.moral.api.pojo.vo.file.FileVo; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * <p> * 附件表 服务类 * </p> * * @author moral * @since 2023-09-21 */ public interface FileTableService extends IService<FileTable> { FileVo upload(MultipartFile file, Integer sysCode); List<FileVo> upload(List<MultipartFile>files,Integer sysCode); void preview(Integer id, HttpServletRequest request, HttpServletResponse response); void coverPreview(Integer id, HttpServletRequest request, HttpServletResponse response); } screen-api/src/main/java/com/moral/api/service/impl/FileTableServiceImpl.java
New file @@ -0,0 +1,188 @@ package com.moral.api.service.impl; import com.moral.api.config.Interceptor.UserHelper; import com.moral.api.entity.FileTable; import com.moral.api.exception.BusinessException; import com.moral.api.mapper.FileTableMapper; import com.moral.api.pojo.enums.FileType; import com.moral.api.pojo.vo.file.FileVo; import com.moral.api.pojo.vo.user.QxUser; import com.moral.api.service.FileTableService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.api.utils.FileTypeUtils; import com.moral.api.utils.StringUtils; import com.moral.util.DateUtils; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.*; /** * <p> * 附件表 服务实现类 * </p> * * @author moral * @since 2023-09-21 */ @Service @Slf4j public class FileTableServiceImpl extends ServiceImpl<FileTableMapper, FileTable> implements FileTableService { @Value("${file.path}") private String basePath; @Override public FileVo upload(MultipartFile file, Integer sysCode) { String originalFilename = file.getOriginalFilename().replaceAll(StringUtils.SPACE, StringUtils.EMPTY).toLowerCase(); String suffix = originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT)); FileType fileType = FileTypeUtils.getFileType(suffix.toLowerCase()); // 处理文件相对路径 系统代码 + 业务代码 + 日期 String filePath = getFilePath(sysCode.toString()); // 保存文件 String targetFolder = basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(filePath); //使用uuid 替换上传文件名,避免重复 String storageFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT)); storageFile(file, storageFileName, targetFolder); // 封装文件信息 QxUser user = UserHelper.getCurrentUser(); FileTable sysFile = new FileTable(); sysFile.setFileName(originalFilename).setFileType(fileType.getValue()).setFileSize((int) file.getSize()).setFileAddress(filePath.concat(storageFileName)) .setFileModule(sysCode).setCreateTime(new Date()); if (Objects.nonNull(user)) { sysFile.setCreateId(user.getUserId()).setCreateName(user.getUserName()); } save(sysFile); return new FileVo().setFileId(sysFile.getFileId()).setFileName(originalFilename); } @Override public List<FileVo> upload(List<MultipartFile> files, Integer sysCode) { List<FileVo> fileList = new LinkedList<>(); for (MultipartFile file : files) { fileList.add(upload(file, sysCode)); } return fileList; } @Override public void preview(Integer id, HttpServletRequest request, HttpServletResponse response) { FileTable sysFile = getById(id); File file = new File(handleFileRealPath(sysFile.getFileAddress())); String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); if (FileTypeUtils.SUFFIX_MP4.equals(suffix)) { videoPreview(file, request, response); } else { try (OutputStream out = response.getOutputStream(); InputStream in = new FileInputStream(file)) { response.setContentType(FileTypeUtils.convertHeaderType(suffix)); response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8")); int len; // 创建数据缓冲区 byte[] buffer = new byte[1024]; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } } catch (Exception e) { log.error("读取文件异常!!! e={}", e.getMessage()); } } } private String getFilePath(String sysCode) { return sysCode.concat(StringUtils.SLASH).concat(StringUtils.SLASH).concat(DateUtils.dateToDateString(new Date(),DateUtils.yyyyMMdd_EN)).concat(StringUtils.SLASH); } public void storageFile(MultipartFile file, String originalFilename, String targetFolder) { File f = new File(targetFolder, originalFilename); try { // 保存文件 if (!f.getParentFile().exists()) { if (!f.getParentFile().mkdirs()) { log.error("error:创建文件失败! dir={}", f.getAbsolutePath()); } } file.transferTo(f); } catch (IOException e) { log.error("error:文件上传失败!!!e={}", e.getMessage()); throw new BusinessException("文件上传失败,请重试!"); } } private String handleFileRealPath(String path) { return basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(path); } private void videoPreview(File file, HttpServletRequest request, HttpServletResponse response) { String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); //设置属性 response.setContentType(FileTypeUtils.convertHeaderType(suffix)); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("ETag", file.getName()); response.setHeader("Last-Modified", new Date().toString()); long contentLength = file.length(); //每次传递实际长度(初始第一次读取少选数据) long length = Math.min(contentLength, 1024); long start = 0, end = 0; String range = request.getHeader("Range"); //第一次请求只返回content length来让客户端请求多次实际数据 if (range == null) { response.setHeader("Content-length", contentLength + ""); } else { //以后的多次以断点续传的方式来返回视频数据 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206 if (range.startsWith("bytes=")) { String[] values = range.split("=")[1].split("-"); start = Integer.parseInt(values[0]); if (values.length > 1) { end = Integer.parseInt(values[1]); } } //无end,每次允许的最大长度 long maxSize = 1024 * 1024; //1MB if (end > 0) { length = end - start + 1; response.setHeader("Content-length", "" + length); response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength); } else { length = Math.min((contentLength - start), maxSize); response.setHeader("Content-length", "" + length); response.setHeader("Content-Range", "bytes " + start + "-" + (start + length - 1) + "/" + contentLength); } } try { FileInputStream fileInputStream = new FileInputStream(file); OutputStream out = response.getOutputStream(); //将数据截取并存入byte[]数组中 byte[] data = new byte[(int) length]; fileInputStream.skip(start); fileInputStream.read(data); //取出要传给前端的有效数据 out.write(data); out.close(); fileInputStream.close(); } catch (Exception e) { log.error("读取文件异常!!! e={}", e.getMessage()); } } @Override public void coverPreview(Integer id, HttpServletRequest request, HttpServletResponse response) { FileTable sysFile = getById(id); File file = new File(handleFileRealPath(sysFile.getFileAddress())); String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); try (OutputStream out = response.getOutputStream()) { response.setContentType(FileTypeUtils.convertHeaderType(suffix)); response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8")); Thumbnails.of(file).size(420, 200).toOutputStream(out); } catch (Exception e) { log.error("读取文件异常!!! e={}", e.getMessage()); } } } screen-api/src/main/java/com/moral/api/utils/FileTypeUtils.java
New file @@ -0,0 +1,126 @@ package com.moral.api.utils; import com.moral.api.pojo.enums.FileType; /** * @ClassName: FileTypeUtils * @Description: * @Author: fan * @Date: 2021/2/1 13:41 * @Version: 1.0 **/ public class FileTypeUtils { /** * 图片后缀 */ private static final String SUFFIX_JPE = ".jpe"; private static final String SUFFIX_JPG = ".jpg"; private static final String SUFFIX_PNG = ".png"; private static final String SUFFIX_JPEG = ".jpeg"; private static final String SUFFIX_BMP = ".bmp"; private static final String SUFFIX_GIF = ".gif"; /** * word */ public static final String SUFFIX_DOC = ".doc"; public static final String SUFFIX_DOCX = ".docx"; /** * excel */ private static final String SUFFIX_XLSX = ".xlsx"; private static final String SUFFIX_XLS = ".xls"; /** */ public static final String SUFFIX_PDF = ".pdf"; /** * 压缩包 */ private static final String SUFFIX_ZIP = ".zip"; private static final String SUFFIX_RAR = ".rar"; private static final String SUFFIX_JAR = ".jar"; private static final String SUFFIX_GZIP = ".gzip"; private static final String SUFFIX_TXT = ".txt"; /** * ppt */ public static final String SUFFIX_PPT = ".ppt"; public static final String SUFFIX_PPTX = ".pptx"; public static final String SUFFIX_MP4 = ".mp4"; /** * @Description 获取文件类型 * @author fanhq * @date 2020/4/20 15:35 * @param suffix * @return java.lang.Integer 1. 图片 * 2. word * 3. excel * 4. pdf * 5. 压缩包 */ public static FileType getFileType(String suffix) { switch (suffix) { case SUFFIX_JPE: case SUFFIX_JPG: case SUFFIX_PNG: case SUFFIX_JPEG: case SUFFIX_BMP: return FileType.PICTURE; case SUFFIX_DOC: case SUFFIX_DOCX: return FileType.WORD; case SUFFIX_XLSX: case SUFFIX_XLS: return FileType.EXCEL; case SUFFIX_PDF: return FileType.PDF; case SUFFIX_ZIP: case SUFFIX_RAR: case SUFFIX_JAR: return FileType.ZIP; default: return FileType.NON; } } /** * 根据文件类型转换响应头类型 * @param type * @return */ public static String convertHeaderType(String type) { switch (type){ case SUFFIX_JPE: case SUFFIX_JPG: case SUFFIX_JPEG: return "image/jpeg"; case SUFFIX_PNG: return "image/png"; case SUFFIX_GIF: return "image/gif"; case SUFFIX_ZIP: return "application/zip"; case SUFFIX_GZIP: return "application/gzip"; case SUFFIX_DOC: case SUFFIX_DOCX: return "application/msword"; case SUFFIX_XLSX: case SUFFIX_XLS: return "application/x-xls"; case SUFFIX_PDF: return "application/pdf"; case SUFFIX_TXT: return "text/plain"; case SUFFIX_MP4: return "video/mp4"; default: return "application/octet-stream"; } } } screen-api/src/main/java/com/moral/api/utils/StringUtils.java
New file @@ -0,0 +1,1175 @@ package com.moral.api.utils; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /*** * @Author JI * @Date 2020/3/27 13:44 * @Param * @return **/ public class StringUtils extends org.apache.commons.lang3.StringUtils { public static final String SPACE = " "; public static final String DOT = "."; public static final String PERIOD = "。"; public static final String SLASH = "/"; public static final String BACKSLASH = "\\"; public static final String EMPTY = ""; public static final String CRLF = "\r\n"; public static final String NEWLINE = "\n"; public static final String UNDERLINE = "_"; public static final String COMMA = ","; public static final String COMMA_CN = ","; public static final String CONNECTION_LINE = "-"; public static final String SEMICOLON = ";"; public static final String SEMICOLON_CN = ";"; public static final String HTML_NBSP = " "; public static final String HTML_AMP = "&"; public static final String HTML_QUOTE = """; public static final String HTML_LT = "<"; public static final String HTML_GT = ">"; public static final String PLACEHOLDER = "%s"; public static final String FILE_SEPARATOR = System.getProperties().getProperty("file.separator"); public static final String EMPTY_JSON = "{}"; /*** * @Author JI * @Description //判断是否为空(空格算空) * @Date 2020/3/27 13:55 * @Param [str] * @return boolean **/ public static boolean isEmpty(String str) { return str == null || "".equals(str.trim()) || "null".equals(str.trim()); } public static boolean isBlank(Map param, String str) { return !param.containsKey(str) || param.get(str) == null || "".equals(param.get(str).toString().trim()) || "null".equals(param.get(str).toString().trim()); } public static boolean isNotBlank(Map param, String str) { return !isBlank(param, str); } /*** * @Author JI * @Description //判断是否为不为空(空格算空) * @Date 2020/3/27 13:55 * @Param [str] * @return boolean **/ public static boolean isNotEmpty(String str) { return !isEmpty(str); } /** * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p> * * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> * * <pre> * StringUtils.isBlank(null) = true * StringUtils.isBlank("") = true * StringUtils.isBlank(" ") = true * StringUtils.isBlank("bob") = false * StringUtils.isBlank(" bob ") = false * </pre> * * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is null, empty or whitespace only * @since 2.0 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) */ public static boolean isBlank(final CharSequence cs) { int strLen; if (cs == null || (strLen = cs.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; } /** * 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。 * <p> * <pre> * nullToDefault(null, "default") = "default" * nullToDefault("", "default") = "" * nullToDefault(" ", "default") = " " * nullToDefault("bat", "default") = "bat" * </pre> * * @param str 要转换的字符串 * @param defaultStr 默认字符串 * @return 字符串本身或指定的默认字符串 */ public static String nullToDefault(String str, String defaultStr) { return (str == null) ? defaultStr : str; } /** * 当给定字符串为空字符串时,转换为<code>null</code> * * @param str 被转换的字符串 * @return 转换后的字符串 */ public static String emptyToNull(String str) { return isEmpty(str) ? null : str; } /** * 是否包含空字符串 * * @param strs 字符串列表 * @return 是否包含空字符串 */ public static boolean hasEmpty(String... strs) { for (String str : strs) { if (isEmpty(str)) { return true; } } return false; } /** * 是否全部为空字符串 * * @param strs 字符串列表 * @return 是否全部为空字符串 */ public static boolean isAllEmpty(String... strs) { for (String str : strs) { if (isNotEmpty(str)) { return false; } } return true; } /** * 是否以指定字符串开头 * * @param str 被监测字符串 * @param prefix 开头字符串 * @param isIgnoreCase 是否忽略大小写 * @return 是否以指定字符串开头 */ public static boolean startWith(String str, String prefix, boolean isIgnoreCase) { if (isIgnoreCase) { return str.toLowerCase().startsWith(prefix.toLowerCase()); } else { return str.startsWith(prefix); } } /** * 是否以指定字符串结尾 * * @param str 被监测字符串 * @param suffix 结尾字符串 * @param isIgnoreCase 是否忽略大小写 * @return 是否以指定字符串结尾 */ public static boolean endWith(String str, String suffix, boolean isIgnoreCase) { if (isIgnoreCase) { return str.toLowerCase().endsWith(suffix.toLowerCase()); } else { return str.endsWith(suffix); } } /** * 是否包含特定字符,忽略大小写,如果给定两个参数都为<code>null</code>,返回true * * @param str 被检测字符串 * @param testStr 被测试是否包含的字符串 * @return 是否包含 */ public static boolean containsIgnoreCase(String str, String testStr) { if (null == str) { //如果被监测字符串和 return null == testStr; } return str.toLowerCase().contains(testStr.toLowerCase()); } /** * 生成set方法名<br/> * 例如:name 返回 setName * * @param fieldName 属性名 * @return setXxx */ public static String genSetter(String fieldName) { return upperFirstAndAddPre(fieldName, "set"); } /** * 生成get方法名 * * @param fieldName 属性名 * @return getXxx */ public static String genGetter(String fieldName) { return upperFirstAndAddPre(fieldName, "get"); } /** * 去掉首部指定长度的字符串并将剩余字符串首字母小写<br/> * 例如:str=setName, preLength=3 -> return name * * @param str 被处理的字符串 * @param preLength 去掉的长度 * @return 处理后的字符串,不符合规范返回null */ public static String cutPreAndLowerFirst(String str, int preLength) { if (str == null) { return null; } if (str.length() > preLength) { char first = Character.toLowerCase(str.charAt(preLength)); if (str.length() > preLength + 1) { return first + str.substring(preLength + 1); } return String.valueOf(first); } return null; } /** * 原字符串首字母大写并在其首部添加指定字符串 例如:str=name, preString=get -> return getName * * @param str 被处理的字符串 * @param preString 添加的首部 * @return 处理后的字符串 */ public static String upperFirstAndAddPre(String str, String preString) { if (str == null || preString == null) { return null; } return preString + capitalize(str); } /** * 去掉指定前缀 * * @param str 字符串 * @param prefix 前缀 * @return 切掉后的字符串,若前缀不是 preffix, 返回原字符串 */ public static String removePrefix(String str, String prefix) { if (isEmpty(str) || isEmpty(prefix)) { return str; } if (str.startsWith(prefix)) { return str.substring(prefix.length()); } return str; } /** * 忽略大小写去掉指定前缀 * * @param str 字符串 * @param prefix 前缀 * @return 切掉后的字符串,若前缀不是 prefix, 返回原字符串 */ public static String removePrefixIgnoreCase(String str, String prefix) { if (isEmpty(str) || isEmpty(prefix)) { return str; } if (str.toLowerCase().startsWith(prefix.toLowerCase())) { return str.substring(prefix.length()); } return str; } /** * 去掉指定后缀 * * @param str 字符串 * @param suffix 后缀 * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串 */ public static String removeSuffix(String str, String suffix) { if (isEmpty(str) || isEmpty(suffix)) { return str; } if (str.endsWith(suffix)) { return str.substring(0, str.length() - suffix.length()); } return str; } /** * 获得字符串对应byte数组 * * @param str 字符串 * @param charset 编码,如果为<code>null</code>使用系统默认编码 * @return bytes */ public static byte[] getBytes(String str, Charset charset) { if (null == str) { return null; } return null == charset ? str.getBytes() : str.getBytes(charset); } /** * 忽略大小写去掉指定后缀 * * @param str 字符串 * @param suffix 后缀 * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串 */ public static String removeSuffixIgnoreCase(String str, String suffix) { if (isEmpty(str) || isEmpty(suffix)) { return str; } if (str.toLowerCase().endsWith(suffix.toLowerCase())) { return str.substring(0, str.length() - suffix.length()); } return str; } /** * 如果给定字符串不是以prefix开头的,在开头补充 prefix * * @param str 字符串 * @param prefix 前缀 * @return 补充后的字符串 */ public static String addPrefixIfNot(String str, String prefix) { if (isEmpty(str) || isEmpty(prefix)) { return str; } if (!str.startsWith(prefix)) { str = prefix + str; } return str; } /** * 如果给定字符串不是以suffix结尾的,在尾部补充 suffix * * @param str 字符串 * @param suffix 后缀 * @return 补充后的字符串 */ public static String addSuffixIfNot(String str, String suffix) { if (isEmpty(str) || isEmpty(suffix)) { return str; } if (!str.endsWith(suffix)) { str += suffix; } return str; } /** * 清理空白字符 * * @param str 被清理的字符串 * @return 清理后的字符串 */ public static String cleanBlank(String str) { if (str == null) { return null; } return str.replaceAll("\\s*", EMPTY); } /** * 切分字符串<br> * from jodd * * @param str 被切分的字符串 * @param delimiter 分隔符 * @return 字符串 */ public static String[] split(String str, String delimiter) { if (str == null) { return null; } if (str.trim().length() == 0) { return new String[]{str}; } // del length int dellen = delimiter.length(); // one more for the last int maxparts = (str.length() / dellen) + 2; int[] positions = new int[maxparts]; int i, j = 0; int count = 0; positions[0] = -dellen; while ((i = str.indexOf(delimiter, j)) != -1) { count++; positions[count] = i; j = i + dellen; } count++; positions[count] = str.length(); String[] result = new String[count]; for (i = 0; i < count; i++) { result[i] = str.substring(positions[i] + dellen, positions[i + 1]); } return result; } /** * 改进JDK subString<br> * index从0开始计算,最后一个字符为-1<br> * 如果from和to位置一样,返回 "" <br> * 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br> * 如果经过修正的index中from大于to,则互换from和to * example: <br> * abcdefgh 2 3 -> c <br> * abcdefgh 2 -3 -> cde <br> * * @param string String * @param fromIndex 开始的index(包括) * @param toIndex 结束的index(不包括) * @return 字串 */ public static String sub(String string, int fromIndex, int toIndex) { int len = string.length(); if (fromIndex < 0) { fromIndex = len + fromIndex; if (fromIndex < 0) { fromIndex = 0; } } else if (fromIndex >= len) { fromIndex = len - 1; } if (toIndex < 0) { toIndex = len + toIndex; if (toIndex < 0) { toIndex = len; } } else if (toIndex > len) { toIndex = len; } if (toIndex < fromIndex) { int tmp = fromIndex; fromIndex = toIndex; toIndex = tmp; } if (fromIndex == toIndex) { return EMPTY; } char[] strArray = string.toCharArray(); char[] newStrArray = Arrays.copyOfRange(strArray, fromIndex, toIndex); return new String(newStrArray); } /** * 切割前部分 * * @param string 字符串 * @param toIndex 切割到的位置(不包括) * @return 切割后的字符串 */ public static String subPre(String string, int toIndex) { return sub(string, 0, toIndex); } /** * 切割后部分 * * @param string 字符串 * @param fromIndex 切割开始的位置(包括) * @return 切割后的字符串 */ public static String subSuf(String string, int fromIndex) { if (isEmpty(string)) { return null; } return sub(string, fromIndex, string.length()); } /** * 给定字符串是否被字符包围 * * @param str 字符串 * @param prefix 前缀 * @param suffix 后缀 * @return 是否包围,空串不包围 */ public static boolean isSurround(String str, String prefix, String suffix) { if (StringUtils.isBlank(str)) { return false; } if (str.length() < (prefix.length() + suffix.length())) { return false; } return str.startsWith(prefix) && str.endsWith(suffix); } // /** // * 给定字符串是否被字符包围 // * // * @param str 字符串 // * @param prefix 前缀 // * @param suffix 后缀 // * @return 是否包围,空串不包围 // */ // public static boolean isSurround(String str, char prefix, char suffix) { // if (StringUtils.isBlank(str)) { // return false; // } // if (str.length() < 2) { // return false; // } // // return str.charAt(0) == prefix && str.charAt(str.length() - 1) == suffix; // } /** * 重复某个字符 * * @param c 被重复的字符 * @param count 重复的数目 * @return 重复字符字符串 */ public static String repeat(char c, int count) { char[] result = new char[count]; for (int i = 0; i < count; i++) { result[i] = c; } return new String(result); } /** * 重复某个字符串 * * @param str 被重复的字符 * @param count 重复的数目 * @return 重复字符字符串 */ public static String repeat(String str, int count) { // 检查 final int len = str.length(); final long longSize = (long) len * (long) count; final int size = (int) longSize; if (size != longSize) { throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize); } final char[] array = new char[size]; str.getChars(0, len, array, 0); int n; // n <<= 1相当于n *2 for (n = len; n < size - n; n <<= 1) { System.arraycopy(array, 0, array, n, n); } System.arraycopy(array, 0, array, n, size - n); return new String(array); } /** * 比较两个字符串(大小写敏感)。 * <p> * <pre> * equals(null, null) = true * equals(null, "abc") = false * equals("abc", null) = false * equals("abc", "abc") = true * equals("abc", "ABC") = false * </pre> * * @param str1 要比较的字符串1 * @param str2 要比较的字符串2 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> */ public static boolean equals(String str1, String str2) { if (str1 == null) { return str2 == null; } return str1.equals(str2); } /** * 比较两个字符串(大小写不敏感)。 * <p> * <pre> * equalsIgnoreCase(null, null) = true * equalsIgnoreCase(null, "abc") = false * equalsIgnoreCase("abc", null) = false * equalsIgnoreCase("abc", "abc") = true * equalsIgnoreCase("abc", "ABC") = true * </pre> * * @param str1 要比较的字符串1 * @param str2 要比较的字符串2 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> */ public static boolean equalsIgnoreCase(String str1, String str2) { if (str1 == null) { return str2 == null; } return str1.equalsIgnoreCase(str2); } /** * 格式化文本, {} 表示占位符<br> * 例如:format("aaa {} ccc", "bbb") ----> aaa bbb ccc * * @param template 文本模板,被替换的部分用 {} 表示 * @param values 参数值 * @return 格式化后的文本 */ public static String format(String template, Object... values) { if (isBlank(template)) { return template; } final StringBuilder sb = new StringBuilder(); final int length = template.length(); int valueIndex = 0; char currentChar; for (int i = 0; i < length; i++) { if (valueIndex >= values.length) { sb.append(sub(template, i, length)); break; } currentChar = template.charAt(i); if (currentChar == '{') { final char nextChar = template.charAt(++i); if (nextChar == '}') { sb.append(values[valueIndex++]); } else { sb.append('{').append(nextChar); } } else { sb.append(currentChar); } } return sb.toString(); } /** * 格式化文本,使用 {varName} 占位<br> * map = {a: "aValue", b: "bValue"} * format("{a} and {b}", map) ----> aValue and bValue * * @param template 文本模板,被替换的部分用 {key} 表示 * @param map 参数值对 * @return 格式化后的文本 */ public static String format(String template, Map<?, ?> map) { if (null == map || map.isEmpty()) { return template; } for (Map.Entry<?, ?> entry : map.entrySet()) { template = template.replace("{" + entry.getKey() + "}", entry.getValue().toString()); } return template; } /** * 编码字符串 * * @param str 字符串 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @return 编码后的字节码 */ public static byte[] bytes(String str, String charset) { return bytes(str, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset)); } /** * 编码字符串 * * @param str 字符串 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @return 编码后的字节码 */ public static byte[] bytes(String str, Charset charset) { if (str == null) { return null; } if (null == charset) { return str.getBytes(); } return str.getBytes(charset); } /** * 将byte数组转为字符串 * * @param bytes byte数组 * @param charset 字符集 * @return 字符串 */ public static String str(byte[] bytes, String charset) { return str(bytes, isBlank(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(); } /** * 字符串转换为byteBuffer * * @param str 字符串 * @param charset 编码 * @return byteBuffer */ public static ByteBuffer byteBuffer(String str, String charset) { return ByteBuffer.wrap(StringUtils.bytes(str, charset)); } /** * 以 conjunction 为分隔符将多个对象转换为字符串 * * @param conjunction 分隔符 * @param objs 数组 * @return 连接后的字符串 */ public static String join(String conjunction, Object... objs) { StringBuilder sb = new StringBuilder(); boolean isFirst = true; for (Object item : objs) { if (isFirst) { isFirst = false; } else { sb.append(conjunction); } sb.append(item); } return sb.toString(); } /** * 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br> * 例如:HelloWorld->hello_world * * @param camelCaseStr 转换前的驼峰式命名的字符串 * @return 转换后下划线大写方式命名的字符串 */ public static String camelCaseToPath(String camelCaseStr) { if (camelCaseStr == null) { return null; } final int length = camelCaseStr.length(); StringBuilder sb = new StringBuilder(); char c; boolean isPreUpperCase = false; for (int i = 0; i < length; i++) { c = camelCaseStr.charAt(i); boolean isNextUpperCase = true; if (i < (length - 1)) { isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1)); } if (Character.isUpperCase(c)) { if (!isPreUpperCase || !isNextUpperCase) { if (i > 0) { sb.append("/"); } } isPreUpperCase = true; } else { isPreUpperCase = false; } sb.append(Character.toLowerCase(c)); } return sb.toString(); } /** * 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br> * 例如:HelloWorld->hello_world * * @param camelCaseStr 转换前的驼峰式命名的字符串 * @return 转换后下划线大写方式命名的字符串 */ public static String camelCaseToUnderline(String camelCaseStr) { if (camelCaseStr == null) { return null; } final int length = camelCaseStr.length(); StringBuilder sb = new StringBuilder(); char c; boolean isPreUpperCase = false; for (int i = 0; i < length; i++) { c = camelCaseStr.charAt(i); boolean isNextUpperCase = true; if (i < (length - 1)) { isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1)); } if (Character.isUpperCase(c)) { if (!isPreUpperCase || !isNextUpperCase) { if (i > 0) { sb.append(UNDERLINE); } } isPreUpperCase = true; } else { isPreUpperCase = false; } sb.append(Character.toLowerCase(c)); } return sb.toString(); } /** * 将下划线方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br> * 例如:hello_world->HelloWorld * * @param name 转换前的下划线大写方式命名的字符串 * @return 转换后的驼峰式命名的字符串 */ public static String underlineToCamelCase(String name) { if (name == null) { return null; } if (name.contains(UNDERLINE)) { name = name.toLowerCase(); StringBuilder sb = new StringBuilder(name.length()); boolean upperCase = false; for (int i = 0; i < name.length(); i++) { char c = name.charAt(i); if (c == '_') { upperCase = true; } else if (upperCase) { sb.append(Character.toUpperCase(c)); upperCase = false; } else { sb.append(c); } } return sb.toString(); } else { return name; } } /** * 包装指定字符串 * * @param str 被包装的字符串 * @param prefix 前缀 * @param suffix 后缀 * @return 包装后的字符串 */ public static String wrap(String str, String prefix, String suffix) { return format("{}{}{}", prefix, str, suffix); } /** * 指定字符串是否被包装 * * @param str 字符串 * @param prefix 前缀 * @param suffix 后缀 * @return 是否被包装 */ public static boolean isWrap(String str, String prefix, String suffix) { return str.startsWith(prefix) && str.endsWith(suffix); } /** * 指定字符串是否被同一字符包装(前后都有这些字符串) * * @param str 字符串 * @param wrapper 包装字符串 * @return 是否被包装 */ public static boolean isWrap(String str, String wrapper) { return isWrap(str, wrapper, wrapper); } /** * 指定字符串是否被同一字符包装(前后都有这些字符串) * * @param str 字符串 * @param wrapper 包装字符 * @return 是否被包装 */ public static boolean isWrap(String str, char wrapper) { return isWrap(str, wrapper, wrapper); } /** * 指定字符串是否被包装 * * @param str 字符串 * @param prefixChar 前缀 * @param suffixChar 后缀 * @return 是否被包装 */ public static boolean isWrap(String str, char prefixChar, char suffixChar) { return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar; } /** * 创建StringBuilder对象 * * @return StringBuilder对象 */ public static StringBuilder builder() { return new StringBuilder(); } /** * 创建StringBuilder对象 * * @return StringBuilder对象 */ public static StringBuilder builder(int capacity) { return new StringBuilder(capacity); } /** * 创建StringBuilder对象 * * @return StringBuilder对象 */ public static StringBuilder builder(String... strs) { final StringBuilder sb = new StringBuilder(); for (String str : strs) { sb.append(str); } return sb; } public static String concatLikeStart(String value) { return concatLike(value, 1); } public static String concatLikeEnd(String value) { return concatLike(value, 2); } public static String concatLikeAll(String value) { return concatLike(value, -1); } /** * @param value * @param type * @return */ public static String concatLike(String value, Integer type) { if (isEmpty(value)) { return null; } StringBuilder builder = new StringBuilder(value.length() + 3); switch (type) { case 1: builder.append("%").append(value); break; case 2: builder.append(value).append("%"); break; case 3: builder.append(value); break; default: builder.append("%").append(value).append("%"); } return builder.toString(); } /** * 获得StringReader * * @param str 字符串 * @return StringReader */ public static StringReader getReader(String str) { return new StringReader(str); } /** * 获得StringWriter * * @return StringWriter */ public static StringWriter getWriter() { return new StringWriter(); } /** * 编码字符串 * * @param str 字符串 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @return 编码后的字节码 */ public static byte[] encode(String str, String charset) { if (str == null) { return null; } if (isBlank(charset)) { return str.getBytes(); } try { return str.getBytes(charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException(format("Charset [{}] unsupported!", charset)); } } /** * 解码字节码 * * @param data 字符串 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @return 解码后的字符串 */ public static String decode(byte[] data, String charset) { if (data == null) { return null; } if (isBlank(charset)) { return new String(data); } try { return new String(data, charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException(format("Charset [{}] unsupported!", charset)); } } // /** // * 首字母变大写 // */ // public static String firstCharToUpperCase(String str) { // char firstChar = str.charAt(0); // if (firstChar >= 'a' && firstChar <= 'z') { // char[] arr = str.toCharArray(); // arr[0] -= ('a' - 'A'); // return new String(arr); // } // return str; // } /** * Description:把数字转化为指定长度的字符串编号,不足位数字前补0,超过或与指定长度相等返回原数值 * 例如:23转化为4位字符编号 => "0023" * * @param val 原数值 * @param num 字符串长度 * @return java.lang.String * @author fanhq * @date 2020/4/17 9:44 */ public static String intToStringCode(Integer val, Integer num) { int i = num - val.toString().length(); StringBuffer sbf = new StringBuffer(); for (int k = 0; k < i; k++) { sbf.append("0"); } return sbf.append(val.toString()).toString(); } public static String match(String message, String regex) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(message); while (m.find()) { return m.group(); } return null; } public static String lpad(Integer length, String data, char text) { if (data.length() >= length) { return data; } StringBuffer stringBuffer = new StringBuffer(); for (int i = data.length(); i < length; i++) { stringBuffer.append(text); } return stringBuffer.append(data).toString(); } } screen-api/src/main/resources/application-dev.yml
@@ -115,10 +115,12 @@ - /webjars/** - /verificationCode/** - /static/** - /file/preview/** AES: KEY: AD42F7787B035B7580000EF93BE20BAD TOKEN: KEY: foh3wi2ooghiCh5 foh3wi2ooghiCh5 file: path: /data/upload/ screen-api/src/main/resources/application-qa.yml
@@ -128,7 +128,7 @@ - /webjars/** - /verificationCode/** - /static/** - /file/** - /file/preview/** AES: @@ -138,3 +138,5 @@ KEY: foh3wi2ooghiCh5 file: path: E:\upload screen-api/src/main/resources/mapper/FileTableMapper.xml
New file @@ -0,0 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.moral.api.mapper.FileTableMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.moral.api.entity.FileTable"> <id column="file_id" property="fileId" /> <result column="file_module" property="fileModule" /> <result column="relation_id" property="relationId" /> <result column="file_name" property="fileName" /> <result column="file_type" property="fileType" /> <result column="file_address" property="fileAddress" /> <result column="file_size" property="fileSize" /> <result column="is_del" property="isDel" /> <result column="create_id" property="createId" /> <result column="create_name" property="createName" /> <result column="create_time" property="createTime" /> </resultMap> </mapper>