From 082ddc5c0d0b14ae12f366c26ff26ea97441b8dc Mon Sep 17 00:00:00 2001 From: Leo Date: Mon, 29 Apr 2024 17:52:20 +0800 Subject: [PATCH] =?UTF-8?q?=E7=88=AC=E8=99=AB=E5=86=99=E5=88=B0=E8=AE=BA?= =?UTF-8?q?=E5=9D=9B=E7=BD=91=E7=AB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 39 + .../cn/van333/wxsend/WxSendApplication.java | 2 + .../business/model/FlarumDiscussion.java | 39 + .../wxsend/business/model/FlarumPost.java | 28 + .../cn/van333/wxsend/business/model/Msg.java | 21 + .../wxsend/business/model/respoenseModel.java | 9 + .../wxsend/business/service/PCService.java | 96 + .../java/cn/van333/wxsend/util/QCUtil.java | 1561 +++++++++++++++++ src/main/resources/application.yml | 12 +- src/test/java/cn/van333/wxsend/Test001.java | 24 + 10 files changed, 1825 insertions(+), 6 deletions(-) create mode 100644 src/main/java/cn/van333/wxsend/business/model/FlarumDiscussion.java create mode 100644 src/main/java/cn/van333/wxsend/business/model/FlarumPost.java create mode 100644 src/main/java/cn/van333/wxsend/business/model/Msg.java create mode 100644 src/main/java/cn/van333/wxsend/business/model/respoenseModel.java create mode 100644 src/main/java/cn/van333/wxsend/business/service/PCService.java create mode 100644 src/main/java/cn/van333/wxsend/util/QCUtil.java create mode 100644 src/test/java/cn/van333/wxsend/Test001.java diff --git a/pom.xml b/pom.xml index 532a0c7..97331e5 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,25 @@ UserAgentUtils 1.21 + + mysql + mysql-connector-java + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.0 + + + com.squareup.okhttp3 + okhttp + 3.6.0 + + + org.projectlombok + lombok + provided + @@ -120,6 +139,26 @@ + + org.jetbrains.kotlin + kotlin-maven-plugin + 1.6.10 + + + compile + process-sources + + compile + + + + src/main/java + target/generated-sources/annotations + + + + + diff --git a/src/main/java/cn/van333/wxsend/WxSendApplication.java b/src/main/java/cn/van333/wxsend/WxSendApplication.java index 80c7db1..cd346f4 100644 --- a/src/main/java/cn/van333/wxsend/WxSendApplication.java +++ b/src/main/java/cn/van333/wxsend/WxSendApplication.java @@ -1,11 +1,13 @@ package cn.van333.wxsend; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @SpringBootApplication @EnableWebMvc +@MapperScan("cn.van333.wxsend.business.mapper") public class WxSendApplication { public static void main(String[] args) { diff --git a/src/main/java/cn/van333/wxsend/business/model/FlarumDiscussion.java b/src/main/java/cn/van333/wxsend/business/model/FlarumDiscussion.java new file mode 100644 index 0000000..e9153ce --- /dev/null +++ b/src/main/java/cn/van333/wxsend/business/model/FlarumDiscussion.java @@ -0,0 +1,39 @@ +package cn.van333.wxsend.business.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.annotation.Resource; +import java.util.Date; + +/** + * @author Leo + * @version 1.0 + * @create 2024/4/29 下午3:05 + * @description: + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Resource +public class FlarumDiscussion { + + private Integer id; + private String title; + private int commentCount; + private int participantCount; + private int postNumberIndex; + private Date createdAt; + private Integer userId; + private Integer firstPostId; + private Date lastPostedAt; + private Integer lastPostedUserId; + private Integer lastPostId; + private Integer lastPostNumber; + private Date hiddenAt; + private Integer hiddenUserId; + private String slug; + private boolean isPrivate; + +} diff --git a/src/main/java/cn/van333/wxsend/business/model/FlarumPost.java b/src/main/java/cn/van333/wxsend/business/model/FlarumPost.java new file mode 100644 index 0000000..17dc51d --- /dev/null +++ b/src/main/java/cn/van333/wxsend/business/model/FlarumPost.java @@ -0,0 +1,28 @@ +package cn.van333.wxsend.business.model; + +import lombok.Data; + +import java.util.Date; + +/** + * @author Leo + * @version 1.0 + * @create 2024/4/29 下午3:08 + * @description: + */ +@Data +public class FlarumPost { + private int id; + private int discussionId; + private Integer number; + private Date createdAt; + private Integer userId; + private String type; + private String content; + private Date editedAt; + private Integer editedUserId; + private Date hiddenAt; + private Integer hiddenUserId; + private String ipAddress; + private boolean isPrivate; +} diff --git a/src/main/java/cn/van333/wxsend/business/model/Msg.java b/src/main/java/cn/van333/wxsend/business/model/Msg.java new file mode 100644 index 0000000..47cacef --- /dev/null +++ b/src/main/java/cn/van333/wxsend/business/model/Msg.java @@ -0,0 +1,21 @@ +package cn.van333.wxsend.business.model; + +import lombok.Data; + +@Data +public class Msg { + private String id; + private String type; + private String tid; + private String hot; + private String title; + private String picname; + private String content; + private String count; + private String dizhi; + private String price; + private String addtime; + private String status; + private String hackpID; + private Object buygoods; +} diff --git a/src/main/java/cn/van333/wxsend/business/model/respoenseModel.java b/src/main/java/cn/van333/wxsend/business/model/respoenseModel.java new file mode 100644 index 0000000..64575db --- /dev/null +++ b/src/main/java/cn/van333/wxsend/business/model/respoenseModel.java @@ -0,0 +1,9 @@ +package cn.van333.wxsend.business.model; + +import lombok.Data; + +@Data +public class respoenseModel { + private String code; + private Msg msg; +} diff --git a/src/main/java/cn/van333/wxsend/business/service/PCService.java b/src/main/java/cn/van333/wxsend/business/service/PCService.java new file mode 100644 index 0000000..053b3c0 --- /dev/null +++ b/src/main/java/cn/van333/wxsend/business/service/PCService.java @@ -0,0 +1,96 @@ +package cn.van333.wxsend.business.service; + +import cn.van333.wxsend.business.model.Msg; +import cn.van333.wxsend.business.model.respoenseModel; +import cn.van333.wxsend.util.QCUtil; +import com.alibaba.fastjson2.JSON; +import okhttp3.*; +import org.springframework.stereotype.Service; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; + +import static java.lang.Thread.sleep; + +/** + * @author Leo + * @version 1.0 + * @create 2024/4/29 下午5:12 + * @description: + */ +@Service +public class PCService { + public static String content = ""; + + public void getData() throws InterruptedException { + + // 6988 + for (int i = 7200; i > 7000; i--) { + System.out.println("第 " + i + "次执行"); + try { + MediaType mediaType = MediaType.parse("text/plain"); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("tid", String.valueOf(i)).build(); + Request request = new Request.Builder().url("https://tm.wx.hackp.net/App/zm/getlist").method("POST", body).addHeader("User-Agent", "Apifox/1.0.0 ").build(); + Response response = client.newCall(request).execute(); + if (response.body() != null) { + String result = response.body().string(); + System.out.println(result); + respoenseModel respoenseModel = JSON.parseObject(result, respoenseModel.class); + Msg msg = respoenseModel.getMsg(); + if (QCUtil.isNotAnyEmpty(msg.getTitle(), msg.getContent(), msg.getDizhi())) { + //content = content + appendHtml(msg.getTitle(), msg.getContent(), msg.getDizhi(), i); + insertToDb(msg.getTitle(), msg.getContent(), msg.getDizhi()); + //youshuju++; + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + sleep(100); + } + + //// 有50条数据再写入文件 + //if (youshuju % 100 == 0 && youshuju != 0) { + // //System.out.println(youshuju); + // j++; + // //System.out.println(content); + // String fileName = "爬取的第" + j + "页 ,最后的为" + i + "条"; + // long l = System.currentTimeMillis() - start; + // System.out.println("用时:" + l + "ms," + l / 1000 + "s" + "," + l / 60000 + "min"); + // createHtml(fileName, content); + // //sleep(200); + // content = ""; + // youshuju = 0; + //} + } + } + + public String insertToDb(String title, String content, String downloadUrl) { + content = content.replace("\\r\\n", ""); + content = content.replace("<\\/span>", ""); + + return null; + + + } + + public static String appendHtml(String title, String content, String downloadUrl, Integer i) { + content = content.replace("\\r\\n", ""); + content = content.replace("<\\/span>", ""); + content = "\n" + "

第" + i + " 条,标题:" + title + "

\n" + "
" + content + "\n" + "

下载链接:" + downloadUrl + "

\n" + "
"; + return content; + } + + public static void createHtml(String fileName, String content) { + String finallyFileName = "D:\\pacong\\xiaochengxu2\\" + fileName + ".html"; + //System.out.println("finallyFileName ******** " + finallyFileName); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(finallyFileName))) { + writer.write(content); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/cn/van333/wxsend/util/QCUtil.java b/src/main/java/cn/van333/wxsend/util/QCUtil.java new file mode 100644 index 0000000..3635eb5 --- /dev/null +++ b/src/main/java/cn/van333/wxsend/util/QCUtil.java @@ -0,0 +1,1561 @@ +package cn.van333.wxsend.util; + + +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.engine.velocity.VelocityEngine; +import org.apache.ibatis.jdbc.SQL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.util.HtmlUtils; + +import javax.activation.DataSource; +import javax.activation.FileDataSource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.math.BigDecimal; +import java.util.*; +import java.util.Map.Entry; + +/** + * 最基础的工具类 + */ +public class QCUtil { + + private static final Logger log = LoggerFactory.getLogger(QCUtil.class); + + /** + * byte数组倒序 + * + * @param bytes + * @return + */ + public static final byte[] byteArrayDesc(byte[] bytes) { + if (QCUtil.isEmpty(bytes)) { + return new byte[0]; + } + int len = bytes.length; + byte[] tmp = new byte[len]; + for (int i = len - 1; i >= 0; i--) { + tmp[len - i - 1] = bytes[i]; + } + return tmp; + + } + + /** + * 打印程序耗时 + * + * @param msg + */ + public static final void consume(long start, long end, String msg) { + System.err.println(String.format("%s consume times: %s=%s-%s", msg, (end - start), end, start)); + } + + /** + * 将非法且不可见的XML字符转为空格(空格的的ascii码是32) + * + * @param bts + * byte[] + * @return 转换后的 byte[] + */ + public static final byte[] convertInvalidInvisibleToSpace(byte[] bytes) { + if (QCUtil.isEmpty(bytes)) { + return new byte[0]; + } + byte[] tmp = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + if (b >= 0 && b <= 8 || b >= 14 && b <= 31 || b == 11 || b == 12 || b == 127) { + tmp[i] = 32; + } else { + tmp[i] = bytes[i]; + } + } + return tmp; + } + + /** + * 将非法且不可见的XML字符转为空格 + * + */ + public static final String convertInvalidInvisibleToSpace(String str) { + if (QCUtil.isEmpty(str)) { + return ""; + } + return new String(QCUtil.convertInvalidInvisibleToSpace(str.getBytes())); + } + + /** + * 将非法且不可见的XML字符转为空格 + * + * @param bts + * byte[] + * @return 转换后的 byte[] + */ + public static final byte[] convertInvalidInvisibleXml(byte[] bytes) { + if (QCUtil.isEmpty(bytes)) { + return new byte[0]; + } + byte[] tmp = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + if (b >= 0 && b <= 8)// \\x00-\\x08 + { + tmp[i] = 32; + } else if (b >= 14 && b <= 31)// \\x0e-\\x1f + { + tmp[i] = 32; + } else if (b == 11 || b == 12 || b == 127)// \\x0b-\\x0c and \\x7f + { + tmp[i] = 32; + } else { + tmp[i] = bytes[i]; + } + } + return tmp; + } + + /** + * 删除临时文件. + * + * @param dir + */ + public static final void deleteTempFile(String dir) { + File tf = new File(dir); + String[] childs = tf.list(); + for (String child : childs) { + new File(dir + File.separator + child).delete(); + } + } + + /** + * 读取文件路径,返回DataSource容器 + * + * @param attFiles + * @return + */ + public static final List fileDirsToDatasource(List attFiles) { + DataSource dc = null; + List dcs = new ArrayList(); + if (isNotEmpty(attFiles)) { + for (File file : attFiles) { + dc = new FileDataSource(file); + dcs.add(dc); + } + } + return dcs; + } + + /** + * 得到数组中非空元素的数量 + * + * @param arr + * @return + */ + public static final int getArraySizeWithoutEmptyElement(String[] arr) { + if (QCUtil.isEmpty(arr)) { + return 0; + } + int count = 0; + for (String s : arr) { + if (!QCUtil.isEmpty(s)) { + count++; + } + } + return count; + } + + /** + * 指定cookie的key,获取对应的value。 + * + * @param request + * @param key + * cookie key + * @return cookie value + */ + public static final String getCookieValue(HttpServletRequest request, String key) { + if (QCUtil.isAnyEmpty(key, request)) { + return ""; + } + Cookie[] cookies = request.getCookies(); + if (QCUtil.isNotEmpty(cookies)) { + for (Cookie c : cookies) { + if (key.equals(c.getName())) { + if (QCUtil.isNotEmpty(c.getValue())) { + return c.getValue(); + } + break; + } + } + } + return ""; + } + + /** + * + * @param response + * @param key + * 键 + * @param value + * 值 + * @param maxAge + * 存活时间,默认-1 + * @param path + * 有效域,默认/ + */ + public static void setCookie(HttpServletResponse response, String key, String value, Integer maxAge, String path) { + Cookie cookie = new Cookie(key, value); + + // 设置浏览器的cookie保留时间,单位秒。负值标识浏览器关闭即删除cookie,0表示马上删除。 + // 这里设置成一年,如果想控制登录超时,可以用ADMIN_SESSION_TIMEOUT在t_parameter中设置redis的超时时间,统一后台控制。 + if (QCUtil.isEmpty(maxAge)) { + cookie.setMaxAge(-1); + } else { + cookie.setMaxAge(maxAge); + } + + if (QCUtil.isEmpty(path)) { + cookie.setPath("/"); + } else { + cookie.setPath(path); + } + + // 这两个参数是因为应付漏洞扫描加入的。 + // 不允许前端javaScript显性读取 + // cookie.setHttpOnly(true); + // 只允许https请求时提交给服务器,也就是说http(测试环境)服务器端读取不到cookie。 + // cookie.setSecure(true); + + response.addCookie(cookie); + } + + /** + * 将InputStream流写入一个File对象中返回 + * + * @param inputStream + * @return + * @throws IOException + */ + //public static final File inputStreamToFile(InputStream in, String name) throws IOException { + // if (QCUtil.isEmpty(in)) { + // return null; + // } + // if (QCUtil.isEmpty(name)) { + // name = QCUtil.times() + ""; + // } + // File f = new File(name); + // FileUtils.copyInputStreamToFile(in, f); + // return f; + //} + + /** + * 判断送入的字符串是否全部为中文 + * + * @param name + * 需判断的字符串 + * @return 判断结果返回 true为中文 false为非中文 + */ + public static final boolean isChinese(String str) { + if (QCUtil.isEmpty(str)) { + return false; + } + str = str.replaceAll("[\u4e00-\u9FFF]", ""); + if (QCUtil.isEmpty(str)) { + return true; + } + return false; + } + + /** + * 判断一个对象是否为空或者长度为0时返回true,否则返回false String:null或length=0返回true + * List,Set,Map:null或size=0返回true 其他null返回true + * + * @param o + * @return + */ + @SuppressWarnings("rawtypes") + public static final boolean isEmpty(Object o) { + if (null == o) { + return true; + } + if (o instanceof String) { + return (0 == ((String) o).trim().length()); + } + if (o instanceof List) { + return (0 == ((List) o).size()); + } + if (o instanceof Set) { + return (0 == ((Set) o).size()); + } + if (o instanceof Map) { + return (0 == ((Map) o).size()); + } + if (o instanceof Object[]) { + return (0 == ((Object[]) o).length); + } + return false; + } + + /** + * 判断一个对象不为null,并且长度不为0时返回true,否则返回false 规则参考QCUtil.isEmpty() + * + * @see #isEmpty(Object o) + * @param o + * @return + */ + public static final boolean isNotEmpty(Object o) { + return !isEmpty(o); + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final String getNotNull(String t) { + return isEmpty(t) ? new String("") : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Character getNotNull(Character t) { + return isEmpty(t) ? new Character('\0') : t; + } + + /** + * 获取非空对象 + * + * @param t + * @return + */ + public static final Byte getNotNull(Byte t) { + byte b = 0; + return isEmpty(t) ? b : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Short getNotNull(Short t) { + short s = 0; + return isEmpty(t) ? s : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Integer getNotNull(Integer t) { + return isEmpty(t) ? new Integer(0) : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Long getNotNull(Long t) { + return isEmpty(t) ? new Long(0) : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Float getNotNull(Float t) { + return isEmpty(t) ? new Float(0) : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static final Double getNotNull(Double t) { + return isEmpty(t) ? new Double(0) : t; + } + + /** + * 获取非空对象,若空返回对象类型默认值 + * + * @param t + * @return + */ + public static BigDecimal getNotNull(BigDecimal t) { + return isEmpty(t) ? new BigDecimal(0) : t; + } + // + ///** + // * 倒序行读文件内容(确保文件为UTF-8编码,才能显示中文)。 + // * + // * @param filename + // * 文件完整路径(确保文件必须存在并且是文件而不是路径) + // * @param seekIndex + // * 从该字节位置往前读取,初始为0,输入null时从最后一个字节往前读取 + // * @param howManyLineToRead + // * 读取行数 + // * @param isNewline + // * 返回的内容是否换行 + // * @return 返回指针位置(下标0,用于下次继续读取)_读取内容(下标1) + // * @throws BusinessException + // */ + //public static final List readLineDesc(String filename, Long seekIndex, int howManyLineToRead, + // Boolean isNewline) throws BusinessException { + // + // if (QCUtil.isEmpty(filename)) { + // return null; + // } + // + // if (seekIndex != null && seekIndex <= 0 || howManyLineToRead <= 0) { + // return null; + // } + // + // RandomAccessFile rf = null; + // StringBuffer result = new StringBuffer(""); + // List temResult = new ArrayList(); + // int lineCount = 0; + // List seekIndex_resultStr = null; + // String r = ""; + // if (isNewline) { + // r = "\n"; + // } + // + // try { + // rf = new RandomAccessFile(filename, "r"); + // // 计算文件指针位置,默认是文件字节数-1,即从最后一个字节开始 + // long nextend = 0L; + // if (seekIndex == null) { + // // 得到文件最后一个字节的指针,指向该字节下方 + // nextend = rf.length() - 1; + // } else { + // nextend = seekIndex; + // } + // + // int c = -1; + // ByteArrayOutputStream out = new ByteArrayOutputStream(); + // while (nextend >= 0 && howManyLineToRead > lineCount) { + // rf.seek(nextend); + // // 读取指针指向的字节 + // c = rf.read(); + // // 如果该字节的ascii码与换行符的ascii码相等 + // if ((c == '\n') && nextend != 0) { + // lineCount++; + // String line = QCUtil.trim(new String(byteArrayDesc(out.toByteArray()))); + // if (QCUtil.isNotEmpty(line)) { + // temResult.add(line + r); + // } + // out = new ByteArrayOutputStream(); + // } else { + // out.write(c); + // } + // if (nextend == 0) {// 当文件指针退至文件开始处,输出第一行 + // String line = QCUtil.trim(new String(byteArrayDesc(out.toByteArray()))); + // if (QCUtil.isNotEmpty(line)) { + // temResult.add(line + r); + // } + // log.info("Have seek to the first byte."); + // break; + // } + // nextend--; + // } + // seekIndex_resultStr = new ArrayList(); + // seekIndex_resultStr.add(nextend + ""); + // for (int i = temResult.size() - 1; i >= 0; i--) { + // if (i == 0) { + // result.append(temResult.get(i).trim()); + // } else { + // result.append(temResult.get(i)); + // } + // } + // seekIndex_resultStr.add(result.toString()); + // return seekIndex_resultStr; + // } catch (FileNotFoundException e) { + // throw new BusinessException("Can't locate file " + filename + ",", e); + // } catch (IOException e) { + // throw new BusinessException("Read data from file " + filename + " failed,", e); + // } finally { + // try { + // if (rf != null) { + // rf.close(); + // } + // } catch (IOException e) { + // throw new BusinessException("Close file " + filename + " failed,", e); + // } + // } + //} + + /** + * 获取当前时间毫秒数 + * + * @return + */ + public static final long times() { + return System.currentTimeMillis(); + } + + /** + * 强化trim() + * + * @param val + * @return + */ + public static final String trim(String val) { + if (isEmpty(val)) { + return ""; + } else { + return val.trim(); + } + } + + /** + * 将File f对象写到服务器本地 + * + * @param f + * @param dir + * 服务器本地路径,可以是一个目录路径,也可以是一个文件路径 如果是目录路径,此目录若不存在,程序自动创建 + * 如果是文件路径,程序会自动创建此文件,包括不存在的目录,并将File + * f写入此文件中,注意,文件路径必须有文件后缀,否则被认为是目录路径 如果是目录路径,文件名是f.getName(); + * 如果是文件路径,文件名为路径中指定的文件名; + * 路径如果不存在,创建的时候,如果此路径为绝对路径,那么创建相应的绝对路径,如果是相对路径,那么相对于用户的user目录,参考File + * getAbsolutePath()方法 + * @throws IOException + * @throws BusinessException + */ + //public static final void writeFileToLocalDir(File f, String dir) throws IOException, BusinessException { + // if (QCUtil.isEmpty(f)) { + // throw new BusinessException("QCUtil.writeFileToLocalDir()'s File f is null."); + // } + // if (QCUtil.isEmpty(dir)) { + // throw new BusinessException("QCUtil.writeFileToLocalDir()'s File dir is empty."); + // } + // File dirf = new File(dir); + // if (!dirf.exists()) { + // String[] dirArr = dirf.getAbsolutePath().split("\\" + File.separator); + // String lastDir = dirArr[dirArr.length - 1]; + // if (!lastDir.contains(".")) { + // dirf = new File(dirf.getAbsolutePath() + File.separator + f.getName()); + // } + // } else if (dirf.exists() && dirf.isDirectory()) { + // dirf = new File(dirf.getAbsolutePath() + File.separator + f.getName()); + // } + // FileUtils.writeByteArrayToFile(dirf, FileUtils.readFileToByteArray(f)); + //} + + /** + * 将字符串的首字母变小写 + * + * @param s + * @return + */ + public static final String lowerCaseFirstChar(String s) { + if (QCUtil.isEmpty(s)) { + return ""; + } + return s.substring(0, 1).toString().toLowerCase() + s.substring(1).toString(); + } + + /** + * 将字符串的首字母变大写 + * + * @param s + * @return + */ + public static final String upperCaseFirstChar(String s) { + if (QCUtil.isEmpty(s)) { + return ""; + } + return s.substring(0, 1).toString().toUpperCase() + s.substring(1).toString(); + } + + /** + * 只要其中一个对象是empty,返回true,否则返回false + * + * @param o + * @return + */ + public static final boolean isAnyEmpty(Object... o) { + for (int i = 0; i < o.length; i++) { + Object obj = o[i]; + if (QCUtil.isEmpty(obj)) { + return true; + } + } + return false; + } + + /** + * 所有对象都不为empty,返回true,否则返回false + * + * @param o + * @return + */ + public static final boolean isNotAnyEmpty(Object... o) { + return !isAnyEmpty(o); + } + + /** + * 获取UUID,纳秒+uuid,用纳秒开头是为了让记录可以使用这个uuid进行排序 + */ + public static final String getUUID() { + return System.nanoTime() + UUID.randomUUID().toString().replaceAll("\\-", ""); + } + + /** + * 使用不可见字符串Constant.unsee0x01将字符串隔开,重新组成一串字符串 + * + * @param strs + * @return + */ + public static final String joinStringWithUnseeChar(Collection strs) { + return joinStringWithSplitor(strs, String.valueOf((char) 0x01)); + } + + /** + * 用任何分隔符将字符串容器中的字符串组成一串字符串。 + * + * @param strs + * @param splitor + * @return + */ + public static final String joinStringWithSplitor(Collection strs, String splitor) { + if (QCUtil.isEmpty(strs)) { + return ""; + } + StringBuffer res = new StringBuffer(""); + for (String s : strs) { + res.append(s + splitor); + } + if (QCUtil.isNotEmpty(res.toString())) { + return res.toString().substring(0, res.toString().length() - 1); + } + return res.toString(); + } + + /** + * 使用不可见字符串Constant.unsee0x01将字符串隔开,重新组成一串字符串 + * + * @param strs + * @return + */ + public static final String joinStringWithUnseeChar(String[] strs) { + return joinStringWithSplitor(strs, String.valueOf((char) 0x01)); + } + + /** + * 用任何分隔符将字符串数组中的字符串组成一串字符串。 + * + * @param strs + * @param splitor + * @return + */ + public static final String joinStringWithSplitor(String[] strs, String splitor) { + if (QCUtil.isEmpty(strs)) { + return ""; + } + StringBuffer res = new StringBuffer(""); + for (String s : strs) { + res.append(s + splitor); + } + if (QCUtil.isNotEmpty(res.toString())) { + return res.toString().substring(0, res.toString().length() - 1); + } + return res.toString(); + } + + /** + * 去除字符串数组中的空串 + * + * @param split + * @return + */ + public static final String[] removeEmptyElements(String[] split) { + List l = new ArrayList(); + for (String s : split) { + if (QCUtil.isNotEmpty(s)) { + l.add(s); + } + } + String[] res = new String[l.size()]; + return l.toArray(res); + } + + /** + * 去除队列中为null的元素 + * + * @param list + * @return + */ + @SuppressWarnings("unchecked") + public static List removeNull(List list) { + if (QCUtil.isEmpty(list)) { + return (List) list; + } + list.removeAll(Collections.singleton(null)); + List res = (List) list; + return res; + } + + /** + * 去除队列中为null的元素 + * + * @param list + * @return + */ + @SuppressWarnings("unchecked") + public static List removeEmpty(List list) { + if (QCUtil.isEmpty(list)) { + return (List) list; + } + List newList = new ArrayList(); + for (T t : list) { + if (QCUtil.isNotEmpty(t)) { + newList.add(t); + } + } + return newList; + } + + /** + * 获取文件后缀 + * + * @param fileName + * 文件名,File对象调用getName(); + * @return + */ + public static final String getSuffix(String fileName) { + if (QCUtil.isEmpty(fileName)) { + return ""; + } + fileName = getRealFileName(fileName); + return fileName.substring(fileName.lastIndexOf(".")); + } + + /** + * 获取文件后缀(连后缀的最开始的“.”都不要了) + * + * @param fileName + * 文件名,File对象调用getName(); + * @return + */ + public static final String getSuffixWithoutDot(String fileName) { + if (QCUtil.isEmpty(fileName)) { + return ""; + } + fileName = getRealFileName(fileName); + return fileName.substring(fileName.lastIndexOf(".") + 1); + } + + /** + * 获取除掉后缀的文件名 + * + * @param fileName + * 文件名,File对象调用getName(); + * @return + */ + public static final String getFileNameIgnoreSuffix(String fileName) { + if (QCUtil.isEmpty(fileName)) { + return ""; + } + fileName = getRealFileName(fileName); + return fileName.substring(0, fileName.lastIndexOf(".")); + } + + /** + * 获取文件名,有些文件名是一串路径,有些是正确的文件名,这个方法做兼容。 + * 比如IE上传到后台接收到的MultipartFile的getOriginalFilename就是一串路径。 + * + * @return 最终的文件名 + */ + public static final String getRealFileName(String fileName) { + if (fileName.indexOf("/") != -1) { + fileName = fileName.substring(fileName.lastIndexOf("/") + 1); + } + if (fileName.indexOf("\\") != -1) { + fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); + } + return fileName; + } + + /** + * 删除第一个字符以及最后一个字符 + * + * @return + */ + public static final String removeFirstLastChar(String s) { + if (QCUtil.isEmpty(s)) { + return ""; + } + return s.substring(1, s.length() - 1); + } + + /** + * spring mvc专用下载 + * + * @param response + * @param request + * @param name + * 客户端附件下载的名字 + * @param b + * 下载数据 + * @throws IOException + * @throws BusinessException + */ + //public static final ResponseEntity write(String name, byte[] b) throws IOException, BusinessException { + // try { + // HttpHeaders headers = new HttpHeaders(); + // headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + // String downloadFileName = new String(name.getBytes(Constant.ENCODING), "iso-8859-1");// 设置编码 + // headers.setContentDispositionFormData("attachment", downloadFileName); + // return new ResponseEntity(b, headers, HttpStatus.CREATED); + // } catch (Exception e) { + // throw new BusinessException(e); + // } + //} + + /** + * 将Map的value中的String[]变成以Constant.unsee0x01隔开的字符串。 原因是Controller不能传递Map的形式到WS层方法, 因为不想做那么复杂,当前只支持用j_m_m_xxx传递Map + * 的变量,所以当分页的时候,需要传递的searchParams就是Map + * 形式的,所以需要将Map里面的String[]变成字符串,从而整个变量就能使用j_map_xxx来传递 + * + * @param j_map_searchParams + * @return + */ + public static Map convertMapArrayToStirng(Map j_map_searchParams) { + Map res = new HashMap(); + if (QCUtil.isEmpty(j_map_searchParams)) { + return res; + } + for (Entry en : j_map_searchParams.entrySet()) { + if (QCUtil.isNotEmpty(en.getValue())) { + if (en.getValue() instanceof String[]) { + res.put(en.getKey(), QCUtil.joinStringWithUnseeChar((String[]) en.getValue())); + } else { + res.put(en.getKey(), (String) en.getValue()); + } + } + } + return res; + } + + /** + * 格式化文件的大小,如果小于1024kb,直接显示kb,如果大于1024kb,换算成mb进行显示,以此类推。 + * + * @param size + * 传一个b为单位的数字 + * @return + */ + public static String formatFileSize(long size) { + String fileSize = ""; + double kbNum = new BigDecimal(size).divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP).doubleValue(); + if (1024 < kbNum) { + double mbNum = new BigDecimal(kbNum).divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP) + .doubleValue(); + if (1024 < mbNum) { + double gbNum = new BigDecimal(mbNum).divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP) + .doubleValue(); + fileSize = gbNum + "GB"; + } else { + fileSize = mbNum + "MB"; + } + } else { + fileSize = kbNum + "KB"; + } + return fileSize; + } + + /** + * 判断字符串中字母的个数 + */ + public static int getAlphaCharLength(String str) { + int count = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) * 1 >= 65 && str.charAt(i) * 1 <= 90 + || str.charAt(i) * 1 >= 97 && str.charAt(i) * 1 <= 122) { + count++; + } + } + return count; + } + + /** + * 判断字符串中数字个数 + */ + public static int getNumLength(String str) { + int count = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) * 1 >= 48 && str.charAt(i) * 1 <= 57) { + count++; + } + } + return count; + }; + + /** + * 判断字符串中特殊字符个数。 + */ + public static int getSpecialCharLength(String str) { + int count = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) * 1 < 48 || str.charAt(i) * 1 > 57 && str.charAt(i) * 1 < 65 + || str.charAt(i) * 1 > 90 && str.charAt(i) * 1 < 97 || str.charAt(i) * 1 > 122) { + count++; + } + } + return count; + }; + + /** + * 判断字符串是否包含大小写。 + */ + public static boolean containBigAndSmall(String str) { + boolean big = false; + boolean small = false; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) * 1 >= 65 && str.charAt(i) * 1 <= 90) { + big = true; + break; + } + } + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) * 1 >= 97 && str.charAt(i) * 1 <= 122) { + small = true; + break; + } + } + if (big && small) { + return true; + } + return false; + } + + /** + * 简单混淆字符串中字符。 当前是0位和1位调换,最后两位字符调换。 + * + * @param str + * @return + */ + public static String confusionStr(String str) { + char[] c = str.toCharArray(); + char a = c[1]; + c[1] = c[0]; + c[0] = a; + a = c[c.length - 1]; + c[c.length - 1] = c[c.length - 2]; + c[c.length - 2] = a; + return new String(c); + } + + /** + * 获取某个范围的随机数。 如获取0-5的随机数,minRang:0,maxRang:5, 如获取5-50的随机数,minRang:5,maxRang:50 + * + * @param minRang + * @param maxRang + * @return + */ + public static int getRandomIntInRang(int minRang, int maxRang) { + Random rand = new Random(); + int randNum = rand.nextInt(maxRang + 1) + minRang; + return randNum; + } + + /** + * 随机获取a-z,0-9中的n个字符作为验证码。 + * + * @return + */ + public static String getVerifyCodeChars(int n) { + char[] c = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }; + int randNum = -1; + char[] resc = new char[n]; + for (int i = 0; i < n; i++) { + randNum = getRandomIntInRang(0, 35); + try { + resc[i] = c[randNum]; + } catch (Exception e) { + resc[i] = 'p'; + continue; + } + } + return new String(resc); + } + + /** + * 随机获取0-9中的n个字符作为验证码。一般用作短信验证码时。 + * + * @return + */ + public static String getVerifyCodeCharsOnliNum(int n) { + char[] c = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }; + int randNum = -1; + char[] resc = new char[n]; + for (int i = 0; i < n; i++) { + randNum = getRandomIntInRang(0, 9); + try { + resc[i] = c[randNum]; + } catch (Exception e) { + resc[i] = '8'; + continue; + } + } + return new String(resc); + } + + /** + * 去除空元素后再join + * 和javaScript的数组的join方法作用一样,主要用于将数组的元素用指定的连接字符相连成一行字符串, + * 放在searchParams中的IN参数中进行查询,如["a", "b", 1]→"a,b,1" + * + * @param array + * @param joinStr + * 链接字符串,可以是单个字符,也可以是多个字符的字符串,也可以是空串。 + * @return + */ + public static String joinIgnoreEmpty(List array, String joinStr) { + array = removeEmpty(array); + return join(array, joinStr); + } + + public static void main(String[] args) { + List s = new ArrayList(); + s.add("a"); + s.add("b"); + s.add(""); + s.add("d"); + System.out.println(joinIgnoreEmpty(s, ",")); + } + + /** + * 和javaScript的数组的join方法作用一样,主要用于将数组的元素用指定的连接字符相连成一行字符串, + * 放在searchParams中的IN参数中进行查询,如["a", "b", 1]→"a,b,1" + * + * @param array + * @param joinStr + * 链接字符串,可以是单个字符,也可以是多个字符的字符串,也可以是空串。 + * @return + */ + public static String join(List array, String joinStr) { + if (QCUtil.isEmpty(array)) { + return ""; + } else { + StringBuffer sb = new StringBuffer(""); + for (T o : array) { + String val = ""; + if (QCUtil.isNotEmpty(o)) { + val = o.toString(); + } + sb.append(val + joinStr); + } + if (QCUtil.isNotEmpty(sb.toString())) { + return sb.toString().substring(0, sb.toString().length() - joinStr.length()); + } + } + return ""; + } + + /** + * 将字符串按照正则匹配分割 + * + * */ + public static List cut(String str, String regex) { + List list = new ArrayList(); + if (QCUtil.isEmpty(regex)) { + return list; + } + String[] ss = str.split(regex); + for (String s : ss) { + list.add(s); + } + return list; + } + + /** + * 将字符串按指定分割符切分成多段并转成List + * + * @param string + * @param splitStr + * @return + */ + public static List convertToList(String string, String splitStr) { + List list = new ArrayList(); + if (QCUtil.isEmpty(string)) { + return list; + } + String[] strs = string.split(splitStr); + if (QCUtil.isEmpty(strs)) { + return list; + } + for (String str : strs) { + list.add(str); + } + return list; + } + + /** + * HTML字符转义 + * + * @see 对输入参数中的敏感字符进行过滤替换,防止用户利用JavaScript等方式输入恶意代码 + * @see String input = + * @see HtmlUtils.htmlEscape(input); //from spring.jar + * @see StringEscapeUtils.escapeHtml(input); //from commons-lang.jar + * @see 尽管Spring和Apache都提供了字符转义的方法,但Apache的StringEscapeUtils功能要更强大一些 + * @see StringEscapeUtils提供了对HTML,Java,JavaScript, SQL ,XML等字符的转义和反转义 + * @see 但二者在转义HTML字符时,都不会对单引号和空格进行转义,而本方法则提供了对它们的转义 + * @return String 过滤后的字符串 + */ + public static String htmlEscape(String input) { + if (isEmpty(input)) { + return input; + } + input = input.replaceAll("&", "&"); + input = input.replaceAll("<", "<"); + input = input.replaceAll(">", ">"); + input = input.replaceAll(" ", " "); + input = input.replaceAll("'", "'"); // IE暂不支持单引号的实体名称,而支持单引号的实体编号,故单引号转义成实体编号,其它字符转义成实体名称 + input = input.replaceAll("\"", """); // 双引号也需要转义,所以加一个斜线对其进行转义 + input = input.replaceAll("\n", "
"); // 不能把\n的过滤放在前面,因为还要对<和>过滤,这样就会导致
失效了 + return input; + } + + /** + * Controller端获取searchParams + * + * @param request + * @return + */ + //public static Map getSearchParams(HttpServletRequest request) { + // Map searchParams = WebQCUtil.getParametersStartingWith(request, WebConstant.search); + // return searchParams; + //} + + /** + * Controller端获取searchParams (value not empty) + * + * @param request + * @return + */ + //public static Map getSearchParamsNotEmpty(HttpServletRequest request) { + // Map searchParams = getSearchParams(request); + // Map searchParamsCopy = new HashMap(searchParams); + // Set> entrys = searchParamsCopy.entrySet(); + // for (Entry entry : entrys) { + // if (QCUtil.isEmpty(entry.getValue())) { + // searchParams.remove(entry.getKey()); + // } + // } + // return searchParams; + //} + + /** + * Controller端获取sortParams + * + * @param request + * @return + */ + //public static Map getSortParams(HttpServletRequest request) { + // Map sortParams = WebQCUtil.getParametersStartingWith(request, WebConstant.sort); + // return sortParams; + //} + + /** + * Controller端获取sortParams (value not empty) + * + * @param request + * @return + */ + //public static Map getSortParamsNotEmpty(HttpServletRequest request) { + // Map sortParams = getSortParams(request); + // Map sortParamsCopy = new HashMap(sortParams); + // Set> entrys = sortParamsCopy.entrySet(); + // for (Entry entry : entrys) { + // if (QCUtil.isEmpty(entry.getValue())) { + // sortParams.remove(entry.getKey()); + // } + // } + // return sortParams; + //} + + /** + * java通用下载。如果使用spring mvc框架,请用spring mvc的专用下载。 + * 将数据写到客户端,供客户下载,比如客户端各种文件附件的下载,以及客户端图片的显示都是用这个方法输出到客户端。 + * + * @see #write(String, byte[]) + * + * @param response + * @param request + * @param name + * 客户端附件下载的名字 + * @param b + * 下载数据 + * @throws IOException + * @throws BusinessException + */ + //public static final void write(HttpServletRequest request, HttpServletResponse response, String name, byte[] b) + // throws IOException, BusinessException { + // OutputStream out = null; + // try { + // out = response.getOutputStream(); + // response.setContentType("APPLICATION/OCTET-STREAM"); + // response.setCharacterEncoding(Constant.ENCODING); + // response.setHeader("Pragma", "public"); + // response.setHeader("Cache-Control", "max-age=0"); + // String agent = (String) request.getHeader("USER-AGENT"); + // if (agent != null && agent.indexOf("MSIE") == -1) { + // // FF + // String enableFileName = "=?" + Constant.ENCODING + "?B?" + // + (new String(Base64.encodeBase64(name.getBytes(Constant.ENCODING)))) + "?="; + // response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName); + // } else { + // // IE + // String enableFileName = new String(name.getBytes("GBK"), "ISO-8859-1"); + // response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName); + // } + // out.write(b); + // } catch (Exception e) { + // throw new BusinessException(e); + // } finally { + // IOQCUtil.flush(out); + // IOQCUtil.close(out); + // } + //} + + /** + * 从字节数组中的start下标开始(包括start)下标,获取len个元素,返回一个新的数组。 + * + * @param b + * @param start + * @param len + * @return + */ + public static byte[] getTargetBytes(byte[] b, int start, int len) { + byte[] newB = new byte[len]; + int i = 0; + if (QCUtil.isNotEmpty(b)) { + while (true) { + if (i == len) { + break; + } + newB[i] = b[start]; + i++; + start++; + } + } + return newB; + } + + /** + * 辅助方法 数组元素 + 前缀 + 分隔符 然后拼接起来 如 参数分别是 [AA,BB,CC], TDD, -- 返回结果是 + * TDDAA--TDDBB--TDDCC + * + * @param deviceIds + * @param prefix + * @return + */ + public static String join(List array, String prefix, String joinStr) { + if (array == null || prefix == null || joinStr == null) { + return ""; + } + StringBuilder buff = new StringBuilder(); + for (int i = 0; i < array.size(); i++) { + if (i == array.size() - 1) { + buff.append(prefix + array.get(i)); + } else { + buff.append(prefix + array.get(i) + joinStr); + } + } + return buff.toString(); + } + + /** + * 拼接sql中的in参数 + * @param + * @param array + * @param joinStr + * @return + */ + public static String joinInStr(List array) { + if (QCUtil.isAnyEmpty(array)) { + return ""; + } + StringBuilder buff = new StringBuilder(); + for (int i = 0; i < array.size(); i++) { + if (QCUtil.isNotEmpty(array.get(i))) { + if (i == array.size() - 1) { + buff.append("'" + array.get(i) + "'"); + } else { + buff.append("'" + array.get(i) + "',"); + } + } + } + return buff.toString(); + } + + /** + * 辅助方法 数组元素 + 前缀 然后返回 如 参数分别是 [AA,BB,CC], TDD 返回结果是 [TDDAA,TDDBB,TDDCC] + * + * @param deviceIds + * @param prefix + * @return + */ + @SuppressWarnings("unchecked") + public static List joinPrefix(List array, String prefix) { + if (array == null || prefix == null) { + return new ArrayList<>(); + } + List newArray = new ArrayList(array.size()); + for (T t : array) { + newArray.add((T) (prefix + t)); + } + return newArray; + } + + /** + * 从0度开始为正北方 + *

+ * Title: degrees + *

+ *

+ * Description:根据角度转化成中文风向,16位陆地 + *

+ * + * @param degrees + * @return + * @author dorry + */ + public static String degrees(Double degrees) { + if (348.75 <= degrees && degrees <= 360) { + return "北"; + } else if (0 <= degrees && degrees <= 11.25) { + return "北"; + } else if (11.25 < degrees && degrees <= 33.75) { + return "东北偏北"; + } else if (33.75 < degrees && degrees <= 56.25) { + return "东北"; + } else if (56.25 < degrees && degrees <= 78.75) { + return "东北偏东"; + } else if (78.75 < degrees && degrees <= 101.25) { + return "东"; + } else if (101.25 < degrees && degrees <= 123.75) { + return "东南偏东"; + } else if (123.75 < degrees && degrees <= 146.25) { + return "东南"; + } else if (146.25 < degrees && degrees <= 168.75) { + return "东南偏南"; + } else if (168.75 < degrees && degrees <= 191.25) { + return "南"; + } else if (191.25 < degrees && degrees <= 213.75) { + return "西南偏南"; + } else if (213.75 < degrees && degrees <= 236.25) { + return "西南"; + } else if (236.25 < degrees && degrees <= 258.75) { + return "西南偏西"; + } else if (258.75 < degrees && degrees <= 281.25) { + return "西"; + } else if (281.25 < degrees && degrees <= 303.75) { + return "西北偏西"; + } else if (303.75 < degrees && degrees <= 326.25) { + return "西北"; + } else if (326.25 < degrees && degrees < 348.75) { + return "西北偏北"; + } else { + return "无风"; + } + } + + /** + * velocity模板得到字符串,模板为绝对路径文件 + * + * @param data + * @param templateDir + * @return + */ + //public static final String getStringFromVelocityEngineByAbsuluteDir(Map data, String templateDir) { + // File templateFile = new File(templateDir); + // if (!templateFile.exists()) { + // return ""; + // } + // VelocityEngine ve = new VelocityEngine(); + // Properties p = new Properties(); + // p.put(Velocity.FILE_RESOURCE_LOADER_PATH, templateFile.getParent()); + // ve.init(p); + // Template t = ve.getTemplate(templateFile.getName(), Constant.ENCODING); + // return getStringFromVelocityEngine(data, t, templateFile); + //} + + /** + * velocity模板得到字符串,模板为相对路径文件 + * + * @param data + * @param templateDir + * @return + */ + //public static final String getStringFromVelocityEngineByRelationDir(Map data, String templateDir) { + // File templateFile = new File(templateDir); + // if (!templateFile.exists()) { + // return ""; + // } + // VelocityEngine ve = new VelocityEngine(); + // Template t = ve.getTemplate(templateFile.getPath(), Constant.ENCODING); + // return getStringFromVelocityEngine(data, t, templateFile); + //} + + /** + * velocity模板得到字符串,实现 + * + * @param data + * @param t + * @param templateFile + * @return + */ + //private static final String getStringFromVelocityEngine(Map data, Template t, File templateFile) { + // VelocityContext context = new VelocityContext(); + // if (!QCUtil.isEmpty(data)) { + // for (Entry e : data.entrySet()) { + // context.put(e.getKey(), e.getValue()); + // } + // } + // StringWriter writer = new StringWriter(); + // t.merge(context, writer); + // log.debug(String.format("Velocity string generate for template[%s]:\n%s", templateFile.getAbsolutePath(), + // writer.toString())); + // return writer.toString(); + //} + + /** + * 读取配置文件中的值 + * 前提是确认Application.java中读取配置文件的编码是ISO8859-1 + * @param env + * @param key + * @return + * @throws UnsupportedEncodingException + */ + public static String getProperty(Environment env, String key) throws UnsupportedEncodingException { + return new String(env.getProperty(key).getBytes("ISO8859-1"), "UTF-8"); + } + + /** + * 过滤前端参数中的javaScript脚本和html标签,防止xss攻击 + * @param value + * @return + */ + public static String filterDangerString(String value) { + if (QCUtil.isEmpty(value)) { + return ""; + } + value = value.replaceAll("<", "<"); + value = value.replaceAll(">", ">"); + return value; + } + + /** + * 随机生成密钥 + * + * @return + */ + public static String getAESRandomKey(int length) { + + ArrayList strList = new ArrayList(); + + int begin = 97; + // 生成小写字母,并加入集合 + for (int i = begin; i < begin + 26; i++) { + strList.add((char) i + ""); + } + // 生成大写字母,并加入集合 + begin = 65; + for (int i = begin; i < begin + 26; i++) { + strList.add((char) i + ""); + } + // 将0-9的数字加入集合 + for (int i = 0; i < 10; i++) { + strList.add(i + ""); + } + + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int size = strList.size(); + String randomStr = strList.get(random.nextInt(size)); + sb.append(randomStr); + } + return sb.toString(); + } + + /** + * 将字符串转Integer + * @return + */ + public static Integer getInteger(String val) { + if (QCUtil.isEmpty(val)) { + return 0; + } + + val = val.replaceAll("[^\\-0-9]", ""); + + if (!isNumber(val)) { + return 0; + } + + try { + return Integer.parseInt(val); + } catch (Exception e) { + return 0; + } + } + + /** + * 判断一个字符串是不是数值型字符串,包括正负小数 + * @param content + * @return + */ + public static boolean isNumber(String content) { + if (QCUtil.isEmpty(content)) { + return false; + } + + String pattern = "^[\\+\\-]?[\\d]+(\\.[\\d|E]+)?$"; + return content.matches(pattern); + } + + /** + * 把输入流的内容转化成字符串 + * + * @param is + * @return + * @throws IOException + */ + public static String readInputStream(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int length = 0; + byte[] buffer = new byte[1024]; + while ((length = is.read(buffer)) != -1) { + baos.write(buffer, 0, length); + } + is.close(); + baos.close(); + return baos.toString(); + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3897859..bc70bfe 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,16 +8,16 @@ spring: profiles: active: dev #数据源配置 -# datasource: -# driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://43.136.29.133:33306/imaotai?characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8 -# username: root -# password: LK.807878712 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://134.175.126.60:33306/flarum_tsayij?characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: LK.807878712 #redis配置 redis: host: 134.175.126.60 port: 36379 - database: 3 + database: 7 timeout: 1800000 lettuce: pool: diff --git a/src/test/java/cn/van333/wxsend/Test001.java b/src/test/java/cn/van333/wxsend/Test001.java new file mode 100644 index 0000000..63da799 --- /dev/null +++ b/src/test/java/cn/van333/wxsend/Test001.java @@ -0,0 +1,24 @@ +package cn.van333.wxsend; + +import cn.van333.wxsend.business.service.PCService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * @author Leo + * @version 1.0 + * @create 2024/4/29 下午5:06 + * @description: + */ +@SpringBootTest +public class Test001 { + + @Autowired + PCService pcService; + @Test + public void test001() throws InterruptedException { + System.out.println("test001"); + pcService.getData(); + } +}