Commit 2e792609 authored by renandong's avatar renandong 🇨🇳

个像标签

parent 26258731
......@@ -15,7 +15,26 @@
<description>push message</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatisplus.version>3.3.0</mybatisplus.version>
<mysql.version>8.0.17</mysql.version>
<druid.version>1.1.13</druid.version>
<commons.lang.version>2.6</commons.lang.version>
<commons.fileupload.version>1.2.2</commons.fileupload.version>
<commons.io.version>2.5</commons.io.version>
<commons.codec.version>1.10</commons.codec.version>
<commons.configuration.version>1.10</commons.configuration.version>
<jwt.version>0.7.0</jwt.version>
<joda.time.version>2.9.9</joda.time.version>
<gson.version>2.8.5</gson.version>
<fastjson.version>1.2.72</fastjson.version>
<hutool.version>4.6.8</hutool.version>
<gexin.version>4.1.1.4</gexin.version>
<lombok.version>1.18.12</lombok.version>
<easypoi.version>4.1.0</easypoi.version>
<thumbnailator.version>0.4.13</thumbnailator.version>
</properties>
<dependencies>
......@@ -23,11 +42,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lomback插件依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -40,29 +59,149 @@
</exclusion>
</exclusions>
</dependency>
<!-- junit-->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<!-- 糊涂工具-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.8</version>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-http</artifactId>
<version>4.1.1.4</version>
<version>${gexin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>${commons.configuration.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda.time.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 计算正方形坐标的开源库 -->
<dependency>
<groupId>org.locationtech.spatial4j</groupId>
<artifactId>spatial4j</artifactId>
<version>0.8</version>
</dependency>
<!-- excel-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>${easypoi.version}</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>${easypoi.version}</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>${easypoi.version}</version>
</dependency>
<!-- excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!--thumbnailator图片处理-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>${thumbnailator.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>getui-nexus</id>
......
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.exception;
/**
* 自定义异常
*
* @author Mark sunlightcs@gmail.com
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有,侵权必究!
*/
package com.weface.common.exception;
import com.weface.common.utils.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
/**
* 异常处理器
*
* @author Mark sunlightcs@gmail.com
*/
@RestControllerAdvice
public class RRExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 处理自定义异常
*/
@ExceptionHandler(RRException.class)
public Model handleRRException(RRException e) {
return Model.error(e.getCode(), e.getMsg());
}
@ExceptionHandler(NoHandlerFoundException.class)
public Model handlerNoFoundException(Exception e) {
logger.error(e.getMessage(), e);
return Model.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public Model handleDuplicateKeyException(DuplicateKeyException e) {
logger.error(e.getMessage(), e);
return Model.error("数据库中已存在该记录");
}
@ExceptionHandler(Exception.class)
public Model handleException(Exception e) {
logger.error(e.getMessage(), e);
return Model.error();
}
/**
* 缺失请求参数处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
public Model handleMissingServletRequestParameterException(MissingServletRequestParameterException e, HttpServletRequest request) {
String message = "缺失请求参数" + e.getParameterName();
logger.error(e.getMessage());
return Model.error(400, message);
}
/**
* 缺失请求参数处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public Model handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
String message = "缺失请求参数" + e.getMessage();
logger.error(e.getMessage());
return Model.error(400, message);
}
/**
* 请求参数类型错误处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public Model handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
String message = "请求参数" + e.getName() + "类型错误";
logger.error(e.getMessage());
return Model.error(400, message);
}
/**
* 请求Conten-Type 错误
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public Model handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, HttpServletRequest request) {
logger.error(e.getMessage());
return Model.error(400, "请求Conten-Type 错误");
}
/**
* 参数类型错误异常类型处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(HttpMessageConversionException.class)
public Model handleHttpMessageNotReadableException(HttpMessageConversionException e, HttpServletRequest request) {
String message = "参数类型错误";
logger.error(e.getMessage());
return Model.error(400, message);
}
/**
* 空指针异常处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(NullPointerException.class)
public Model handleNullPointerException(NullPointerException e, HttpServletRequest request) {
String message = "系统出错了...";
logger.error(e.getMessage());
return Model.error(500, message);
}
/**
* 绑定异常处理
*
* @param e
* @param request
* @return
*/
@ExceptionHandler(BindException.class)
public Model handleBindException(BindException e, HttpServletRequest request) {
BindingResult result = e.getBindingResult();
StringBuilder errorMsg = new StringBuilder();
for (ObjectError error : result.getAllErrors()) {
errorMsg.append(error.getDefaultMessage()).append(",");
}
errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
return Model.error(400, "参数错误" + errorMsg);
}
/**
* 处理运行时异常
*
* @param e
* @param request
* @return
*/
@ExceptionHandler({RuntimeException.class})
@ResponseBody
public Model handleRuntimeException(RuntimeException e, HttpServletRequest request) {
logger.error(e.getMessage());
return Model.error(400, "");
}
}
package com.weface.common.utils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Base64 工具类
*/
public class Base64Util {
private static final char last2byte = (char) Integer.parseInt("00000011", 2);
private static final char last4byte = (char) Integer.parseInt("00001111", 2);
private static final char last6byte = (char) Integer.parseInt("00111111", 2);
private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
private static final char[] encodeTable = 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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
public Base64Util() {
}
public static String encode(byte[] from) {
StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
int num = 0;
char currentByte = 0;
int i;
for (i = 0; i < from.length; ++i) {
for (num %= 8; num < 8; num += 6) {
switch (num) {
case 0:
currentByte = (char) (from[i] & lead6byte);
currentByte = (char) (currentByte >>> 2);
case 1:
case 3:
case 5:
default:
break;
case 2:
currentByte = (char) (from[i] & last6byte);
break;
case 4:
currentByte = (char) (from[i] & last4byte);
currentByte = (char) (currentByte << 2);
if (i + 1 < from.length) {
currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
}
break;
case 6:
currentByte = (char) (from[i] & last2byte);
currentByte = (char) (currentByte << 4);
if (i + 1 < from.length) {
currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
}
}
to.append(encodeTable[currentByte]);
}
}
if (to.length() % 4 != 0) {
for (i = 4 - to.length() % 4; i > 0; --i) {
to.append("=");
}
}
return to.toString();
}
private static String byte2Hex(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer();
String temp = null;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
stringBuffer.append(0);
}
stringBuffer.append(temp);
}
return stringBuffer.toString();
}
public static String getSign(String appKey,Long timestamp,String mastersecret) throws NoSuchAlgorithmException {
String str = appKey + timestamp + mastersecret;
String encodeStr = "";
MessageDigest instance = MessageDigest.getInstance("SHA-256");
instance.update(str.getBytes(StandardCharsets.UTF_8));
encodeStr = byte2Hex(instance.digest());
return encodeStr;
}
}
package com.weface.common.utils;
import java.util.HashMap;
import java.util.Map;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/12/1
* 实现简单缓存
*/
public class CacheUtil {
private static CacheUtil cacheUtil;
private static Map<String, Object> cacheMap;
private CacheUtil() {
cacheMap = new HashMap<String, Object>();
}
public static CacheUtil getInstance() {
if (cacheUtil == null) {
cacheUtil = new CacheUtil();
}
return cacheUtil;
}
/**
* 添加缓存
*
* @param key
* @param obj
*/
public void addCacheData(String key, Object obj) {
cacheMap.put(key, obj);
}
/**
* 取出缓存
*
* @param key
* @return
*/
public Object getCacheData(String key) {
return cacheMap.get(key);
}
/**
* 清除缓存
*
* @param key
*/
public void removeCacheData(String key) {
cacheMap.remove(key);
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
/**
* 系统参数相关Key
*
* @author Mark sunlightcs@gmail.com
*/
public class ConfigConstant {
/**
* 云存储配置KEY
*/
public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
/**
* 常量
*
* @author Mark sunlightcs@gmail.com
*/
public class Constant {
/** 超级管理员ID */
public static final int SUPER_ADMIN = 1;
/**
* 当前页码
*/
public static final String PAGE = "page";
/**
* 每页显示记录数
*/
public static final String LIMIT = "limit";
/**
* 排序字段
*/
public static final String ORDER_FIELD = "sidx";
/**
* 排序方式
*/
public static final String ORDER = "order";
/**
* 升序
*/
public static final String ASC = "asc";
/**
* 菜单类型
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年11月15日 下午1:24:29
*/
public enum MenuType {
/**
* 目录
*/
CATALOG(0),
/**
* 菜单
*/
MENU(1),
/**
* 按钮
*/
BUTTON(2);
private int value;
MenuType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 定时任务状态
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月3日 上午12:07:22
*/
public enum ScheduleStatus {
/**
* 正常
*/
NORMAL(0),
/**
* 暂停
*/
PAUSE(1);
private int value;
ScheduleStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 云服务商
*/
public enum CloudService {
/**
* 七牛云
*/
QINIU(1),
/**
* 阿里云
*/
ALIYUN(2),
/**
* 腾讯云
*/
QCLOUD(3);
private int value;
CloudService(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理
*
* @author Mark sunlightcs@gmail.com
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 日期格式化 日期格式为:yyyy-MM-dd
* @param date 日期
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
/**
* 日期格式化 日期格式为:yyyy-MM-dd
* @param date 日期
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date, String pattern) {
if(date != null){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
/**
* 字符串转换成日期
* @param strDate 日期字符串
* @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
*/
public static Date stringToDate(String strDate, String pattern) {
if (StringUtils.isBlank(strDate)){
return null;
}
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return fmt.parseLocalDateTime(strDate).toDate();
}
/**
* 根据周数,获取开始日期、结束日期
* @param week 周期 0本周,-1上周,-2上上周,1下周,2下下周
* @return 返回date[0]开始日期、date[1]结束日期
*/
public static Date[] getWeekStartAndEnd(int week) {
DateTime dateTime = new DateTime();
LocalDate date = new LocalDate(dateTime.plusWeeks(week));
date = date.dayOfWeek().withMinimumValue();
Date beginDate = date.toDate();
Date endDate = date.plusDays(6).toDate();
return new Date[]{beginDate, endDate};
}
/**
* 对日期的【秒】进行加/减
*
* @param date 日期
* @param seconds 秒数,负数为减
* @return 加/减几秒后的日期
*/
public static Date addDateSeconds(Date date, int seconds) {
DateTime dateTime = new DateTime(date);
return dateTime.plusSeconds(seconds).toDate();
}
/**
* 对日期的【分钟】进行加/减
*
* @param date 日期
* @param minutes 分钟数,负数为减
* @return 加/减几分钟后的日期
*/
public static Date addDateMinutes(Date date, int minutes) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMinutes(minutes).toDate();
}
/**
* 对日期的【小时】进行加/减
*
* @param date 日期
* @param hours 小时数,负数为减
* @return 加/减几小时后的日期
*/
public static Date addDateHours(Date date, int hours) {
DateTime dateTime = new DateTime(date);
return dateTime.plusHours(hours).toDate();
}
/**
* 对日期的【天】进行加/减
*
* @param date 日期
* @param days 天数,负数为减
* @return 加/减几天后的日期
*/
public static Date addDateDays(Date date, int days) {
DateTime dateTime = new DateTime(date);
return dateTime.plusDays(days).toDate();
}
/**
* 对日期的【周】进行加/减
*
* @param date 日期
* @param weeks 周数,负数为减
* @return 加/减几周后的日期
*/
public static Date addDateWeeks(Date date, int weeks) {
DateTime dateTime = new DateTime(date);
return dateTime.plusWeeks(weeks).toDate();
}
/**
* 对日期的【月】进行加/减
*
* @param date 日期
* @param months 月数,负数为减
* @return 加/减几月后的日期
*/
public static Date addDateMonths(Date date, int months) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMonths(months).toDate();
}
/**
* 对日期的【年】进行加/减
*
* @param date 日期
* @param years 年数,负数为减
* @return 加/减几年后的日期
*/
public static Date addDateYears(Date date, int years) {
DateTime dateTime = new DateTime(date);
return dateTime.plusYears(years).toDate();
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
public static String getDomain(){
HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
}
public static String getOrigin(){
HttpServletRequest request = getHttpServletRequest();
return request.getHeader("Origin");
}
}
package com.weface.common.utils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
/**
* http 工具类
*/
@Slf4j
public class HttpUtil {
public static String post(String requestUrl, String accessToken, String params) throws Exception {
String contentType = "application/x-www-form-urlencoded";
return HttpUtil.post(requestUrl, accessToken, contentType, params);
}
public static String post(String requestUrl, String accessToken, String contentType, String params) throws Exception {
String encoding = "UTF-8";
if (requestUrl.contains("nlp")) {
encoding = "GBK";
}
return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
}
public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding) throws Exception {
String url = requestUrl + "?access_token=" + accessToken;
return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
}
public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding) throws Exception {
return HttpUtil.postGeneralUrl(generalUrl, contentType, params, encoding, null);
}
public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding, String token) throws Exception {
URL url = new URL(generalUrl);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
// 设置通用的请求属性
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("Connection", "Keep-Alive");
if (StringUtils.isNotEmpty(token)) {
connection.setRequestProperty("token", token);
}
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setDoInput(true);
// 得到请求的输出流对象
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.write(params.getBytes(StandardCharsets.UTF_8));
out.flush();
out.close();
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> headers = connection.getHeaderFields();
// 遍历所有的响应头字段
// for (String key : headers.keySet()) {
// log.info(key + "--->" + headers.get(key));
// }
// 定义 BufferedReader输入流来读取URL的响应
// BufferedReader in = null;
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
String result = "";
String getLine;
while ((getLine = in.readLine()) != null) {
result += getLine;
}
in.close();
return result;
}
public static String getGeneralUrl(String generalUrl, String contentType, String params, String encoding)
throws Exception {
return HttpUtil.getGeneralUrl(generalUrl, contentType, params, encoding, null);
}
public static String getGeneralUrl(String generalUrl, String contentType, String params, String encoding, String token)
throws Exception {
URL url = new URL(generalUrl);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
// 设置通用的请求属性
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("Connection", "Keep-Alive");
if (StringUtils.isNotEmpty(token)) {
connection.setRequestProperty("token", token);
}
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setDoInput(true);
// 得到请求的输出流对象
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.write(params.getBytes(encoding));
out.flush();
out.close();
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> headers = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : headers.keySet()) {
log.info(key + "--->" + headers.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
BufferedReader in = null;
in = new BufferedReader(
new InputStreamReader(connection.getInputStream(), encoding));
String result = "";
String getLine;
while ((getLine = in.readLine()) != null) {
result += getLine;
}
in.close();
log.info("result:" + result);
return result;
}
public static boolean isJson2(String str) {
boolean flag = false;
try {
Object parse = JSON.parse(str);
flag = true;
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
return flag;
}
// public static String postGeTui(String url, Object obj, String token) {
// CloseableHttpClient httpClient = HttpClients.createDefault();
// HttpPost httpPost = new HttpPost(url);
// httpPost.setHeader("token", token);
// httpPost.setHeader("Content-Type", "application/json");
// httpPost.setHeader("Accept", "application/json");
// StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(obj), "UTF-8");
// System.out.println(stringEntity);
// httpPost.setEntity(stringEntity);
// CloseableHttpResponse response = null;
// try {
// response = httpClient.execute(httpPost);
// StatusLine status = response.getStatusLine();
// int state = status.getStatusCode();
// if (state == HttpStatus.SC_OK) {
// HttpEntity responseEntity = response.getEntity();
// return EntityUtils.toString(responseEntity);
// } else {
// log.error("请求返回:" + state + "(" + url + ")");
// }
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// IoUtil.close(response);
// IoUtil.close(httpClient);
// }
//
// return null;
// }
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import com.alibaba.druid.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
/**
* IP地址
*
* @author Mark sunlightcs@gmail.com
*/
public class IPUtils {
private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// //使用代理,则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return ip;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import java.util.HashMap;
/**
* Map工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class MapUtils extends HashMap<String, Object> {
@Override
public MapUtils put(String key, Object value) {
super.put(key, value);
return this;
}
}
package com.weface.common.utils;
import lombok.Getter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* @author Aleyn
* @description Model
* @since 2021/11/10 16:34
*/
@Getter
public class Model<T> implements Serializable {
private String code;
private String msg;
private T data;
public static final String SUCCESS = "0000";
public static final String ERROR = "500";
public Model<T> setCode(String code) {
this.code = code;
return this;
}
public Model<T> setMsg(String msg) {
this.msg = msg;
return this;
}
public Model<T> setData(T data) {
this.data = data;
return this;
}
public static <T> Model ok() {
return new Model().setCode(SUCCESS).setMsg("请求成功");
}
public static <T> Model ok(T result) {
return new Model().setCode(SUCCESS).setMsg("请求成功").setData(result);
}
public static Model ok(String msg) {
return new Model().setCode(SUCCESS).setMsg(msg);
}
public static Model error(Integer code, String msg) {
return new Model().setCode(code.toString()).setMsg(msg);
}
public static Model error(String msg) {
return new Model().setCode(ERROR).setMsg(msg);
}
public static Model error() {
return new Model().setCode(ERROR).setMsg("未知异常,请联系管理员");
}
public Model put(String k, Object v) {
Map<String, Object> map = new HashMap<>();
map.put(k, v);
this.data = (T) map;
return this;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 总记录数
*/
private int totalCount;
/**
* 每页记录数
*/
private int pageSize;
/**
* 总页数
*/
private int totalPage;
/**
* 当前页数
*/
private int currPage;
/**
* 列表数据
*/
private List<?> list;
/**
* 分页
* @param list 列表数据
* @param totalCount 总记录数
* @param pageSize 每页记录数
* @param currPage 当前页数
*/
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
/**
* 分页
*/
public PageUtils(IPage<?> page) {
this.list = page.getRecords();
this.totalCount = (int)page.getTotal();
this.pageSize = (int)page.getSize();
this.currPage = (int)page.getCurrent();
this.totalPage = (int)page.getPages();
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrPage() {
return currPage;
}
public void setCurrPage(int currPage) {
this.currPage = currPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
}
package com.weface.common.utils;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class PicUtils {
//以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
private static final Logger logger = LoggerFactory.getLogger(PicUtils.class);
private static final Integer ZERO = 0;
private static final Integer ONE_ZERO_TWO_FOUR = 1024;
private static final Integer NINE_ZERO_ZERO = 900;
private static final Integer ONE_ZERO_ZERO = 500;
private static final Integer THREE_TWO_SEVEN_FIVE = 3275;
private static final Integer TWO_ZERO_FOUR_SEVEN = 2047;
private static final Double ZERO_NINE_FIVE = 0.95;
private static final Double ZERO_EIGHT_FIVE = 0.85;
private static final Double ZERO_SIX = 0.6;
private static final Double ZERO_FOUR_FOUR = 0.44;
private static final Double ZERO_FOUR = 0.4;
/**
* 根据指定大小压缩图片
*
* @param imageBytes 源图片字节数组
* @param desFileSize 指定图片大小,单位kb
* @return 压缩质量后的图片字节数组
*/
public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) {
return imageBytes;
}
long srcSize = imageBytes.length;
double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR);
try {
while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream)
.scale(accuracy)
.outputQuality(accuracy)
.toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
}
logger.info("图片原大小={}kb | 压缩后大小={}kb",
srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR);
} catch (Exception e) {
logger.error("【图片压缩】msg=图片压缩失败!", e);
}
return imageBytes;
}
/**
* 自动调节精度(经验数值)
*
* @param size 源图片大小
* @return 图片压缩质量比
*/
private static double getAccuracy(long size) {
double accuracy;
if (size < ONE_ZERO_ZERO) {
accuracy = ZERO_NINE_FIVE;
} else if (size < NINE_ZERO_ZERO) {
accuracy = ZERO_EIGHT_FIVE;
} else if (size < TWO_ZERO_FOUR_SEVEN) {
accuracy = ZERO_SIX;
} else if (size < THREE_TWO_SEVEN_FIVE) {
accuracy = ZERO_FOUR_FOUR;
} else {
accuracy = ZERO_FOUR;
}
return accuracy;
}
/**
* 旋转图片
* @param image ImageIo.read()获取的图片缓冲流
* @param degree 旋转度数
* @param bgcolor 背景颜色,不加为null
* @return 旋转后图片的输入流
*/
public static InputStream rotateImg(BufferedImage image, int degree, Color bgcolor) throws IOException {
//原始图象的宽度
int iw = image.getWidth();
//原始图象的高度
int ih = image.getHeight();
int w = 0;
int h = 0;
int x = 0;
int y = 0;
degree = degree % 360;
//将角度转换到0-360度之间
if (degree < 0) {
degree = 360 + degree;
}
//将角度转为弧度
double ang = Math.toRadians(degree);
/**
*确定旋转后的图象的高度和宽度
*/
if (degree == 180 || degree == 0 || degree == 360) {
w = iw;
h = ih;
} else if (degree == 90 || degree == 270) {
w = ih;
h = iw;
} else {
int d = iw + ih;
w = (int) (d * Math.abs(Math.cos(ang)));
h = (int) (d * Math.abs(Math.sin(ang)));
}
//确定原点坐标
x = (w / 2) - (iw / 2);
y = (h / 2) - (ih / 2);
BufferedImage rotatedImage = new BufferedImage(w, h, image.getType());
Graphics2D gs = (Graphics2D) rotatedImage.getGraphics();
if (bgcolor == null) {
rotatedImage = gs.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
} else {
gs.setColor(bgcolor);
//以给定颜色绘制旋转后图片的背景
gs.fillRect(0, 0, w, h);
}
AffineTransform at = new AffineTransform();
//旋转图象
at.rotate(ang, w / 2, h / 2);
at.translate(x, y);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
op.filter(image, rotatedImage);
image = rotatedImage;
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ImageOutputStream imageOut = ImageIO.createImageOutputStream(byteOut);
ImageIO.write(image, "png", imageOut);
return new ByteArrayInputStream(byteOut.toByteArray());
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.weface.common.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
/**
* 查询参数
*
* @author Mark sunlightcs@gmail.com
*/
public class Query<T> {
public IPage<T> getPage(Map<String, Object> params) {
return this.getPage(params, null, false);
}
public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
//分页参数
long curPage = 1;
long limit = 10;
if (params.get(Constant.PAGE) != null) {
curPage = Convert.toLong(params.get(Constant.PAGE));
}
if (params.get(Constant.LIMIT) != null) {
limit = Convert.toLong(params.get(Constant.LIMIT));
}
//分页对象
Page<T> page = new Page<>(curPage, limit);
//分页参数
params.put(Constant.PAGE, page);
//排序字段
//防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
String orderField = SQLFilter.sqlInject((String) params.get(Constant.ORDER_FIELD));
String order = (String) params.get(Constant.ORDER);
//前端字段排序
if (StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)) {
if (Constant.ASC.equalsIgnoreCase(order)) {
return page.addOrder(OrderItem.asc(orderField));
} else {
return page.addOrder(OrderItem.desc(orderField));
}
}
//没有排序字段,则不排序
if (StringUtils.isBlank(defaultOrderField)) {
return page;
}
//默认排序
if (isAsc) {
page.addOrder(OrderItem.asc(defaultOrderField));
} else {
page.addOrder(OrderItem.desc(defaultOrderField));
}
return page;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring Context 工具类
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class<? extends Object> getType(String name) {
return applicationContext.getType(name);
}
}
\ No newline at end of file
package com.weface.common.xss;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* HTML filtering utility for protecting against XSS (Cross Site Scripting).
*
* This code is licensed LGPLv3
*
* This code is a Java port of the original work in PHP by Cal Hendersen.
* http://code.iamcal.com/php/lib_filter/
*
* The trickiest part of the translation was handling the differences in regex handling
* between PHP and Java. These resources were helpful in the process:
*
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
* http://www.regular-expressions.info/modifiers.html
*
* A note on naming conventions: instance variables are prefixed with a "v"; global
* constants are in all caps.
*
* Sample use:
* String input = ...
* String clean = new HTMLFilter().filter( input );
*
* The class is not thread safe. Create a new instance if in doubt.
*
* If you find bugs or have suggestions on improvement (especially regarding
* performance), please contact us. The latest version of this
* source, and our contact details, can be found at http://xss-html-filter.sf.net
*
* @author Joseph O'Connell
* @author Cal Hendersen
* @author Michael Semb Wever
*/
public final class HTMLFilter {
/** regex flag union representing /si modifiers in php **/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("<");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
/** set of allowed html elements, along with allowed attributes for each element **/
private final Map<String, List<String>> vAllowed;
/** counts of open tags for each (allowable) html element **/
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
/** html elements which must always be self-closing (e.g. "<img />") **/
private final String[] vSelfClosingTags;
/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/
private final String[] vNeedClosingTags;
/** set of disallowed html elements **/
private final String[] vDisallowed;
/** attributes which should be checked for valid protocols **/
private final String[] vProtocolAtts;
/** allowed protocols **/
private final String[] vAllowedProtocols;
/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/
private final String[] vRemoveBlanks;
/** entities allowed within html markup **/
private final String[] vAllowedEntities;
/** flag determining whether comments are allowed in input String. */
private final boolean stripComment;
private final boolean encodeQuotes;
private boolean vDebug = false;
/**
* flag determining whether to try to make tags when presented with "unbalanced"
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
* unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/** Default constructor.
*
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<String>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<String>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<String>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
}
/** Set debug flag to true. Otherwise use default settings. See the default constructor.
*
* @param debug turn debug on with a true argument
*/
public HTMLFilter(final boolean debug) {
this();
vDebug = debug;
}
/** Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
public HTMLFilter(final Map<String,Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
private void debug(final String msg) {
if (vDebug) {
Logger.getAnonymousLogger().info(msg);
}
}
//---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
//---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted
* html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
debug("************************************************");
debug(" INPUT: " + input);
s = escapeComments(s);
debug(" escapeComments: " + s);
s = balanceHTML(s);
debug(" balanceHTML: " + s);
s = checkTags(s);
debug(" checkTags: " + s);
s = processRemoveBlanks(s);
debug("processRemoveBlanks: " + s);
s = validateEntities(s);
debug(" validateEntites: " + s);
debug("************************************************\n\n");
return s;
}
public boolean isAlwaysMakeTags(){
return alwaysMakeTags;
}
public boolean isStripComments(){
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
final String match = m.group(1); //(.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
s = buf.toString();
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
s += "</" + key + ">";
}
}
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (!inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
String params = "";
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<String>();
final List<String> paramValues = new ArrayList<String>();
while (m2.find()) {
paramNames.add(m2.group(1)); //([a-z0-9]+)
paramValues.add(m2.group(3)); //(.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); //([a-z0-9]+)
paramValues.add(m3.group(3)); //([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params += " " + paramName + "=\"" + paramValue + "\"";
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1, s.length());
if (s.startsWith("#//")) {
s = "#" + s.substring(3, s.length());
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); //([^&;]*)
final String two = m.group(2); //(?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s){
if(encodeQuotes){
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); //(>|^)
final String two = m.group(2); //([^<]+?)
final String three = m.group(3); //(<|$)
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));
}
m.appendTail(buf);
return buf.toString();
}else{
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble)
? '&' + preamble
: "&amp;" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}
\ No newline at end of file
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.xss;
import org.apache.commons.lang.StringUtils;
/**
* SQL过滤
*
* @author Mark sunlightcs@gmail.com
*/
public class SQLFilter {
/**
* SQL注入过滤
* @param str 待验证的字符串
*/
public static String sqlInject(String str){
if(StringUtils.isBlank(str)){
return null;
}
//去掉'|"|;|\字符
str = StringUtils.replace(str, "'", "");
str = StringUtils.replace(str, "\"", "");
str = StringUtils.replace(str, ";", "");
str = StringUtils.replace(str, "\\", "");
//转换成小写
str = str.toLowerCase();
//非法字符
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
//判断是否包含非法字符
for(String keyword : keywords){
if(str.indexOf(keyword) != -1){
throw new RuntimeException("包含非法字符");
}
}
return str;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.xss;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* XSS过滤
*
* @author Mark sunlightcs@gmail.com
*/
public class XssFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
(HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
@Override
public void destroy() {
}
}
\ No newline at end of file
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.common.xss;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* XSS过滤处理
*
* @author Mark sunlightcs@gmail.com
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
//没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
HttpServletRequest orgRequest;
//html过滤
private final static HTMLFilter htmlFilter = new HTMLFilter();
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
orgRequest = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
//非json类型,直接返回
if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
return super.getInputStream();
}
//为空,直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StringUtils.isBlank(json)) {
return super.getInputStream();
}
//xss过滤
json = xssEncode(json);
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
}
};
}
@Override
public String getParameter(String name) {
String value = super.getParameter(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] parameters = super.getParameterValues(name);
if (parameters == null || parameters.length == 0) {
return null;
}
for (int i = 0; i < parameters.length; i++) {
parameters[i] = xssEncode(parameters[i]);
}
return parameters;
}
@Override
public Map<String,String[]> getParameterMap() {
Map<String,String[]> map = new LinkedHashMap<>();
Map<String,String[]> parameters = super.getParameterMap();
for (String key : parameters.keySet()) {
String[] values = parameters.get(key);
for (int i = 0; i < values.length; i++) {
values[i] = xssEncode(values[i]);
}
map.put(key, values);
}
return map;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
private String xssEncode(String input) {
return htmlFilter.filter(input);
}
/**
* 获取最原始的request
*/
public HttpServletRequest getOrgRequest() {
return orgRequest;
}
/**
* 获取最原始的request
*/
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
if (request instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) request).getOrgRequest();
}
return request;
}
}
package com.weface.component;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.weface.common.utils.Base64Util;
import com.weface.common.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/2
*/
@Slf4j
public class GeTuiUtils {
//请求前缀
public static final String GETUIBASEURL = "https://restapi.getui.com/v2/";
public static final String APPID = "CYol79N33N71BV6dcjrqj3";
public static final String BASEURL = "https://openapi-gi.getui.com/v2/";
public static final String ENCODING = "UTF-8";
public static final String CONTENTTYPE = "application/json;charset=utf-8";
public static final String APPKEY = "rdLx5zumRK7oEme8MheAh8";
public static final String MASTERSECRET = "mekLZ4frLu7RHtKsN9mQn";
/**
* 获取个像token
*
* @return JSONObject
*/
public static String getAuth() {
// 获取token地址
log.info("开始获取个像token");
String getAccessTokenUrl = BASEURL + APPID + "/auth_sign";
Long timestamp = System.currentTimeMillis();
try {
Map<String, Object> map = new HashMap<>();
map.put("sign", Base64Util.getSign(APPKEY, timestamp, MASTERSECRET));
map.put("timestamp", timestamp);
String result = HttpUtil.postGeneralUrl(getAccessTokenUrl, CONTENTTYPE, JSONObject.toJSONString(map), ENCODING);
if (HttpUtil.isJson2(result)) {
JSONObject jsonObject = JSONObject.parseObject(result);
if ("true".equals(jsonObject.getString("result"))) {
Console.log(jsonObject);
return jsonObject.getString("authtoken");
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("获取个像token失败!");
}
return null;
}
/**
* 获取个推token
*
* @return JSONObject
*/
public static JSONObject getGeTuiAuth() {
// 获取token地址
log.info("开始获取个推token");
String getAccessTokenUrl = GETUIBASEURL + APPID + "/auth";
Long timestamp = System.currentTimeMillis();
try {
Map<String, Object> map = new HashMap<>();
map.put("sign", Base64Util.getSign(APPKEY, timestamp, MASTERSECRET));
map.put("timestamp", timestamp);
map.put("appkey", APPKEY);
String result = HttpUtil.postGeneralUrl(getAccessTokenUrl, CONTENTTYPE, JSONObject.toJSONString(map), ENCODING);
if (HttpUtil.isJson2(result)) {
JSONObject jsonObject = JSONObject.parseObject(result);
if (jsonObject.containsKey("code") && jsonObject.getInteger("code") == 0) {
return jsonObject.getJSONObject("data");
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("获取个推token失败!");
}
return null;
}
/**
* 根据giUid查询用户相关标签code
*
* @param userIdList
* @param token
* @return
* @throws Exception
*/
public static String queryTag(String[] userIdList, String token) throws Exception {
//请求url
String getUsersCidUrl = "https://openapi-gi.getui.com/v3/" + APPID + "/query_tag";
//将token以及用户ID封装调用画像查询接口
Map<String, Object> map = new HashMap<>();
map.put("userIdList", userIdList);
map.put("token", token);
//发送post请求拿到当前用户的所有图像
return HttpUtil.postGeneralUrl(getUsersCidUrl, CONTENTTYPE, JSONObject.toJSONString(map), ENCODING);
}
/**
* 执行别名单推
*
* @param alias 用户别名
* @param messageTemplate 消息模板
* @param token token
* @return 消息推送结果
* @throws Exception
*/
public static String singlePush(String[] alias, MessageTemplate messageTemplate, String token) throws Exception {
Map<String, Object> map = convertBeanToMap(alias, messageTemplate);
//请求url
String url = GETUIBASEURL + APPID + "/push/single/alias";
HttpRequest request = cn.hutool.http.HttpUtil.createPost(url);
request.header("token", token);
request.body(JSONUtil.toJsonStr(map));
log.info("执行别名单推");
return request.execute().body();
}
/**
* 创建消息拿到任务id
*
* @param messageTemplate 消息模板
* @param token token
* @return 任务id
* @throws Exception
*/
public static String getTaskId(MessageTemplate messageTemplate, String token) throws Exception {
Map<String, Object> map = convertBeanToMap(null, messageTemplate);
//请求url
String url = GETUIBASEURL + APPID + "/push/list/message";
//创建post请求
HttpRequest request = cn.hutool.http.HttpUtil.createPost(url);
//设置请求头token
request.header("token", token);
//设置请求体数据
request.body(JSONUtil.toJsonStr(map));
////创建消息 获取taskid
log.info("获取任务id");
String body = request.execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
return (jsonObject.containsKey("code") && jsonObject.getInteger("code") == 0) ? jsonObject.getJSONObject("data").getString("taskid") : body;
}
/**
* 实体类封装为map
*
* @param alias 别名
* @param messageTemplate 消息模板
* @return map对象
*/
public static Map<String, Object> convertBeanToMap(String[] alias, MessageTemplate messageTemplate) {
if (ArrayUtils.isEmpty(alias) || messageTemplate == null) return null;
Map<String, Object> map = new HashMap<>();
//request_id 唯一不重复
map.put("request_id", System.currentTimeMillis() + RandomUtil.randomString(15));
//任务组名
String group_name = messageTemplate.getGroup_name();
if (StringUtils.isNotBlank(group_name)) {
map.put("group_name", group_name);
}
Map<String, Object> audienceMap = new HashMap<>();
audienceMap.put("alias", alias);
map.put("audience", audienceMap);
//消息离线时间设置,单位毫秒,-1表示不设离线,-1 ~ 3 * 24 * 3600 * 1000(3天)之间
Long ttl = messageTemplate.getTtl();
if (ttl != null) {
Map<String, Object> settingsMap = new HashMap<>();
settingsMap.put("ttl", ttl);
map.put("settings", settingsMap);
}
//消息模板
Map<String, Object> pushMessageMap = new HashMap<>();
Map<String, Object> notificationMap = new HashMap<>();
notificationMap.put("title", messageTemplate.getTitle());
notificationMap.put("body", messageTemplate.getBody());
notificationMap.put("click_type", messageTemplate.getClick_type());
switch (messageTemplate.getClick_type()) {
case "intent":
notificationMap.put("intent", messageTemplate.getIntent());
case "url":
notificationMap.put("url", messageTemplate.getUrl());
}
pushMessageMap.put("notification", notificationMap);
map.put("push_message", pushMessageMap);
return map;
}
/**
* 执行别名批量推送
*
* @param map body参数
* @param token token
* @return 执行结果
*/
public static String listPushByAlias(Map<String, Object> map, String token) {
//请求url
String url = GETUIBASEURL + APPID + "/push/list/alias";
//创建post请求
HttpRequest request = cn.hutool.http.HttpUtil.createPost(url);
//设置请求头token
request.header("token", token);
//设置请求体数据
request.body(JSONUtil.toJsonStr(map));
//执行请求
log.info("执行别名批量推送");
return request.execute().body();
}
}
package com.weface.component;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.weface.entity.MenuTagsEntity;
import com.weface.entity.TUserTagEntity;
import com.weface.entity.UserMenusEntity;
import com.weface.service.MenuTagsService;
import com.weface.service.TUserTagService;
import com.weface.common.exception.RRException;
import com.weface.common.utils.CacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/2
*/
@Slf4j
@Component
@Transactional
public class MenuService {
@Autowired
private MenuTagsService menuTagsService;
@Autowired
private TUserTagService tUserTagService;
private static final CacheUtil CACHE = CacheUtil.getInstance();
private static final ReentrantLock lock = new ReentrantLock();
/**
* 获取token并缓存一份
*
* @return 从缓存中拿token
*/
public String getAuthToken() {
String authToken = "";
lock.lock();
try {
authToken = Convert.toStr(CACHE.getCacheData("authToken"));
if (Objects.isNull(authToken)) {
authToken = GeTuiUtils.getAuth();
// authToken = "01718df19708866512701e7637fee9568a0dac5f9390609f08ef148cab56c060";
if (ObjectUtil.isNull(authToken)) throw new RRException("获取个推token失败");
CACHE.addCacheData("authToken", authToken);
}
} catch (RRException e) {
e.printStackTrace();
log.error("加锁失败!");
} finally {
lock.unlock();
}
return authToken;
}
/**
* 通过gid以及操作系统字段获取标签code并转为实际值,后存库并返回
*
* @param userList 用户的giUid
* @return
*/
public Map<String, Object> getUserTags(String[] userList) {
try {
if (ArrayUtil.isEmpty(userList)) return null;
//根据用户giuId请求到用户最新的爱好数据
Map<String, Object> map = queryTag(userList);
//以上均做过非空处理如果返回不为空 那么map内一定是有数据的
if (map == null) return null;
return map;
} catch (Exception e) {
e.printStackTrace();
log.error("执行新增用户标签数据到用户表中发生异常" + e.getMessage());
}
return null;
}
/**
* 从map中解析标签并收集关系表数据
*
* @param map 个推返回数据
* @return 标签数据
*/
public List<UserMenusEntity> getTagUser(Map<String, Object> map) {
if (ObjectUtil.isNull(map)) return null;
//获取所有用户标签
List<Map<String, Object>> userTag = Convert.convert(new TypeReference<List<Map<String, Object>>>() {
}, map.get("userTag"));
//收集中间表数据
List<UserMenusEntity> userMenusList = new ArrayList<>();
//获取所有用户信息
List<TUserTagEntity> tUserTagEntities = tUserTagService.list();
//遍历所有返回用户数据
for (Map<String, Object> item : userTag) {
//拿到当前用户giUid
String userId = (String) item.get("userId");
//拿到标签
List<MenuTagsEntity> list = Convert.convert(new TypeReference<List<MenuTagsEntity>>() {
}, item.get("tags"));
//查找当前用户的id
Optional<TUserTagEntity> first = tUserTagEntities.stream().filter(x -> userId.equals(x.getGid())).findFirst();
//如果对象不为空
if (first.isPresent()) {
//拿到id
String uid = first.get().getUid();
//收集标签id
List<Long> collect = list.stream().map(MenuTagsEntity::getId).collect(Collectors.toList());
//遍历标签id
for (Long aLong : collect) {
//填充数据
UserMenusEntity userMenusEntity = new UserMenusEntity();
userMenusEntity.setUserId(uid);
userMenusEntity.setTagsId(aLong);
//添加数据到集合内
userMenusList.add(userMenusEntity);
}
}
}
return userMenusList;
}
/**
* 通过用户id获取获取用户标签信息
*
* @param userIdList gid
* @return
*/
private Map<String, Object> queryTag(String[] userIdList) {
//设置标识
boolean flag = true;
//获取token
String authToken = getAuthToken();
try {
while (flag) {
//将token以及用户ID封装调用画像查询接口
String result = GeTuiUtils.queryTag(userIdList, authToken);
JSONObject jsonObject = JSONObject.parseObject(result);
//如果状态码为302token已过期则需要重新获取token并更新数据库token
if (jsonObject.containsKey("error_info") && jsonObject.getJSONObject("error_info").getInteger("error_code") == 302) {
log.warn("token过期");
//authToken = "01718df19708866512701e7637fee9568a0dac5f9390609f08ef148cab56c060";
authToken = GeTuiUtils.getAuth();
if (ObjectUtil.isNull(authToken)) throw new RRException("获取个推token失败");
CACHE.addCacheData("authToken", authToken);
break;
}
//判断返回json内是否包含要解析的userTag
if (jsonObject.containsKey("userTag")) {
JSONArray userTag = jsonObject.getJSONArray("userTag");
List<Map<String, Object>> userTags = getUserTagByTag(userTag);
Map<String, Object> all = null;
if (userTags != null && userTag.size() > 0) {
all = new HashMap<>();
//将数据封装并转为json格式返回
all.put("userTag", userTags);
all.put("error_code", 0);
}
return all;
//如果以上步骤无法走通则直接返回。并修改标识符终止循环
} else {
log.error("返回值内不包含需要解析的数据" + jsonObject.toJSONString());
flag = false;
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("执行调用个推接口获取标签数据发生异常" + e.getMessage());
}
return null;
}
/**
* 解析json拿到所有用户
*
* @param userTag 用户数据
* @return
*/
private List<Map<String, Object>> getUserTagByTag(JSONArray userTag) {
List<Map<String, Object>> userTags = null;
Integer failCount = Convert.toInt(CACHE.getCacheData("failCount"));
Integer successCount = Convert.toInt(CACHE.getCacheData("successCount"));
if (ObjectUtil.isNull(failCount))
failCount = 0;
if (ObjectUtil.isNull(successCount))
successCount = 0;
if (userTag != null && userTag.size() > 0) {
//封装返回的数据userTags
userTags = new ArrayList<>(userTag.size());
for (Object o : userTag) {
JSONObject jsonObject1 = JSONObject.parseObject(o.toString());
//判断返回json内是否包含要解析的error_code,并判断返回的json状态码是否正常
if (jsonObject1.containsKey("error_code") && jsonObject1.getInteger("error_code") == 0) {
String userId = "";
if (jsonObject1.containsKey("userId"))
userId = jsonObject1.getString("userId");
//如果从json中获取的当前giUid为空,则跳出本次循环
if (StringUtils.isBlank(userId)) continue;
//封装当前用户的所有tags信息
Map<String, Object> data = new HashMap<>(2);
//封装要返回的所有tags
List<MenuTagsEntity> list = getMenuByTag(jsonObject1.getJSONArray("tags"));
//根据giUid查询的标签如果为空则跳出本次循环
if (list != null && list.size() > 0) {
data.put("userId", userId);
data.put("tags", list);
userTags.add(data);
}
successCount++;
} else {
failCount++;
}
}
}
CACHE.addCacheData("failCount", failCount);
CACHE.addCacheData("successCount", successCount);
return userTags;
}
/**
* 解析json拿到当前用户对应的标签列表
* 根据标签的code查询标签数据
*
* @param tags 标签
* @return
*/
private List<MenuTagsEntity> getMenuByTag(JSONArray tags) {
List<MenuTagsEntity> list = null;
if (tags != null && tags.size() > 0) {
list = new ArrayList<>(tags.size());
for (Object tag : tags) {
JSONObject jsonObject2 = JSONObject.parseObject(tag.toString());
String code = "";
if (jsonObject2.containsKey("code"))
code = jsonObject2.getString("code");
//如果传入标签的code为空则跳出本次循环
if (StringUtils.isBlank(code)) continue;
String weight = "";
if (jsonObject2.containsKey("weight"))
weight = jsonObject2.getString("weight");
//根据code或权重查询图像
MenuTagsEntity one = menuTagsService.getOneByCodeOrWeight(code, weight);
//如果查询的结果为空则跳出本次循环
if (one == null) continue;
list.add(one);
}
}
return list;
}
}
package com.weface.component;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/23
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MessageTemplate {
/**
* 任务组
*/
private String group_name;
/**
* 消息离线时间设置,单位毫秒,-1表示不设离线,-1 ~ 3 * 24 * 3600 * 1000(3天)之间
*/
private Long ttl;
/**
* 通知消息标题,长度 ≤ 50
*/
private String title;
/**
* 通知消息内容,长度 ≤ 256
*/
private String body;
/**
* 点击通知后续动作,
* 目前支持以下后续动作,
* intent:打开应用内特定页面,
* url:打开网页地址,
* payload:自定义消息内容启动应用,
* payload_custom:自定义消息内容不启动应用,
* startapp:打开应用首页,
* none:纯通知,无后续动作
*/
private String click_type;
/**
* click_type为url时必填 无 点击通知打开链接
*/
private String url;
/**
* click_type为intent时必填 无 点击通知打开应用特定页面,长度 ≤ 4096;
*/
private String intent;
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}
\ No newline at end of file
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.config;
import com.weface.common.xss.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
/**
* Filter配置
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.weface.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatis-plus配置
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
package com.weface.controller;
import com.weface.common.utils.Model;
import com.weface.common.utils.PageUtils;
import com.weface.component.MenuService;
import com.weface.dto.UserTagFrom;
import com.weface.service.MenuTagsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 所有标签等级划分
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@RestController
@RequestMapping("/tags/menuTags")
public class MenuTagsController {
@Autowired
private MenuTagsService menuTagsService;
@Autowired
private MenuService menuService;
/**
* 标签列表 可模糊查询根据levelThird
*/
@PostMapping("/list")
public Model list(@RequestBody Map<String, Object> params) {
PageUtils page = menuTagsService.queryPage(params);
return Model.ok(page);
}
/**
* 根据用户giUid先调个推拿到code后走数据库拿到数据并更新相关数据后返回
*
* @return
*/
@PostMapping("/queryTagByGiUid")
public Model queryTagsByGiUid(@RequestBody UserTagFrom userTagFrom) {
Map<String, Object> data = menuService.getUserTags(userTagFrom.getGiUidList());
return Model.ok(data);
}
}
package com.weface.controller;
import com.weface.common.utils.Model;
import com.weface.common.utils.PageUtils;
import com.weface.dto.UserTagFrom;
import com.weface.service.TUserTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@RestController
@RequestMapping("/tags/userTags")
public class UserTagsController {
@Autowired
private TUserTagService tUserTagService;
/**
* 查询所有用户对应标签信息
*/
@PostMapping("/list")
public Model list(@RequestBody Map<String, Object> params) {
PageUtils page = tUserTagService.getUserAndTags(params);
return Model.ok(page);
}
/**
* 根据标签查询用户gid
*/
@PostMapping("/queryByTag")
public Model queryByTag(@RequestBody UserTagFrom userTagFrom) {
List<String> data = tUserTagService.getGidByTag(userTagFrom.getTags());
return Model.ok(data);
}
/**
* 根据gid查询用户标签
*/
@PostMapping("/queryByGid")
public Model queryByGid(@RequestBody UserTagFrom userTagFrom) {
// String[] userIdList = new String[]{"3917d1037675078ae3a1abb4c6da3ef6", "1231313123"};
// String os = "Android";
Map<String, Object> data = tUserTagService.getTagByGid(userTagFrom.getGiUidList());
return Model.ok(data);
}
}
package com.weface.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.weface.entity.MenuTagsEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 所有标签等级划分
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@Mapper
public interface MenuTagsDao extends BaseMapper<MenuTagsEntity> {
}
package com.weface.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.weface.entity.TUserTagEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 用户ID标签关联表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-30 18:57:06
*/
@Mapper
public interface TUserTagDao extends BaseMapper<TUserTagEntity> {
//查询用户和标签信息
<T> IPage<TUserTagEntity> getUserAndTags(Page<T> page, String giUid, String tag);
//使用limit分页查询
List<String> findGidByLimit(int pageRecord, int limit);
//根据标签查询用户gid
List<String> getGidByTag(List<String> list);
//根据gid查询用户标签
List<TUserTagEntity> getTagByGid(List<String> list);
//查询所有用户标签关联数据
List<TUserTagEntity> selectAllUserForTags();
//查询今天更新用户gid
List<String> findTodayGid();
}
package com.weface.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.weface.entity.UserMenusEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 用户和标签中间表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@Mapper
public interface UserMenusDao extends BaseMapper<UserMenusEntity> {
//批量插入
int batchInsert(List<UserMenusEntity> list);
//全表删除
int deleteAll(List<String> list);
}
package com.weface.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/3
*/
@Data
public class MenuTagsForm implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 一级标签名称
*/
private String levelFirst;
/**
* 二级标签名称
*/
private String levelSecond;
/**
* 三级标签名称
*/
private String levelThird;
/**
* 编码
*/
private String code;
/**
* 套餐等级
*/
private Integer menuGrade;
/**
* 是否有权重
*/
private String weight;
}
package com.weface.dto;
import lombok.Data;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/17
*/
@Data
public class UserTagFrom {
private String[] giUidList;
private String[] tags;
private Integer page;
}
package com.weface.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 所有标签等级划分
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@Data
@TableName("tb_menu_tags")
public class MenuTagsEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
* 一级标签名称
*/
@Excel(name = "一级标签", width = 10)
private String levelFirst;
/**
* 二级标签名称
*/
@Excel(name = "二级标签", width = 10)
private String levelSecond;
/**
* 三级标签名称
*/
@Excel(name = "三级标签", width = 10)
private String levelThird;
/**
* 编码
*/
private String code;
/**
* 套餐等级
*/
private Integer menuGrade;
/**
* 是否有权重
*/
private String weight;
/**
* 是否删除
*/
private Integer isDel;
/**
*
*/
private Date createTime;
/**
*
*/
private Date updateTime;
}
package com.weface.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 用户ID标签关联表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-30 18:57:06
*/
@ExcelTarget("tUserTagEntity")
@Data
@TableName("t_user_tag")
public class TUserTagEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@Excel(name = "id", width = 10)
@TableId
private Long id;
/**
* 用户ID
*/
private String uid;
/**
* 用户手机号
*/
private String tel;
/**
* 标签id
*/
@Excel(name = "用户Gid", width = 40)
private String gid;
/**
* 标签数据
*/
// @ExcelCollection(name = "标签列表",orderNum = "3")
// @TableField(exist = false)
// private List<MenuTagsEntity> list;
/**
* 标签数据
*/
@ExcelEntity(name = "标签列表",id = "id")
@TableField(exist = false)
private List<MenuTagsEntity> list;
}
package com.weface.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
* 用户和标签中间表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
@Data
@TableName("tb_user_menus")
public class UserMenusEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
* 用户id
*/
private String userId;
/**
* 标签ID
*/
private Long tagsId;
}
package com.weface.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.weface.entity.MenuTagsEntity;
import com.weface.common.utils.PageUtils;
import java.util.Map;
/**
* 所有标签等级划分
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
public interface MenuTagsService extends IService<MenuTagsEntity> {
//列表
PageUtils queryPage(Map<String, Object> params);
//根据code和权重查询标签
MenuTagsEntity getOneByCodeOrWeight(String code, String weight);
}
package com.weface.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.weface.entity.TUserTagEntity;
import com.weface.common.utils.PageUtils;
import java.util.List;
import java.util.Map;
/**
* 用户ID标签关联表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-30 18:57:06
*/
public interface TUserTagService extends IService<TUserTagEntity> {
//查询所有用户对应标签信息
PageUtils getUserAndTags(Map<String, Object> params);
//使用limit分页查询
List<String> findGidByLimit(int i, int limit);
//查询当天的数据
List<String> findTodayGid();
//根据标签查询用户gid
List<String> getGidByTag(String[] tags);
//根据gid查询用户标签
Map<String, Object> getTagByGid(String[] userIdList);
List<TUserTagEntity> getAllImport();
}
package com.weface.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.weface.entity.UserMenusEntity;
import java.util.List;
/**
* 用户和标签中间表
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2021-11-18 16:20:52
*/
public interface UserMenusService extends IService<UserMenusEntity> {
//批量插入
void batchInsert(List<UserMenusEntity> list);
}
package com.weface.serviceimpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weface.dao.MenuTagsDao;
import com.weface.entity.MenuTagsEntity;
import com.weface.service.MenuTagsService;
import com.weface.common.utils.PageUtils;
import com.weface.common.utils.Query;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service("menuTagsService")
public class MenuTagsServiceImpl extends ServiceImpl<MenuTagsDao, MenuTagsEntity> implements MenuTagsService {
/**
* 列表
*
* @param params 参数
* @return 标签
*/
@Override
public PageUtils queryPage(Map<String, Object> params) {
String levelThird = (String) params.get("levelThird");
IPage<MenuTagsEntity> page = this.page(
new Query<MenuTagsEntity>().getPage(params),
new QueryWrapper<MenuTagsEntity>().lambda().like(StringUtils.isNotBlank(levelThird), MenuTagsEntity::getLevelThird, levelThird)
);
return new PageUtils(page);
}
/**
* 根据code和权重查询标签
*
* @param code 编码
* @param weight 权重
* @return 标签信息
*/
@Override
public MenuTagsEntity getOneByCodeOrWeight(String code, String weight) {
return this.getOne(new QueryWrapper<MenuTagsEntity>()
.lambda().eq(MenuTagsEntity::getCode, code)
.eq(MenuTagsEntity::getLevelFirst, "Android")
.eq(StringUtils.isNotBlank(weight), MenuTagsEntity::getWeight, weight));
}
}
\ No newline at end of file
package com.weface.serviceimpl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weface.dao.TUserTagDao;
import com.weface.dto.MenuTagsForm;
import com.weface.entity.TUserTagEntity;
import com.weface.service.TUserTagService;
import com.weface.common.utils.PageUtils;
import com.weface.common.utils.Query;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.*;
@Service("tUserTagService")
public class TUserTagServiceImpl extends ServiceImpl<TUserTagDao, TUserTagEntity> implements TUserTagService {
/**
* 查询用户和标签信息
*
* @param params 查询参数
* @return 用户和标签数据分页
*/
@Override
public PageUtils getUserAndTags(Map<String, Object> params) {
IPage<Object> page = new Query<>().getPage(params);
String giUid = (String) params.get("giUid");
String tag = (String) params.get("tag");
IPage<TUserTagEntity> userAndTagsByUid = this.baseMapper.getUserAndTags(new Page<TUserTagEntity>(page.getCurrent(), page.getSize()), giUid, tag);
userAndTagsByUid.setTotal(userAndTagsByUid.getRecords().size());
return new PageUtils(userAndTagsByUid);
}
/**
* 使用limit分页查询
*
* @param pageRecord 起始值
* @param limit 每次查询数量
* @return gid
*/
@Override
public List<String> findGidByLimit(int pageRecord, int limit) {
return this.baseMapper.findGidByLimit(pageRecord, limit);
}
/**
* 查询当天修改的用户gid
*
* @return
*/
@Override
public List<String> findTodayGid() {
return this.baseMapper.findTodayGid();
}
/**
* 根据标签查询用户gid
*
* @param tags 标签完全匹配
* @return gid
*/
@Override
public List<String> getGidByTag(String[] tags) {
return this.baseMapper.getGidByTag(Arrays.asList(tags));
}
/**
* 根据gid查询用户标签
*
* @param userIdList gid
* @return 标签信息
*/
@Override
public Map<String, Object> getTagByGid(String[] userIdList) {
List<TUserTagEntity> userByUid = this.baseMapper.getTagByGid(Arrays.asList(userIdList));
List<Map<String, Object>> list = new ArrayList<>(userByUid.size());
for (TUserTagEntity tUserTagEntity : userByUid) {
Map<String, Object> map = new HashMap<>();
List<MenuTagsForm> objects = new ArrayList<>();
tUserTagEntity.getList().forEach(item -> {
MenuTagsForm menuTagsForm = new MenuTagsForm();
BeanUtils.copyProperties(item, menuTagsForm);
objects.add(menuTagsForm);
});
map.put("userId", tUserTagEntity.getGid());
map.put("tags", objects);
list.add(map);
}
Map<String, Object> map = new HashMap<>(2);
map.put("error_code", 0);
map.put("userTag", list);
return map;
}
@Override
public List<TUserTagEntity> getAllImport() {
return this.baseMapper.selectAllUserForTags();
}
}
\ No newline at end of file
package com.weface.serviceimpl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weface.dao.UserMenusDao;
import com.weface.entity.UserMenusEntity;
import com.weface.service.UserMenusService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service("userMenusService")
@Transactional
public class UserMenusServiceImpl extends ServiceImpl<UserMenusDao, UserMenusEntity> implements UserMenusService {
/**
* 批量插入
*
* @param userMenusList 被插入数据
*/
@Override
public void batchInsert(List<UserMenusEntity> userMenusList) {
if (CollectionUtils.isNotEmpty(userMenusList)) {
List<String> deleteUid = getDeleteUid(userMenusList);
//批量插入前全删
this.baseMapper.deleteAll(deleteUid);
//获取集合长度
int count = userMenusList.size();
//每次批量插入个数
int limit = 10000;
int sum = 0;
//计算页数
int totalPage = (count % limit == 0) ? (count / limit) : (count / limit + 1);
for (int i = 0; i < totalPage; i++) {
List<UserMenusEntity> userMenusEntities = new ArrayList<>(10000);
//如果是最后一页,则截取到最后
if (i == totalPage - 1) {
userMenusEntities = userMenusList.subList(i * limit, count);
} else {
userMenusEntities = userMenusList.subList(i * limit, (i + 1) * limit);
}
//批量插入每次一万条
sum += this.baseMapper.batchInsert(userMenusEntities);
}
if (sum > 0) {
log.warn("新增成功记录==" + sum + "==条");
} else {
log.error("新增失败");
}
}
}
private List<String> getDeleteUid(List<UserMenusEntity> userMenusList){
return userMenusList.stream().map(UserMenusEntity::getUserId).distinct().collect(Collectors.toList());
}
}
\ No newline at end of file
package com.weface.task;
import com.weface.component.MenuService;
import com.weface.entity.UserMenusEntity;
import com.weface.service.TUserTagService;
import com.weface.service.UserMenusService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @CreateUser: Administrator
* @CreateTime: 2021/11/4
*/
@Component
@Slf4j
@EnableScheduling
public class UserTagsTask {
@Autowired
private MenuService menuService;
@Autowired
private TUserTagService tUserTagService;
@Autowired
private UserMenusService userMenusService;
@Scheduled(cron = "0 0 0 1 * ?")
public void updateUserTags() {
try {
List<String> todayGid = tUserTagService.findTodayGid();
int size = todayGid.size();
int limit = 1000;
List<UserMenusEntity> userMenusList = new ArrayList<>();
int totalPage = (size % limit == 0) ? (size / limit) : (size / limit + 1);
CountDownLatch latch = new CountDownLatch(totalPage);
ExecutorService pool = Executors.newFixedThreadPool(totalPage);
//收集中间表数据
for (int i = 0; i < totalPage; i++) {
int finalI = i;
Runnable runnable = () -> {
List<String> list = new ArrayList<>();
if (finalI == totalPage - 1) {
list = todayGid.subList(finalI * limit, size);
} else {
list = todayGid.subList(finalI * limit, (finalI + 1) * limit);
}
if (CollectionUtils.isNotEmpty(list)) {
String[] strings = list.toArray(new String[0]);
Map<String, Object> android = menuService.getUserTags(strings);
List<UserMenusEntity> tagUser = menuService.getTagUser(android);
if (CollectionUtils.isNotEmpty(tagUser)) {
userMenusList.addAll(tagUser);
}
}
latch.countDown();
};
pool.execute(runnable);
}
latch.await();
userMenusService.batchInsert(userMenusList);
} catch (InterruptedException e) {
e.printStackTrace();
log.error("执行定时更新标签任务失败!");
}
}
// @Scheduled(cron = "* * * * * ?")
// public void updateUser() {
// System.out.println("你好" + System.currentTimeMillis());
// }
}
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://172.16.10.33:3306/png?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: wefaceweface
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
#Oracle需要打开注释
#validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
#login-username: admin
#login-password: admin
filter:
stat:
log-slow-sql: false
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
##多数据源的配置
#dynamic:
# datasource:
# slave1:
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# slave2:
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/renren_security
# username: renren
# password: 123456
\ No newline at end of file
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/renren_fast?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: renren
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
#Oracle需要打开注释
#validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
#login-username: admin
#login-password: admin
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
##多数据源的配置
#dynamic:
# datasource:
# slave1:
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# slave2:
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/renren_security
# username: renren
# password: 123456
\ No newline at end of file
#server:
# port: 8080
# Tomcat
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8080
connection-timeout: 5000ms
spring:
application:
name: service-web
server:
port: 8080
# 环境 dev|test|prod
profiles:
active: dev
# jackson时间格式化
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
enabled: true
mvc:
throw-exception-if-no-handler-found: true
getui:
apps: {
kkwj: {appkey: "vIBAFNAEk88qekbfS3miE8",mastersecret: "JojRk0duJd6oXiHIyFPqj",appId: "LhnWI1t7hc7ABsYbWokXD6",baseUrl: "http://api.getui.com/apiex.htm"},
kkmz: {appkey: "ywXeatlN0k5vDkHDQCqb87",mastersecret: "Jt4Rj3b3YA6qJkOmkN8HG3",appId: "739bQ9FSze62zjgXsZtAF4",baseUrl: "http://api.getui.com/apiex.htm"},
kksh: {appkey: "rdLx5zumRK7oEme8MheAh8",mastersecret: "mekLZ4frLu7RHtKsN9mQn",appId: "CYol79N33N71BV6dcjrqj3",baseUrl: "http://api.getui.com/apiex.htm"}
}
apps: {
kkwj: { appkey: "vIBAFNAEk88qekbfS3miE8",mastersecret: "JojRk0duJd6oXiHIyFPqj",appId: "LhnWI1t7hc7ABsYbWokXD6",baseUrl: "http://api.getui.com/apiex.htm" },
kkmz: { appkey: "ywXeatlN0k5vDkHDQCqb87",mastersecret: "Jt4Rj3b3YA6qJkOmkN8HG3",appId: "739bQ9FSze62zjgXsZtAF4",baseUrl: "http://api.getui.com/apiex.htm" },
kksh: { appkey: "rdLx5zumRK7oEme8MheAh8",mastersecret: "mekLZ4frLu7RHtKsN9mQn",appId: "CYol79N33N71BV6dcjrqj3",baseUrl: "http://api.getui.com/apiex.htm" }
}
#mybatis
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.weface.*.entity
global-config:
#数据库相关配置
db-config:
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: AUTO
logic-delete-value: -1
logic-not-delete-value: 0
banner: false
#原生配置
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
jdbc-type-for-null: 'null'
Spring Boot Version: ${spring-boot.version}
$$$ $ $$$
$$$ $$$ $$$
$$$$$$$$$$$$$$$$$$$$ $$$$$$$ $$$$$$$$$$$$ $$$
$$$$$$$$$$$$$$$$$$$$ $$$$$$$ $$$$$$$$$$$$ $$$
$$$ $$$ $$$ $$$ $$$ $$$
$$$ $$$ $$$ $$$ $$$ $$$ $$$
$$$$$$$$$$ $$$ $$$ $$$ $$$ $$$ $$$
$$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$
$$$ $$ $$$$$$ $$$$$$$ $$$ $$$
$$$ $ $$$ $$$$$ $ $$$$$$$ $$$ $$$ $$$
$$$$ $$$$ $$$$$$$ $$ $$$ $$ $$$ $$$
$$$$ $$$$ $$$$$$$ $$$ $$$$$$
--by Bootschool.net [chéng gōng]
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="TRACE" />
<!-- 开发、测试环境 -->
<springProfile name="dev,test">
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="INFO" />
<logger name="com.weface" level="DEBUG" />
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="org.springframework.web" level="ERROR"/>
<logger name="org.springboot.sample" level="ERROR" />
<logger name="com.weface" level="ERROR" />
</springProfile>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weface.dao.MenuTagsDao">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="com.weface.entity.MenuTagsEntity" id="menuTagsMap">
<result property="id" column="id"/>
<result property="levelFirst" column="level_first"/>
<result property="levelSecond" column="level_second"/>
<result property="levelThird" column="level_third"/>
<result property="code" column="code"/>
<result property="menuGrade" column="menu_grade"/>
<result property="weight" column="weight"/>
<result property="isDel" column="is_del"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weface.dao.TUserTagDao">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="com.weface.entity.TUserTagEntity" id="tUserTagMap">
<result property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="tel" column="tel"/>
<result property="gid" column="gid"/>
<collection property="list" ofType="com.weface.entity.MenuTagsEntity">
<id property="id" column="tagId"></id>
<result property="levelFirst" column="level_first"></result>
<result property="levelSecond" column="level_second"></result>
<result property="levelThird" column="level_third"></result>
<result property="code" column="code"></result>
<result property="menuGrade" column="menu_grade"></result>
<result property="weight" column="weight"></result>
</collection>
</resultMap>
<!-- 使用limit分页查询-->
<select id="findGidByLimit" resultType="string">
SELECT gid
FROM t_user_tag
WHERE gid IS NOT NULL LIMIT #{pageRecord}
, #{limit}
</select>
<!-- 查询当天更新用户gid-->
<select id="findTodayGid" resultType="string">
SELECT
gid
FROM
t_user_tag
WHERE
gid IS NOT NULL
AND TO_DAYS( save_date ) = TO_DAYS( NOW() )
</select>
<!-- 将公共片段抽取:只针对个别业务-->
<sql id="common">
SELECT ut.uid,
ut.gid,
mt.id AS tagId,
mt.level_first,
mt.level_second,
mt.level_third,
mt.`code`,
mt.menu_grade,
mt.weight
FROM t_user_tag ut
LEFT JOIN tb_user_menus um ON ut.uid = um.user_id
LEFT JOIN tb_menu_tags mt ON um.tags_id = mt.id
WHERE mt.level_first = "Android"
</sql>
<!-- 查询用户和标签信息-->
<select id="getUserAndTags" resultMap="tUserTagMap">
<include refid="common"/>
<if test="giUid !=null and giUid != ''">
AND ut.user_id LIKE CONCAT(CONCAT('%',#{giUid}),'%')
</if>
<if test="tag!=null and tag != ''">
AND ut.gid IN (
SELECT
ut.gid
FROM
t_user_tag ut
LEFT JOIN tb_user_menus um ON ut.uid = um.user_id
LEFT JOIN tb_menu_tags mt ON um.tags_id = mt.id
WHERE
mt.level_first = "Android"
AND mt.level_third LIKE CONCAT(CONCAT('%',#{tag}),'%')
)
</if>
</select>
<!-- 根据标签查询用户gid-->
<select id="getGidByTag" resultType="string">
SELECT DISTINCT
ut.gid
FROM
t_user_tag ut
LEFT JOIN tb_user_menus um ON ut.uid = um.user_id
LEFT JOIN tb_menu_tags mt ON um.tags_id = mt.id
WHERE
mt.level_first = "Android"
AND mt.level_third IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<!-- 根据gid查询用户标签-->
<select id="getTagByGid" resultMap="tUserTagMap">
<include refid="common"/>
AND ut.gid IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<!-- 查询所有用户标签管理数据-->
<select id="selectAllUserForTags" resultMap="tUserTagMap">
<include refid="common"/>
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weface.dao.UserMenusDao">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="com.weface.entity.UserMenusEntity" id="userMenusMap">
<result property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="tagsId" column="tags_id"/>
</resultMap>
<!--批量添加-->
<insert id="batchInsert" parameterType="java.util.List">
insert into tb_user_menus(id,user_id,tags_id)
values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.id},#{item.userId},#{item.tagsId})
</foreach>
</insert>
<!-- 批量删除-->
<delete id="deleteAll">
DELETE FROM tb_user_menus where user_id IN
<foreach collection="list" item="item" index="index" separator="," open="(" close=")">
#{item}
</foreach>
</delete>
</mapper>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment