diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 9dc18424..f70deefb 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -92,6 +92,7 @@ public class ShiroConfig { filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码 filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码 filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token + filterChainDefinitionMap.put("/zyk/zykInfo/static/**", "anon");//图片预览 &下载文件不限制token filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览 filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件 filterChainDefinitionMap.put("/wxpay/**", "anon");//微信接口 diff --git a/jeecg-module-main/pom.xml b/jeecg-module-main/pom.xml index 6624adce..a7cdf312 100644 --- a/jeecg-module-main/pom.xml +++ b/jeecg-module-main/pom.xml @@ -80,8 +80,11 @@ hutool-http ${hutool.version} - - + + com.jcraft + jsch + 0.1.55 + diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/controller/ZykController.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/controller/ZykController.java new file mode 100644 index 00000000..3fc44c85 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/controller/ZykController.java @@ -0,0 +1,193 @@ +package org.jeecg.modules.zyk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.constant.SymbolConstant; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.zyk.entity.ZykInfo; +import org.jeecg.modules.zyk.service.IZykService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; + +/** +* @Description: 资源库信息 +* @Author: jeecg-boot +* @Date: 2024-05-16 +* @Version: V1.0 +*/ +@Api(tags="资源库信息") +@RestController +@RequestMapping("/zyk/zykInfo") +@Slf4j +public class ZykController extends JeecgController { + + @Autowired + private IZykService zykService; + + @AutoLog(value = "资源库信息-分页列表查询") + @ApiOperation(value="资源库信息-分页列表查询", notes="资源库信息-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList(ZykInfo zykInfo, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + Page pageList = zykService.findPage(zykInfo,new Page(pageNo, pageSize)); + return Result.OK(pageList); + } + + + @AutoLog(value = "资源库信息-添加") + @ApiOperation(value="资源库信息-添加", notes="资源库信息-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ZykInfo zykInfo) { + String res = zykService.saveInfo(zykInfo); + return Result.OK(res); + } + + /** + * 编辑 + * @param zykInfo + * @return + */ + @AutoLog(value = "资源库信息-编辑") + @ApiOperation(value="资源库信息-编辑", notes="资源库信息-编辑") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) + public Result edit(@RequestBody ZykInfo zykInfo) { + String res = zykService.modifyInfo(zykInfo); + return Result.OK(res); + } + + /** + * 通过id删除 + * @param id + * @return + */ + @AutoLog(value = "资源库信息-通过id删除") + @ApiOperation(value="资源库信息-通过id删除", notes="资源库信息-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + String res = zykService.removeById(id); + return Result.OK(res); + } + + /** + * 批量删除 + * @param ids + * @return + */ + @AutoLog(value = "资源库信息-批量删除") + @ApiOperation(value="资源库信息-批量删除", notes="资源库信息-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + String res = zykService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK(res); + } + + /** + * 预览图片&下载文件 + * 请求地址:http://localhost:8080/common/static/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg} + * @param request + * @param response + */ +// @GetMapping(value = "/static/**") +// public void view(HttpServletRequest request, HttpServletResponse response) { +// // ISO-8859-1 ==> UTF-8 进行编码转换 +// String filePath = extractPathFromPattern(request); +// if(oConvertUtils.isEmpty(filePath) || CommonConstant.STRING_NULL.equals(filePath)){ +// return; +// } +// // 其余处理略 +// InputStream inputStream = null; +// OutputStream outputStream = null; +// try { +// filePath = filePath.replace("..", "").replace("../",""); +// if (filePath.endsWith(SymbolConstant.COMMA)) { +// filePath = filePath.substring(0, filePath.length() - 1); +// } +// Map map = zykService.downloadRemoteFile(filePath); +// if(!map.get("code").equals("0")){ +// throw new RuntimeException(map.get("msg")); +// } +// String localFilePath = map.get("data"); +// File file = new File(localFilePath); +// if(!file.exists()){ +// response.setStatus(404); +// throw new RuntimeException("文件["+filePath+"]不存在.."); +// } +// // 设置强制下载不打开 +// response.setContentType("application/force-download"); +// response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1")); +// inputStream = new BufferedInputStream(new FileInputStream(localFilePath)); +// outputStream = response.getOutputStream(); +// byte[] buf = new byte[1024]; +// int len; +// while ((len = inputStream.read(buf)) > 0) { +// outputStream.write(buf, 0, len); +// } +// response.flushBuffer(); +// } catch (IOException e) { +// log.error("预览文件失败" + e.getMessage()); +// response.setStatus(404); +// e.printStackTrace(); +// } finally { +// if (inputStream != null) { +// try { +// inputStream.close(); +// } catch (IOException e) { +// log.error(e.getMessage(), e); +// } +// } +// if (outputStream != null) { +// try { +// outputStream.close(); +// } catch (IOException e) { +// log.error(e.getMessage(), e); +// } +// } +// } +// } + @GetMapping(value = "/static/**") + public void view(HttpServletRequest request, HttpServletResponse response) { + // ISO-8859-1 ==> UTF-8 进行编码转换 + String filePath = extractPathFromPattern(request); + if(oConvertUtils.isEmpty(filePath) || CommonConstant.STRING_NULL.equals(filePath)){ + return; + } + try { + filePath = filePath.replace("..", "").replace("../",""); + if (filePath.endsWith(SymbolConstant.COMMA)) { + filePath = filePath.substring(0, filePath.length() - 1); + } + zykService.downloadRes(filePath,response); + } catch (Exception e) { + log.error("预览文件失败" + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 把指定URL后的字符串全部截断当成参数 + * 这么做是为了防止URL中包含中文或者特殊字符(/等)时,匹配不了的问题 + * @param request + * @return + */ + private static String extractPathFromPattern(final HttpServletRequest request) { + String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path); + } + +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/entity/ZykInfo.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/entity/ZykInfo.java new file mode 100644 index 00000000..bcee25f7 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/entity/ZykInfo.java @@ -0,0 +1,71 @@ +package org.jeecg.modules.zyk.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +import java.io.Serializable; +import java.util.Date; + +@Data +@ApiModel(value="zyk_info对象", description="资源库信息") +public class ZykInfo implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private String id; + @ApiModelProperty(value = "创建人") + private String createBy; + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建时间") + private Date createTime; + @ApiModelProperty(value = "修改人") + private String updateBy; + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "修改时间") + private Date updateTime; + /**业务ID*/ + @ApiModelProperty(value = "业务ID") + private String bizId; + /**业务表*/ + @ApiModelProperty(value = "业务表") + private String bizTable; + /**学期学年*/ + @ApiModelProperty(value = "学期学年") + private String xqxn; + /**开课单位*/ + @ApiModelProperty(value = "开课单位") + private String kkdw; + /**课程名称*/ + @ApiModelProperty(value = "课程名称") + private String kcmc; + /**授课教师*/ + @ApiModelProperty(value = "授课教师") + private String skjs; + /**文件类型*/ + @ApiModelProperty(value = "文件类型") + private String wjlx; + /**文件名称*/ + @ApiModelProperty(value = "文件名称") + private String fileName; + /**学号*/ + @TableField(exist = false) + private String xh; + /**次*/ + @TableField(exist = false) + private String seq; + /**章*/ + @TableField(exist = false) + private String chapter; + /**节*/ + @TableField(exist = false) + private String section; + +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/ZykMapper.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/ZykMapper.java new file mode 100644 index 00000000..da768305 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/ZykMapper.java @@ -0,0 +1,22 @@ +package org.jeecg.modules.zyk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.jeecg.modules.zyk.entity.ZykInfo; + +import java.util.List; + +/** + * @Description: 资源库信息 + * @Author: jeecg-boot + * @Date: 2024-05-16 + * @Version: V1.0 + */ +public interface ZykMapper extends BaseMapper { + List findPage(Page page, ZykInfo params); + ZykInfo getById(@Param("id")String id); + void addInfo(ZykInfo zykInfo); + void modifyInfo(ZykInfo zykInfo); + ZykInfo getByBiz(ZykInfo zykInfo); +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/xml/ZykMapper.xml b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/xml/ZykMapper.xml new file mode 100644 index 00000000..5f966784 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/mapper/xml/ZykMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + insert into zyk_info( + id, + create_by, + create_time, + biz_id, + biz_table, + xqxn, + kkdw, + kcmc, + skjs, + wjlx, + file_name, + xh, + seq, + chapter, + section + ) + value( + #{id}, + #{createBy}, + #{createTime}, + #{bizId}, + #{bizTable}, + #{xqxn}, + #{kkdw}, + #{kcmc}, + #{skjs}, + #{wjlx}, + #{fileName}, + #{xh}, + #{seq}, + #{chapter}, + #{section} + ) + + + + update zyk_info + set + update_by = #{updateBy}, + update_time = #{updateTime}, + file_name = #{fileName} + where id = #{id} + + + + delete from zyk_info where id = #{id} + + + + + \ No newline at end of file diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/IZykService.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/IZykService.java new file mode 100644 index 00000000..9b3c5c00 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/IZykService.java @@ -0,0 +1,56 @@ +package org.jeecg.modules.zyk.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.zyk.entity.ZykInfo; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +/** + * @Description: 资源库信息 + * @Author: jeecg-boot + * @Date: 2024-05-16 + * @Version: V1.0 + */ +public interface IZykService extends IService { + + Page findPage(ZykInfo zykInfo, Page page); + + String saveInfo(ZykInfo zykInfo); + + String modifyInfo(ZykInfo zykInfo); + + String removeById(String id); + + String removeByIds(List list); + + /** + * 下载远端文件(预留) + * @param filePath + * @return 下载结果 + */ +// Map downloadRemoteFile(String filePath); + + /** + * 下载远端文件流(含接口) + * @param filePath + */ + void downloadRes(String filePath, HttpServletResponse response) throws Exception; + + /** + * 更新到资源库(接口) + * @param zykInfo + * @return 上传结果 + */ + Map saveToZyk(ZykInfo zykInfo); + + /** + * 删除资源库(接口) + * @param zykInfo + * @return 上传结果 + */ + Map deleteZyk(ZykInfo zykInfo); + +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/impl/ZykServiceImpl.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/impl/ZykServiceImpl.java new file mode 100644 index 00000000..28cebe34 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/service/impl/ZykServiceImpl.java @@ -0,0 +1,208 @@ +package org.jeecg.modules.zyk.service.impl; + +import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.modules.zyk.entity.ZykInfo; +import org.jeecg.modules.zyk.mapper.ZykMapper; +import org.jeecg.modules.zyk.service.IZykService; +import org.jeecg.modules.zyk.utils.util.FileHandleUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Description: 资源库信息 + * @Author: jeecg-boot + * @Date: 2024-05-16 + * @Version: V1.0 + */ +@Service +public class ZykServiceImpl extends ServiceImpl implements IZykService { + + @Autowired + private FileHandleUtil fileHandleUtil; + + @Autowired + private ZykMapper zykMapper; + + @Override + public Page findPage(ZykInfo zykInfo, Page page){ + List list = zykMapper.findPage(page,zykInfo); + page.setRecords(list); + return page; + } + + @Override + public String saveInfo(ZykInfo zykInfo){ + Map map = fileHandleUtil.uploadFile(zykInfo); + if(!map.get("code").equals("0")){ + return map.get("msg"); + } + zykInfo.setFileName(map.get("data")); + LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + zykInfo.setCreateBy(user.getUsername()); + zykInfo.setCreateTime(new Date()); + Long id = new DefaultIdentifierGenerator().nextId(new ZykInfo()); + zykInfo.setId(id.toString()); + zykMapper.addInfo(zykInfo); + return "添加成功!"; + } + + @Override + public String modifyInfo(ZykInfo zykInfo){ + Map map = fileHandleUtil.uploadFile(zykInfo); + if(!map.get("code").equals("0")){ + return map.get("msg"); + } + zykInfo.setFileName(map.get("data")); + LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + zykInfo.setUpdateBy(user.getUsername()); + zykInfo.setUpdateTime(new Date()); + zykMapper.modifyInfo(zykInfo); + return "编辑成功!"; + } + + @Override + public String removeById(String id){ + ZykInfo zykInfo = zykMapper.getById(id); + if(zykInfo.getFileName() != null && !zykInfo.getFileName().equals("")){ + String[] df = fileHandleUtil.getDirectoryAndFileName(zykInfo.getFileName()); + if(!df[0].equals("")&&!df[1].equals("")){ + fileHandleUtil.delete(df[0],df[1]); + } + } + zykMapper.deleteById(id); + return "删除成功!"; + } + + @Override + public String removeByIds(List list){ + for(int i=0;i downloadRemoteFile(String filePath){ +// Map map = new HashMap(); +// map.put("code","0"); +// if(filePath == null || filePath.equals("")){ +// map.put("code","1"); +// map.put("msg","文件路径不能为空!"); +// } +// if(filePath.lastIndexOf("/")==-1){ +// map.put("code","1"); +// map.put("msg","文件路径不存在!"); +// } +// String[] df = fileHandleUtil.getDirectoryAndFileName(filePath); +// if(df[0].equals("")){ +// map.put("code","1"); +// map.put("msg","文件路径不存在!"); +// } +// if(df[1].equals("")){ +// map.put("code","1"); +// map.put("msg","文件不存在!"); +// } +// Map downloadMap = fileHandleUtil.download(df[0],df[1]); +// if(!downloadMap.get("code").equals("0")){ +// return downloadMap; +// } +// map.put("data",downloadMap.get("fileName")); +// return map; +// } + + /** + * 下载远端文件流(含接口) + * @param filePath + */ + @Override + public void downloadRes(String filePath, HttpServletResponse response) throws Exception { + if(filePath == null || filePath.equals("")){ + throw new RuntimeException("文件["+filePath+"]不存在!"); + } + if(filePath.lastIndexOf("/")==-1){ + throw new RuntimeException("文件路径不存在!"); + } + String[] df = fileHandleUtil.getDirectoryAndFileName(filePath); + if(df[0].equals("")){ + throw new RuntimeException("文件路径不存在!"); + } + if(df[1].equals("")){ + throw new RuntimeException("文件不存在!"); + } + fileHandleUtil.downloadRes(df[0],df[1],response); + } + + /** + * 更新到资源库(接口) + * @param zykInfo + * @return 上传结果 + */ + @Override + public Map saveToZyk(ZykInfo zykInfo){ + Map map = fileHandleUtil.uploadFile(zykInfo); + if(!map.get("code").equals("0")){ + return map; + } + zykInfo.setFileName(map.get("data")); + ZykInfo entity = zykMapper.getByBiz(zykInfo); + LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(entity!=null){ + zykInfo.setUpdateBy(user.getUsername()); + zykInfo.setUpdateTime(new Date()); + zykInfo.setId(entity.getId()); + zykMapper.modifyInfo(zykInfo); + }else{ + zykInfo.setCreateBy(user.getUsername()); + zykInfo.setCreateTime(new Date()); + Long id = new DefaultIdentifierGenerator().nextId(new ZykInfo()); + zykInfo.setId(id.toString()); + zykMapper.addInfo(zykInfo); + } + return map; + } + + /** + * 删除资源库(接口) + * @param zykInfo + * @return 上传结果 + */ + @Override + public Map deleteZyk(ZykInfo zykInfo){ + Map map = new HashMap(); + map.put("code","0"); + ZykInfo entity = zykMapper.getByBiz(zykInfo); + if(entity.getFileName() != null && !entity.getFileName().equals("")){ + String[] df = fileHandleUtil.getDirectoryAndFileName(entity.getFileName()); + if(!df[0].equals("")&&!df[1].equals("")){ + fileHandleUtil.delete(df[0],df[1]); + } + } + zykMapper.deleteById(entity.getId()); + map.put("msg","删除成功!"); + return map; + } + +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SFTPUtil.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SFTPUtil.java new file mode 100644 index 00000000..258f2ec3 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SFTPUtil.java @@ -0,0 +1,399 @@ +package org.jeecg.modules.zyk.utils.sftp; + +import com.jcraft.jsch.*; +import java.io.*; + +import org.jeecg.common.util.CommonUtils; +import org.jeecg.modules.zyk.utils.text.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; +import java.util.*; + +@Service +public class SFTPUtil { + private long count = 3; + private long count1 = 0; + private long sleepTime = 300000;//5分钟 + private static final Logger logger = LoggerFactory.getLogger(SFTPUtil.class); + + @Autowired + private SftpConfig sftpConfig; + + public ChannelSftp connect(){ + ChannelSftp sftp = null; + try { + JSch jsch = new JSch(); + Session sshSession = jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort()); + logger.info("Session created ... host=" + sftpConfig.getHostname() + ";port=" + sftpConfig.getPort()+";UserName=" + sftpConfig.getUsername() + ";Password="+sftpConfig.getPassword()); +// jsch.addIdentity("e:/sftp_keys.ppk",""); + sshSession.setPassword(sftpConfig.getPassword()); + Properties sshConfig = new Properties(); + sshConfig.put("StrictHostKeyChecking", "no"); + sshSession.setConfig(sshConfig); + sshSession.setTimeout(sftpConfig.getTimeout()); + sshSession.connect(); + logger.info("Session connected ..."); + logger.info("Opening Channel ..."); + Channel channel = sshSession.openChannel("sftp"); + channel.connect(); + sftp = (ChannelSftp) channel; + logger.info("登录成功"); + } catch (Exception e){ + try{ + count1 += 1; + if(count == count1){ + throw new RuntimeException(e); + } + Thread.sleep(sleepTime); + logger.info("重新连接...."); + connect(); + } catch (InterruptedException e1){ + throw new RuntimeException(e1); + } + } + return sftp; + } + + private void mkdirs(String directory,ChannelSftp sftp) throws SftpException{ + String[] dics = directory.split("/"); + for(int i=0;i< dics.length;i++){ + try { + if(dics[i].equals("")){ + continue; + } + sftp.cd(dics[i]); + } catch (SftpException e1) { + try { + sftp.mkdir(dics[i]); + sftp.cd(dics[i]); + } catch (SftpException e2) { + throw new RuntimeException("打开文件夹错误,[{}]", e2); + } + } + } + } + + /** + * 上传文件 + * @param directory 上传的目录 + * @param uploadFilePath 要上传的文件路径(文件真实路径+名称) + * @param uploadFileName 要上传的文件名称(重新定义的文件名称) + * @param + */ + public Map upload(String directory, String uploadFilePath, String uploadFileName) { + Map map = new HashMap(); + map.put("code","0"); + map.put("msg","上传成功"); + ChannelSftp sftp = null; + try{ + sftp = connect(); + try { + directory = getDirectory(directory); + sftp.cd(directory); + } catch (SftpException e1) { + try { + mkdirs(directory,sftp); +// sftp.mkdir(directory); +// sftp.cd(directory); + } catch (SftpException e2) { + map.put("code","1"); + map.put("msg","ftp创建"+directory+"文件路径失败"); +// throw new RuntimeException("ftp创建文件路径失败" + directory); + } + } + File file = new File(uploadFilePath); + InputStream inputStream=null; + try { + inputStream = new FileInputStream(file); + sftp.put(inputStream, uploadFileName); + map.put("data",directory.concat(uploadFileName)); + } catch (Exception e3) { + map.put("code","1"); + map.put("msg","上传文件异常:" + e3.getMessage()); +// throw new RuntimeException("sftp异常" + e3); + } finally { + closeStream(inputStream,null); + } + }catch (Exception e) { + map.put("code","1"); + map.put("msg","sftp异常:" + e.getMessage()); + }finally { + if(sftp!=null){ + disConnect(sftp); + } + } + return map; + } + + /** + * 下载文件 + * + * @param directory 下载目录 + * @param downloadFile 下载的文件 + * @param saveFile 存在本地的路径 + */ + public Map download(String directory, String downloadFile, String saveFile) { + Map map = new HashMap(); + map.put("code","0"); + map.put("msg","删除成功"); + ChannelSftp sftp = null; + try{ + sftp = connect(); + OutputStream output = null; + try { + File localDirFile = new File(saveFile); + // 判断本地目录是否存在,不存在需要新建各级目录 + if (!localDirFile.exists()) { + localDirFile.mkdirs(); + } + if (logger.isInfoEnabled()) { + logger.info("开始获取远程文件:[{}]---->[{}]", new Object[]{directory, saveFile}); + } + sftp.cd(directory); + if (logger.isInfoEnabled()) { + logger.info("打开远程文件:[{}]", new Object[]{directory}); + } + String newName = CommonUtils.getFileName(downloadFile); + String newDownloadFile = saveFile.concat(File.separator).concat(newName); + output = new FileOutputStream(new File(newDownloadFile)); + sftp.get(downloadFile, output); + if (logger.isInfoEnabled()) { + logger.info("文件下载成功"); + } + map.put("fileName",newDownloadFile); + } catch (Exception e) { + if (logger.isInfoEnabled()) { + logger.info("文件下载出现异常,[{}]", e); + } + throw new RuntimeException("文件下载出现异常,[{}]", e); + } finally { + closeStream(null,output); + } + }catch (Exception e) { + map.put("code","1"); + map.put("msg","sftp异常:" + e.getMessage()); + }finally { + if(sftp!=null){ + disConnect(sftp); + } + } + return map; + } + + /** + * 网页下载文件 + * @param response + * @param directory + * @param downloadFile + * @throws Exception + */ + public void writeFileToRes(String directory, String downloadFile,HttpServletResponse response) throws Exception { + ChannelSftp sftp = null; + try{ + sftp = connect(); + InputStream inputStream = null; + ServletOutputStream outputStream=null; + try { + sftp.cd(directory); + inputStream = sftp.get(downloadFile); + byte[] buf = new byte[1024 * 10]; + outputStream = response.getOutputStream(); + response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(downloadFile, "UTF-8")); + int readLength; + while (((readLength = inputStream.read(buf)) != -1)) { + outputStream.write(buf, 0, readLength); + } + outputStream.flush(); + } catch (SftpException e1) { + e1.printStackTrace(); + throw new Exception(StringUtils.format("sftp exception,sftp exception。 ", e1.getMessage())); + } catch (IOException e2) { +// e2.printStackTrace(); +// throw new Exception(StringUtils.format("io exception,io exception 。 ", e2.getMessage())); + }finally { + closeStream(null,outputStream); + try { + if(inputStream!=null) { + inputStream.close(); + } + } catch (IOException e3) { + e3.printStackTrace(); + } + } + }catch (Exception e) { + e.printStackTrace(); + throw new Exception(StringUtils.format("sftp exception,sftp exception。 ", e.getMessage())); + }finally { + if(sftp!=null){ + disConnect(sftp); + } + } + } + + /** + * 删除文件 + * @param directory 要删除文件所在目录 + * @param deleteFile 要删除的文件 + */ + public Map delete(String directory, String deleteFile) { + Map map = new HashMap(); + map.put("code","0"); + map.put("msg","删除成功"); + ChannelSftp sftp = null; + try{ + sftp = connect(); + directory = delDiagonalLines(directory); + sftp.cd(directory); + sftp.rm(deleteFile); + }catch (Exception e) { + map.put("code","1"); + map.put("msg","sftp异常:" + e.getMessage()); + }finally { + if(sftp!=null){ + disConnect(sftp); + } + } + return map; + } + + private String getDirectory(String directory){ + String rootPath = sftpConfig.getUploadpath(); + if(rootPath.endsWith("/")){ + return sftpConfig.getUploadpath() + directory; + }else{ + return sftpConfig.getUploadpath() +"/"+ directory; + } + } + + private String delDiagonalLines(String directory){ + if(directory.startsWith("/")){ + directory = directory.substring(directory.indexOf("/")+1); + delDiagonalLines(directory); + } + return directory; + } + + /** + * 断掉连接 + */ + public void disConnect(ChannelSftp sftp) { + try { + sftp.disconnect(); + sftp.getSession().disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public SFTPUtil(long count, long sleepTime) { + this.count = count; + this.sleepTime = sleepTime; + } + + public SFTPUtil() { + + } + + /** + * 关闭流 + * @param outputStream + */ + private void closeStream(InputStream inputStream,OutputStream outputStream) { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(inputStream != null){ + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /*****************以下为预留方法*******************/ +// /** +// * 下载远程文件夹下的所有文件 +// * @param remoteFilePath +// * @param localDirPath +// * @throws Exception +// */ +// public void getFileDir(String remoteFilePath, String localDirPath) throws Exception { +// File localDirFile = new File(localDirPath); +// // 判断本地目录是否存在,不存在需要新建各级目录 +// if (!localDirFile.exists()) { +// localDirFile.mkdirs(); +// } +// if (logger.isInfoEnabled()) { +// logger.info("sftp文件服务器文件夹[{}],下载到本地目录[{}]", new Object[]{remoteFilePath, localDirFile}); +// } +// ChannelSftp channelSftp = connect(); +// Vector lsEntries = channelSftp.ls(remoteFilePath); +// if (logger.isInfoEnabled()) { +// logger.info("远程目录下的文件为[{}]", lsEntries); +// } +// for (LsEntry entry : lsEntries) { +// String fileName = entry.getFilename(); +// if (checkFileName(fileName)) { +// continue; +// } +// String remoteFileName = getRemoteFilePath(remoteFilePath, fileName); +// channelSftp.get(remoteFileName, localDirPath); +// } +// disConnect(channelSftp); +// } +// +// private boolean checkFileName(String fileName) { +// if (".".equals(fileName) || "..".equals(fileName)) { +// return true; +// } +// return false; +// } +// +// private String getRemoteFilePath(String remoteFilePath, String fileName) { +// if (remoteFilePath.endsWith("/")) { +// return remoteFilePath.concat(fileName); +// } else { +// return remoteFilePath.concat("/").concat(fileName); +// } +// } +// +// /** +// * 列出目录下的文件 +// * @param directory 要列出的目录 +// * @return +// * @throws SftpException +// */ +// public List listFiles(String directory) throws SftpException { +// ChannelSftp sftp = connect(); +// List fileNameList = new ArrayList(); +// try { +// sftp.cd(directory); +// } catch (SftpException e) { +// return fileNameList; +// } +// Vector vector = sftp.ls(directory); +// for (int i = 0; i < vector.size(); i++) { +// if (vector.get(i) instanceof LsEntry) { +// LsEntry lsEntry = (LsEntry) vector.get(i); +// String fileName = lsEntry.getFilename(); +// if (".".equals(fileName) || "..".equals(fileName)) { +// continue; +// } +// fileNameList.add(fileName); +// } +// } +// disConnect(sftp); +// return fileNameList; +// } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SftpConfig.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SftpConfig.java new file mode 100644 index 00000000..1b7b3c9b --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/sftp/SftpConfig.java @@ -0,0 +1,28 @@ +package org.jeecg.modules.zyk.utils.sftp; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "sftp") +@Data +public class SftpConfig { + private String hostname; + private Integer port; + private String username; + private String password; + private Integer timeout; + private String uploadpath; + + public SftpConfig(String hostname,Integer port,String username,String password,Integer timeout,String uploadpath){ + this.hostname = hostname; + this.port = port; + this.username = username; + this.password = password; + this.timeout = timeout; + this.uploadpath = uploadpath; + } + + public SftpConfig(){} +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/CharsetKit.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/CharsetKit.java new file mode 100644 index 00000000..e9e7a284 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/CharsetKit.java @@ -0,0 +1,85 @@ +package org.jeecg.modules.zyk.utils.text; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * 字符集工具类 + * + * @author ruoyi + */ +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 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(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(); + } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Constants.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Constants.java new file mode 100644 index 00000000..72b2c001 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Constants.java @@ -0,0 +1,115 @@ +package org.jeecg.modules.zyk.utils.text; + +/** + * 通用常量信息 + * + * @author ruoyi + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 系统用户授权缓存 + */ + public static final String SYS_AUTH_CACHE = "sys-authCache"; + + /** + * 参数管理 cache name + */ + public static final String SYS_CONFIG_CACHE = "sys-config"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache name + */ + public static final String SYS_DICT_CACHE = "sys-dict"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi:"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap:"; + + /** + * LDAPS 远程方法调用 + */ + public static final String LOOKUP_LDAPS = "ldaps:"; + + /** + * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) + */ + public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; + + /** + * 定时任务违规的字符 + */ + public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", + "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" }; +} \ No newline at end of file diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Convert.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Convert.java new file mode 100644 index 00000000..79a3f372 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/Convert.java @@ -0,0 +1,1000 @@ +package org.jeecg.modules.zyk.utils.text; + +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 ruoyi + */ +public class Convert +{ + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @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数组
+ * + * @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数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class 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对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @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
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和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 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 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("^整$", "零元整"); + } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StrFormatter.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StrFormatter.java new file mode 100644 index 00000000..9fab78b1 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StrFormatter.java @@ -0,0 +1,90 @@ +package org.jeecg.modules.zyk.utils.text; + +/** + * 字符串格式化 + * + * @author ruoyi + */ +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 = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @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(); + } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StringUtils.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StringUtils.java new file mode 100644 index 00000000..11421200 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/text/StringUtils.java @@ -0,0 +1,624 @@ +package org.jeecg.modules.zyk.utils.text; + +import org.springframework.util.AntPathMatcher; + +import java.util.*; + +/** + * 字符串工具类 + * + * @author ruoyi + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @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) || NULLSTR.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 NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + 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 NULLSTR; + } + + 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 NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @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 final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + 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; + } + + /** + * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * + * @param set 给定的集合 + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @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; + } + + /** + * 删除最后一个字符串 + * + * @param str 输入字符串 + * @param spit 以什么类型结尾的 + * @return 截取后的字符串 + */ + public static String lastStringDel(String str, String spit) + { + if (!StringUtils.isEmpty(str) && str.endsWith(spit)) + { + return str.subSequence(0, str.length() - 1).toString(); + } + return str; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如: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; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + 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 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 cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static final 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 final 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(); + } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/FileHandleUtil.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/FileHandleUtil.java new file mode 100644 index 00000000..a01a1d52 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/FileHandleUtil.java @@ -0,0 +1,212 @@ +package org.jeecg.modules.zyk.utils.util; + +import org.jeecg.modules.zyk.entity.ZykInfo; +import org.jeecg.modules.zyk.utils.sftp.SFTPUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +@Service +public class FileHandleUtil { + + @Autowired + private SFTPUtil sftpUtil; + + @Value(value = "${jeecg.path.upload}") + private String uploadpath; + + @Value(value = "${jeecg.path.webapp}") + private String downloadpath; + + public Map uploadFile(ZykInfo zykInfo){ + Map map = new HashMap(); + map.put("code","0"); + Map directoryMap = getDirectory(zykInfo); + if(!directoryMap.get("code").equals("0")){ + return directoryMap; + } + //资源库文件路径 + String directory = directoryMap.get("directory"); + //源文件路径 + Map fileNameMap = getFileName(zykInfo); + if(!fileNameMap.get("code").equals("0")){ + return fileNameMap; + } + //上传文件 + Map uploadMap = sftpUtil.upload(directory,fileNameMap.get("filePath"),fileNameMap.get("fileName")); + if(!uploadMap.get("code").equals("0")){ + return uploadMap; + } + map.put("data",uploadMap.get("data")); + return map; + } + + public String[] getDirectoryAndFileName(String fileName) { + String[] ss = new String[2]; + String path = fileName.substring(0,fileName.lastIndexOf("/")); + String name = fileName.substring(fileName.lastIndexOf("/")+1); + ss[0] = path; + ss[1] = name; + return ss; + } + + public Map download(String directory, String downloadFile){ + return sftpUtil.download(directory,downloadFile,getDownloadPath("temp")); + } + + public void downloadRes(String directory, String downloadFile,HttpServletResponse response) throws Exception{ + sftpUtil.writeFileToRes(directory,downloadFile,response); + } + + public void delete(String directory, String downloadFile){ + sftpUtil.delete(directory,downloadFile); + } + + /** + * 资源库文件路径 + * @param zykInfo + * @return + */ + private Map getDirectory(ZykInfo zykInfo){ + Map map = new HashMap(); + map.put("code","0"); + StringBuffer sb = new StringBuffer(); + if(zykInfo.getXqxn()==null || zykInfo.getXqxn().equals("")){ + map.put("code","1"); + map.put("msg","学期学年不能为空!"); + return map; + } + sb.append(zykInfo.getXqxn()); + sb.append("/"); + if(zykInfo.getKkdw()==null || zykInfo.getKkdw().equals("")){ + map.put("code","1"); + map.put("msg","开课单位不能为空!"); + return map; + } + sb.append(zykInfo.getKkdw()); + sb.append("/"); + if(zykInfo.getKcmc()==null || zykInfo.getKcmc().equals("")){ + map.put("code","1"); + map.put("msg","课程名称不能为空!"); + return map; + } + sb.append(zykInfo.getKcmc()); + sb.append("/"); + if(zykInfo.getSkjs()==null || zykInfo.getSkjs().equals("")){ + map.put("code","1"); + map.put("msg","授课教师不能为空!"); + return map; + } + sb.append(zykInfo.getSkjs()); + sb.append("/"); + if(zykInfo.getWjlx()==null || zykInfo.getWjlx().equals("")){ + map.put("code","1"); + map.put("msg","文件类型不能为空!"); + return map; + } + sb.append(zykInfo.getWjlx()); + sb.append("/"); + map.put("directory",sb.toString()); + return map; + } + + /** + * 获取文件路径和新文件名称 + * @param zykInfo + * @return + */ + private Map getFileName(ZykInfo zykInfo){ + Map map = new HashMap(); + map.put("code","0"); + String uploadFileName = getRealFileFullPath(zykInfo.getFileName()); + if(uploadFileName.equals("")){ + map.put("code","1"); + map.put("msg","文件路径不能为空!"); + return map; + } + File file = new File(uploadFileName); + if(!file.exists()){ + map.put("code","1"); + map.put("msg","文件["+zykInfo.getFileName()+"]不存在.."); + return map; + } + map.put("filePath",uploadFileName); + String fileName = uploadFileName.substring(uploadFileName.lastIndexOf('/')+1, uploadFileName.indexOf("_")); + String suffix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); + fileName = fileName + suffix; + if(zykInfo.getWjlx().equals(WjlxEnum.JXDG.getType())){ + String kcmc = zykInfo.getKcmc(); + fileName = kcmc+"_"+WjlxEnum.JXDG.getType()+suffix; + } + if(zykInfo.getWjlx().equals(WjlxEnum.JXRL.getType())){ + String kcmc = zykInfo.getKcmc(); + fileName = kcmc+"_"+WjlxEnum.JXRL.getType()+suffix; + } + if(zykInfo.getWjlx().equals(WjlxEnum.KCLW.getType())){ + String kcmc = zykInfo.getKcmc(); + fileName = kcmc+"_要求"+suffix; + } + if(zykInfo.getWjlx().equals(WjlxEnum.XSLW.getType())){ + String kcmc = zykInfo.getKcmc(); + String xh = zykInfo.getXh(); + String seq = zykInfo.getSeq(); + fileName = kcmc+"_"+xh+"_"+seq+suffix; + } + if(zykInfo.getWjlx().equals(WjlxEnum.JXDY.getType())){ + String kcmc = zykInfo.getKcmc(); + String chapter = zykInfo.getChapter(); + String section = zykInfo.getSection(); + fileName = kcmc+"_第"+chapter+"章_第"+section+"节"+suffix; + } + if(zykInfo.getWjlx().equals(WjlxEnum.QT.getType())){ + String kcmc = zykInfo.getKcmc(); + fileName = kcmc+"_其他_"+fileName; + } + map.put("fileName",fileName); + return map; + } + + /** + * 获取文件真实路径 + * @param path + * @return + */ + private String getRealFileFullPath(String path){ + String filePath = ""; + if(path==null || path.equals("")){ + return ""; + } + path = path.replace("\\", "/"); + int idx = path.indexOf(uploadpath); + if(idx==-1){ + filePath = uploadpath + File.separator + path; + }else{ + filePath = path; + } + return filePath; + } + + /** + * 获取文件真实路径 + * @param path + * @return + */ + private String getDownloadPath(String path){ + String filePath = ""; + if(path==null || path.equals("")){ + return ""; + } + int idx = path.indexOf(downloadpath); + if(idx==-1){ + filePath = downloadpath + File.separator + path; + }else{ + filePath = path; + } + return filePath; + } +} diff --git a/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/WjlxEnum.java b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/WjlxEnum.java new file mode 100644 index 00000000..8f324530 --- /dev/null +++ b/jeecg-module-main/src/main/java/org/jeecg/modules/zyk/utils/util/WjlxEnum.java @@ -0,0 +1,55 @@ +package org.jeecg.modules.zyk.utils.util; + +import org.apache.commons.lang3.StringUtils; + +/** + * @Description: 文件类型枚举类 + * @author: jeecg-boot + */ +public enum WjlxEnum { + + /**教学大纲*/ + JXDG("教学大纲"), + /**教学日历*/ + JXRL("教学日历"), + /**课程论文*/ + KCLW("课程论文"), + /**课程论文*/ + XSLW("学生论文"), + /**教学单元*/ + JXDY("教学单元"), + /**其他*/ + QT("其他"); + + /** + * 类型 + */ + private String type; + + WjlxEnum(){} + + WjlxEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public static WjlxEnum toEnum(String type) { + if(StringUtils.isEmpty(type)){ + return null; + } + for(WjlxEnum item : WjlxEnum.values()) { + if(item.getType().equals(type)) { + return item; + } + } + return null; + } +} + diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml index 4b4bd828..1adcfa57 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml @@ -332,17 +332,16 @@ ffmpeg: weipu: userId: 765996 userKey: 330ed91f6c7e4600a454a6a5216723bf - -#SFTP -#sftp: -# hostname: 210.47.29.18 -# port: 22 -# uername: nenujwc18 -# password: hFvxJG%yRNZQ -# timeout: 1000 -# uploadpath: / #问卷星 wjx: appid: 1321039 appkey: 55328ebd11964fc8b40c10011bcb425d - url: https://www.wjx.cn/openapi/default.aspx \ No newline at end of file + url: https://www.wjx.cn/openapi/default.aspx +#SFTP +sftp: + hostname: 192.168.2.200 + port: 22 + username: sftp + password: sftp + timeout: 1000 + uploadpath: /kczx \ No newline at end of file diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml index 9a401445..1bc6262f 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml @@ -133,15 +133,15 @@ spring: master: url: jdbc:mysql://127.0.0.1:3306/course_information_center_jeecg_db?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai username: root +# password: root password: ABCabc@123 - # password: root driver-class-name: com.mysql.cj.jdbc.Driver # 多数据源配置 - multi-oracle: - url: jdbc:oracle:thin:@202.198.129.24:1521:orcl - username: C##XSKC - password: mAPP2t2ABAfx7 - driver-class-name: oracle.jdbc.OracleDriver +# multi-oracle: +# url: jdbc:oracle:thin:@202.198.129.24:1521:orcl +# username: C##XSKC +# password: mAPP2t2ABAfx7 +# driver-class-name: oracle.jdbc.OracleDriver #redis 配置 redis: database: 0 @@ -343,4 +343,12 @@ weipu: wjx: appid: 1321039 appkey: 55328ebd11964fc8b40c10011bcb425d - url: https://www.wjx.cn/openapi/default.aspx \ No newline at end of file + url: https://www.wjx.cn/openapi/default.aspx +#SFTP +sftp: + hostname: 192.168.2.200 + port: 22 + username: sftp + password: sftp + timeout: 1000 + uploadpath: /kczx \ No newline at end of file