通用mybatis-plus查询封装(QueryGenerator)

结果如下图所示

在这里插入图片描述

java类代码分别如下

1

package com.hdx.contractor.util.mybatis;import com.hdx.contractor.common.user.SecurityUser;
import com.hdx.contractor.common.user.UserDetail;
import com.hdx.contractor.util.query.oConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties;/*** mybatis拦截器,自动注入创建人、创建时间、修改人、修改时间* @Author: xu* @Date: 2024-10-06* @Version: V1.0**/
@Slf4j
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];String sqlId = mappedStatement.getId();log.debug("------sqlId------" + sqlId);SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();Object parameter = invocation.getArgs()[1];log.debug("------sqlCommandType------" + sqlCommandType);if (parameter == null) {return invocation.proceed();}if (SqlCommandType.INSERT == sqlCommandType) {UserDetail sysUser = this.getLoginUser();Field[] fields = oConvertUtils.getAllFields(parameter);for (Field field : fields) {log.debug("------field.name------" + field.getName());try {if ("createBy".equals(field.getName())) {field.setAccessible(true);Object localCreateBy = field.get(parameter);field.setAccessible(false);if (localCreateBy == null || "".equals(localCreateBy)) {if (sysUser != null) {// 登录人账号field.setAccessible(true);field.set(parameter, sysUser.getUsername());field.setAccessible(false);}}}if ("userId".equals(field.getName())) {field.setAccessible(true);Object localuserId = field.get(parameter);field.setAccessible(false);if (localuserId == null || "".equals(localuserId)) {if (sysUser != null) {// 登录人账号field.setAccessible(true);field.set(parameter, sysUser.getId());field.setAccessible(false);}}}// 注入创建时间if ("createTime".equals(field.getName())) {field.setAccessible(true);Object localCreateDate = field.get(parameter);field.setAccessible(false);if (localCreateDate == null || "".equals(localCreateDate)) {field.setAccessible(true);field.set(parameter, new Date());field.setAccessible(false);}}//注入部门编码if ("sysOrgCode".equals(field.getName())) {field.setAccessible(true);Object localSysOrgCode = field.get(parameter);field.setAccessible(false);if (localSysOrgCode == null || "".equals(localSysOrgCode)) {// 获取登录用户信息if (sysUser != null) {field.setAccessible(true);//field.set(parameter, sysUser.getOrgCode());field.setAccessible(false);}}}} catch (Exception e) {}}}if (SqlCommandType.UPDATE == sqlCommandType) {UserDetail sysUser = this.getLoginUser();Field[] fields = null;if (parameter instanceof ParamMap) {ParamMap<?> p = (ParamMap<?>) parameter;//update-begin-author:scott date:20190729 for:批量更新报错issues/IZA3Q--String et = "et";if (p.containsKey(et)) {parameter = p.get(et);} else {parameter = p.get("param1");}//update-end-author:scott date:20190729 for:批量更新报错issues/IZA3Q-//update-begin-author:scott date:20190729 for:更新指定字段时报错 issues/#516-if (parameter == null) {return invocation.proceed();}//update-end-author:scott date:20190729 for:更新指定字段时报错 issues/#516-fields = oConvertUtils.getAllFields(parameter);} else {fields = oConvertUtils.getAllFields(parameter);}for (Field field : fields) {log.debug("------field.name------" + field.getName());try {if ("updateBy".equals(field.getName())) {//获取登录用户信息if (sysUser != null) {// 登录账号field.setAccessible(true);field.set(parameter, sysUser.getUsername());field.setAccessible(false);}}if ("updateTime".equals(field.getName())) {field.setAccessible(true);field.set(parameter, new Date());field.setAccessible(false);}} catch (Exception e) {e.printStackTrace();}}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// TODO Auto-generated method stub}//update-begin--Author:scott  Date:20191213 for:关于使用Quzrtz 开启线程任务, #465/*** 获取登录用户* @return*/private UserDetail getLoginUser() {UserDetail sysUser = null;try {sysUser = SecurityUser.getUser();} catch (Exception e) {//e.printStackTrace();sysUser = null;}return sysUser;}//update-end--Author:scott  Date:20191213 for:关于使用Quzrtz 开启线程任务, #465}

2

package com.hdx.contractor.util.query;/*** @Description: 通用常量* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public interface CommonConstant {/*** 未知的*/String UNKNOWN = "unknown";/*** String 类型的空值*/String STRING_NULL = "null";/*** 字典翻译文本后缀*/String DICT_TEXT_SUFFIX = "_dictText";}

3

package com.hdx.contractor.util.query;import com.baomidou.mybatisplus.annotation.DbType;
import com.hdx.contractor.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;/*** @Description: 通用工具* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
@Slf4j
public class CommonUtils {/*** 文件名 正则字符串* 文件名支持的字符串:字母数字中文.-_()() 除此之外的字符将被删除*/private static String FILE_NAME_REGEX = "[^A-Za-z\\.\\(\\)\\-()\\_0-9\\u4e00-\\u9fa5]";/*** 当前系统数据库类型*/private static String DB_TYPE = "";private static DbType dbTypeEnum = null;/*** 全局获取平台数据库类型(作废了)** @return*/@Deprecatedpublic static String getDatabaseType() {if (oConvertUtils.isNotEmpty(DB_TYPE)) {return DB_TYPE;}DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);try {return getDatabaseTypeByDataSource(dataSource);} catch (SQLException e) {//e.printStackTrace();log.warn(e.getMessage(), e);return "";}}/*** 获取数据库类型** @param dataSource* @return* @throws SQLException*/private static String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException {if ("".equals(DB_TYPE)) {Connection connection = dataSource.getConnection();try {DatabaseMetaData md = connection.getMetaData();String dbType = md.getDatabaseProductName().toUpperCase();String sqlserver = "SQL SERVER";if (dbType.indexOf(DataBaseConstant.DB_TYPE_MYSQL) >= 0) {DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;} else if (dbType.indexOf(DataBaseConstant.DB_TYPE_ORACLE) >= 0 || dbType.indexOf(DataBaseConstant.DB_TYPE_DM) >= 0) {DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;} else if (dbType.indexOf(DataBaseConstant.DB_TYPE_SQLSERVER) >= 0 || dbType.indexOf(sqlserver) >= 0) {DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;} else if (dbType.indexOf(DataBaseConstant.DB_TYPE_POSTGRESQL) >= 0) {DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;} else if (dbType.indexOf(DataBaseConstant.DB_TYPE_MARIADB) >= 0) {DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;} else {log.error("数据库类型:[" + dbType + "]不识别!");//throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");}} catch (Exception e) {log.error(e.getMessage(), e);} finally {connection.close();}}return DB_TYPE;}}

4

package com.hdx.contractor.util.query;import com.hdx.contractor.util.SpringContextUtils;import java.util.List;/*** @ClassName: DataAutorUtils* @Description: 数据权限查询规则容器工具类* @Author: xu* @Date: 2024-10-06* @Version: V1.0* */
public class DataAutorUtils {public static final String MENU_DATA_AUTHOR_RULES = "MENU_DATA_AUTHOR_RULES";/*** 获取请求对应的数据权限规则* * @return*/@SuppressWarnings("unchecked")public static synchronized List<SysPermissionDataRuleModel> loadDataSearchConditon() {return (List<SysPermissionDataRuleModel>) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULES);}}

5

package com.hdx.contractor.util.query;
/*** 数据库上下文常量* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public interface DataBaseConstant {//*********数据库类型****************************************/**MYSQL数据库*/public static final String DB_TYPE_MYSQL = "MYSQL";/** ORACLE*/public static final String DB_TYPE_ORACLE = "ORACLE";/**达梦数据库*/public static final String DB_TYPE_DM = "DM";/**postgreSQL达梦数据库*/public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";/**sqlserver数据库*/public static final String DB_TYPE_SQLSERVER = "SQLSERVER";/**mariadb 数据库*/public static final String DB_TYPE_MARIADB = "MARIADB";/**DB2 数据库*/public static final String DB_TYPE_DB2 = "DB2";/**HSQL 数据库*/public static final String DB_TYPE_HSQL = "HSQL";//	// 数据库类型,对应 database_type 字典
//	public static final String DB_TYPE_MYSQL_NUM = "1";
//	public static final String DB_TYPE_MYSQL7_NUM = "6";
//	public static final String DB_TYPE_ORACLE_NUM = "2";
//	public static final String DB_TYPE_SQLSERVER_NUM = "3";
//	public static final String DB_TYPE_POSTGRESQL_NUM = "4";
//	public static final String DB_TYPE_MARIADB_NUM = "5";//*********系统上下文变量****************************************/*** 数据-所属机构编码*/public static final String SYS_ORG_CODE = "sysOrgCode";/*** 数据-所属机构编码*/public static final String SYS_ORG_CODE_TABLE = "sys_org_code";/*** 数据-所属机构编码*/public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode";/*** 数据-所属机构编码*/public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code";/*** 数据-系统用户编码(对应登录用户账号)*/public static final String SYS_USER_CODE = "sysUserCode";/*** 数据-系统用户编码(对应登录用户账号)*/public static final String SYS_USER_CODE_TABLE = "sys_user_code";/*** 登录用户真实姓名*/public static final String SYS_USER_NAME = "sysUserName";/*** 登录用户真实姓名*/public static final String SYS_USER_NAME_TABLE = "sys_user_name";/*** 系统日期"yyyy-MM-dd"*/public static final String SYS_DATE = "sysDate";/*** 系统日期"yyyy-MM-dd"*/public static final String SYS_DATE_TABLE = "sys_date";/*** 系统时间"yyyy-MM-dd HH:mm"*/public static final String SYS_TIME = "sysTime";/*** 系统时间"yyyy-MM-dd HH:mm"*/public static final String SYS_TIME_TABLE = "sys_time";/*** 数据-所属机构编码*/public static final String SYS_BASE_PATH = "sys_base_path";//*********系统上下文变量****************************************//*********系统建表标准字段****************************************/*** 创建者登录名称*/public static final String CREATE_BY_TABLE = "create_by";/*** 创建者登录名称*/public static final String CREATE_BY = "createBy";/*** 创建日期时间*/public static final String CREATE_TIME_TABLE = "create_time";/*** 创建日期时间*/public static final String CREATE_TIME = "createTime";/*** 更新用户登录名称*/public static final String UPDATE_BY_TABLE = "update_by";/*** 更新用户登录名称*/public static final String UPDATE_BY = "updateBy";/*** 更新日期时间*/public static final String UPDATE_TIME = "updateTime";/*** 更新日期时间*/public static final String UPDATE_TIME_TABLE = "update_time";/*** 业务流程状态*/public static final String BPM_STATUS = "bpmStatus";/*** 业务流程状态*/public static final String BPM_STATUS_TABLE = "bpm_status";//*********系统建表标准字段****************************************/*** 租户ID 实体字段名*/String TENANT_ID = "tenantId";/*** 租户ID 数据库字段名*/String TENANT_ID_TABLE = "tenant_id";/*** sql语句 where*/String SQL_WHERE = "where";/*** sql语句 asc*/String SQL_ASC = "asc";/*** sqlserver数据库,中间有空格*/String DB_TYPE_SQL_SERVER_BLANK = "sql server";
}

6

package com.hdx.contractor.util.query;/*** 查询链接规则* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public enum MatchTypeEnum {/**查询链接规则 AND*/AND("AND"),/**查询链接规则 OR*/OR("OR");private String value;MatchTypeEnum(String value) {this.value = value;}public String getValue() {return value;}public static MatchTypeEnum getByValue(Object value) {if (oConvertUtils.isEmpty(value)) {return null;}return getByValue(value.toString());}public static MatchTypeEnum getByValue(String value) {if (oConvertUtils.isEmpty(value)) {return null;}for (MatchTypeEnum val : values()) {if (val.getValue().toLowerCase().equals(value.toLowerCase())) {return val;}}return null;}
}

7

package com.hdx.contractor.util.query;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Date;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/**** @Author: xu* @Date: 2024-10-06* @Version: V1.0**/
@Slf4j
public class oConvertUtils {public static boolean isEmpty(Object object) {if (object == null) {return (true);}if ("".equals(object)) {return (true);}if (CommonConstant.STRING_NULL.equals(object)) {return (true);}return (false);}public static boolean isNotEmpty(Object object) {if (object != null && !"".equals(object) && !object.equals(CommonConstant.STRING_NULL)) {return (true);}return (false);}public static String decode(String strIn, String sourceCode, String targetCode) {String temp = code2code(strIn, sourceCode, targetCode);return temp;}@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")public static String StrToUTF(String strIn, String sourceCode, String targetCode) {strIn = "";try {strIn = new String(strIn.getBytes("ISO-8859-1"), "GBK");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return strIn;}private static String code2code(String strIn, String sourceCode, String targetCode) {String strOut = null;if (strIn == null || "".equals(strIn.trim())) {return strIn;}try {byte[] b = strIn.getBytes(sourceCode);for (int i = 0; i < b.length; i++) {System.out.print(b[i] + "  ");}strOut = new String(b, targetCode);} catch (Exception e) {e.printStackTrace();return null;}return strOut;}public static int getInt(String s, int defval) {if (s == null || s == "") {return (defval);}try {return (Integer.parseInt(s));} catch (NumberFormatException e) {return (defval);}}public static int getInt(String s) {if (s == null || s == "") {return 0;}try {return (Integer.parseInt(s));} catch (NumberFormatException e) {return 0;}}public static int getInt(String s, Integer df) {if (s == null || s == "") {return df;}try {return (Integer.parseInt(s));} catch (NumberFormatException e) {return 0;}}public static Integer[] getInts(String[] s) {if (s == null) {return null;}Integer[] integer = new Integer[s.length];for (int i = 0; i < s.length; i++) {integer[i] = Integer.parseInt(s[i]);}return integer;}public static double getDouble(String s, double defval) {if (s == null || s == "") {return (defval);}try {return (Double.parseDouble(s));} catch (NumberFormatException e) {return (defval);}}public static double getDou(Double s, double defval) {if (s == null) {return (defval);}return s;}/*public static Short getShort(String s) {if (StringUtil.isNotEmpty(s)) {return (Short.parseShort(s));} else {return null;}}*/public static int getInt(Object object, int defval) {if (isEmpty(object)) {return (defval);}try {return (Integer.parseInt(object.toString()));} catch (NumberFormatException e) {return (defval);}}public static Integer getInt(Object object) {if (isEmpty(object)) {return null;}try {return (Integer.parseInt(object.toString()));} catch (NumberFormatException e) {return null;}}public static int getInt(BigDecimal s, int defval) {if (s == null) {return (defval);}return s.intValue();}public static Integer[] getIntegerArry(String[] object) {int len = object.length;Integer[] result = new Integer[len];try {for (int i = 0; i < len; i++) {result[i] = new Integer(object[i].trim());}return result;} catch (NumberFormatException e) {return null;}}public static String getString(String s) {return (getString(s, ""));}public static String getString(Object object) {if (isEmpty(object)) {return "";}return (object.toString().trim());}public static String getString(int i) {return (String.valueOf(i));}public static String getString(float i) {return (String.valueOf(i));}public static String getString(String s, String defval) {if (isEmpty(s)) {return (defval);}return (s.trim());}public static String getString(Object s, String defval) {if (isEmpty(s)) {return (defval);}return (s.toString().trim());}public static long stringToLong(String str) {Long test = new Long(0);try {test = Long.valueOf(str);} catch (Exception e) {}return test.longValue();}/*** 获取本机IP*/public static String getIp() {String ip = null;try {InetAddress address = InetAddress.getLocalHost();ip = address.getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}return ip;}/*** 判断一个类是否为基本数据类型。* * @param clazz*            要判断的类。* @return true 表示为基本数据类型。*/private static boolean isBaseDataType(Class clazz) throws Exception {return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz.isPrimitive());}/*** @param request*            IP* @return IP Address*/public static String getIpAddrByRequest(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}/*** @return 本机IP* @throws SocketException*/public static String getRealIp() throws SocketException {// 本地IP,如果没有配置外网IP则返回它String localip = null;// 外网IPString netip = null;Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();InetAddress ip = null;// 是否找到外网IPboolean finded = false;while (netInterfaces.hasMoreElements() && !finded) {NetworkInterface ni = netInterfaces.nextElement();Enumeration<InetAddress> address = ni.getInetAddresses();while (address.hasMoreElements()) {ip = address.nextElement();// 外网IPif (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {netip = ip.getHostAddress();finded = true;break;} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IPlocalip = ip.getHostAddress();}}}if (netip != null && !"".equals(netip)) {return netip;} else {return localip;}}/*** java去除字符串中的空格、回车、换行符、制表符* * @param str* @return*/public static String replaceBlank(String str) {String dest = "";if (str != null) {String reg = "\\s*|\t|\r|\n";Pattern p = Pattern.compile(reg);Matcher m = p.matcher(str);dest = m.replaceAll("");}return dest;}/*** 判断元素是否在数组内* * @param substring* @param source* @return*/public static boolean isIn(String substring, String[] source) {if (source == null || source.length == 0) {return false;}for (int i = 0; i < source.length; i++) {String aSource = source[i];if (aSource.equals(substring)) {return true;}}return false;}/*** 获取Map对象*/public static Map<Object, Object> getHashMap() {return new HashMap<>(5);}/*** SET转换MAP* * @param str* @return*/public static Map<Object, Object> setToMap(Set<Object> setobj) {Map<Object, Object> map = getHashMap();for (Iterator iterator = setobj.iterator(); iterator.hasNext();) {Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) iterator.next();map.put(entry.getKey().toString(), entry.getValue() == null ? "" : entry.getValue().toString().trim());}return map;}public static boolean isInnerIp(String ipAddress) {boolean isInnerIp = false;long ipNum = getIpNum(ipAddress);/*** 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 当然,还有127这个网段是环回地址**/long aBegin = getIpNum("10.0.0.0");long aEnd = getIpNum("10.255.255.255");long bBegin = getIpNum("172.16.0.0");long bEnd = getIpNum("172.31.255.255");long cBegin = getIpNum("192.168.0.0");long cEnd = getIpNum("192.168.255.255");String localIp = "127.0.0.1";isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || localIp.equals(ipAddress);return isInnerIp;}private static long getIpNum(String ipAddress) {String[] ip = ipAddress.split("\\.");long a = Integer.parseInt(ip[0]);long b = Integer.parseInt(ip[1]);long c = Integer.parseInt(ip[2]);long d = Integer.parseInt(ip[3]);long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;return ipNum;}private static boolean isInner(long userIp, long begin, long end) {return (userIp >= begin) && (userIp <= end);}/*** 将下划线大写方式命名的字符串转换为驼峰式。* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>* 例如:hello_world->helloWorld* * @param name*            转换前的下划线大写方式命名的字符串* @return 转换后的驼峰式命名的字符串*/public static String camelName(String name) {StringBuilder result = new StringBuilder();// 快速检查if (name == null || name.isEmpty()) {// 没必要转换return "";} else if (!name.contains(SymbolConstant.UNDERLINE)) {// 不含下划线,仅将首字母小写//update-begin--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能//update-begin--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();//update-end--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能}// 用下划线将原始字符串分割String[] camels = name.split("_");for (String camel : camels) {// 跳过原始字符串中开头、结尾的下换线或双重下划线if (camel.isEmpty()) {continue;}// 处理真正的驼峰片段if (result.length() == 0) {// 第一个驼峰片段,全部字母都小写result.append(camel.toLowerCase());} else {// 其他的驼峰片段,首字母大写result.append(camel.substring(0, 1).toUpperCase());result.append(camel.substring(1).toLowerCase());}}return result.toString();}/*** 将下划线大写方式命名的字符串转换为驼峰式。* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>* 例如:hello_world,test_id->helloWorld,testId* * @param name*            转换前的下划线大写方式命名的字符串* @return 转换后的驼峰式命名的字符串*/public static String camelNames(String names) {if(names==null||"".equals(names)){return null;}StringBuffer sf = new StringBuffer();String[] fs = names.split(",");for (String field : fs) {field = camelName(field);sf.append(field + ",");}String result = sf.toString();return result.substring(0, result.length() - 1);}//update-begin--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能/*** 将下划线大写方式命名的字符串转换为驼峰式。(首字母写)* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>* 例如:hello_world->HelloWorld* * @param name*            转换前的下划线大写方式命名的字符串* @return 转换后的驼峰式命名的字符串*/public static String camelNameCapFirst(String name) {StringBuilder result = new StringBuilder();// 快速检查if (name == null || name.isEmpty()) {// 没必要转换return "";} else if (!name.contains(SymbolConstant.UNDERLINE)) {// 不含下划线,仅将首字母小写return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();}// 用下划线将原始字符串分割String[] camels = name.split("_");for (String camel : camels) {// 跳过原始字符串中开头、结尾的下换线或双重下划线if (camel.isEmpty()) {continue;}// 其他的驼峰片段,首字母大写result.append(camel.substring(0, 1).toUpperCase());result.append(camel.substring(1).toLowerCase());}return result.toString();}//update-end--Author:zhoujf  Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能/*** 将驼峰命名转化成下划线* @param para* @return*/public static String camelToUnderline(String para){int length = 3;if(para.length()<length){return para.toLowerCase(); }StringBuilder sb=new StringBuilder(para);//定位int temp=0;//从第三个字符开始 避免命名不规范 for(int i=2;i<para.length();i++){if(Character.isUpperCase(para.charAt(i))){sb.insert(i+temp, "_");temp+=1;}}return sb.toString().toLowerCase(); }/*** 随机数* @param place 定义随机数的位数*/public static String randomGen(int place) {String base = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789";StringBuffer sb = new StringBuffer();Random rd = new Random();for(int i=0;i<place;i++) {sb.append(base.charAt(rd.nextInt(base.length())));}return sb.toString();}/*** 获取类的所有属性,包括父类* * @param object* @return*/public static Field[] getAllFields(Object object) {Class<?> clazz = object.getClass();List<Field> fieldList = new ArrayList<>();while (clazz != null) {fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));clazz = clazz.getSuperclass();}Field[] fields = new Field[fieldList.size()];fieldList.toArray(fields);return fields;}/*** 将map的key全部转成小写* @param list* @return*/public static List<Map<String, Object>> toLowerCasePageList(List<Map<String, Object>> list){List<Map<String, Object>> select = new ArrayList<>();for (Map<String, Object> row : list) {Map<String, Object> resultMap = new HashMap<>(5);Set<String> keySet = row.keySet(); for (String key : keySet) { String newKey = key.toLowerCase(); resultMap.put(newKey, row.get(key)); }select.add(resultMap);}return select;}/*** 将entityList转换成modelList* @param fromList* @param tClass* @param <F>* @param <T>* @return*/public static<F,T> List<T> entityListToModelList(List<F> fromList, Class<T> tClass){if(fromList == null || fromList.isEmpty()){return null;}List<T> tList = new ArrayList<>();for(F f : fromList){T t = entityToModel(f, tClass);tList.add(t);}return tList;}public static<F,T> T entityToModel(F entity, Class<T> modelClass) {log.debug("entityToModel : Entity属性的值赋值到Model");Object model = null;if (entity == null || modelClass ==null) {return null;}try {model = modelClass.newInstance();} catch (InstantiationException e) {log.error("entityToModel : 实例化异常", e);} catch (IllegalAccessException e) {log.error("entityToModel : 安全权限异常", e);}BeanUtils.copyProperties(entity, model);return (T)model;}/*** 判断 list 是否为空** @param list* @return true or false* list == null		: true* list.size() == 0	: true*/public static boolean listIsEmpty(Collection list) {return (list == null || list.size() == 0);}/*** 判断 list 是否不为空** @param list* @return true or false* list == null		: false* list.size() == 0	: false*/public static boolean listIsNotEmpty(Collection list) {return !listIsEmpty(list);}}

8

package com.hdx.contractor.util.query;import java.io.Serializable;/*** @Description: QueryCondition* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public class QueryCondition implements Serializable {private static final long serialVersionUID = 4740166316629191651L;private String field;/** 组件的类型(例如:input、select、radio) */private String type;/*** 对应的数据库字段的类型* 支持:int、bigDecimal、short、long、float、double、boolean*/private String dbType;private String rule;private String val;public String getField() {return field;}public void setField(String field) {this.field = field;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getDbType() {return dbType;}public void setDbType(String dbType) {this.dbType = dbType;}public String getRule() {return rule;}public void setRule(String rule) {this.rule = rule;}public String getVal() {return val;}public void setVal(String val) {this.val = val;}@Overridepublic String toString(){StringBuffer sb =new StringBuffer();if(field == null || "".equals(field)){return "";}sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.dbType).append(" ").append(this.val);return sb.toString();}
}

9

package com.hdx.contractor.util.query;import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.util.NumberUtils;import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;/*** @Description: 查询生成器* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
@Slf4j
public class QueryGenerator {public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN";private static final String BEGIN = "_begin";private static final String END = "_end";/*** 数字类型字段,拼接此后缀 接受多值参数*/private static final String MULTI = "_MultiString";private static final String STAR = "*";private static final String COMMA = ",";/*** 查询 逗号转义符 相当于一个逗号【作废】*/public static final String QUERY_COMMA_ESCAPE = "++";private static final String NOT_EQUAL = "!";/*** 页面带有规则值查询,空格作为分隔符*/private static final String QUERY_SEPARATE_KEYWORD = " ";/*** 高级查询前端传来的参数名*/private static final String SUPER_QUERY_PARAMS = "superQueryParams";/*** 高级查询前端传来的拼接方式参数名*/private static final String SUPER_QUERY_MATCH_TYPE = "superQueryMatchType";/*** 单引号*/public static final String SQL_SQ = "'";/*** 排序列*/private static final String ORDER_COLUMN = "column";/*** 排序方式*/private static final String ORDER_TYPE = "order";private static final String ORDER_TYPE_ASC = "ASC";/*** mysql 模糊查询之特殊字符下划线 (_、\)*/public static final String LIKE_MYSQL_SPECIAL_STRS = "_,%";/*** 日期格式化yyyy-MM-dd*/public static final String YYYY_MM_DD = "yyyy-MM-dd";/*** to_date*/public static final String TO_DATE = "to_date";/*** 时间格式化*/private static final ThreadLocal<SimpleDateFormat> LOCAL = new ThreadLocal<SimpleDateFormat>();private static SimpleDateFormat getTime() {SimpleDateFormat time = LOCAL.get();if (time == null) {time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");LOCAL.set(time);}return time;}/*** 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成** @param searchObj    查询实体* @param parameterMap request.getParameterMap()* @return QueryWrapper实例*/public static <T> QueryWrapper<T> initQueryWrapper(T searchObj, Map<String, String[]> parameterMap) {long start = System.currentTimeMillis();QueryWrapper<T> queryWrapper = new QueryWrapper<T>();installMplus(queryWrapper, searchObj, parameterMap);log.debug("---查询条件构造器初始化完成,耗时:" + (System.currentTimeMillis() - start) + "毫秒----");return queryWrapper;}/*** 组装Mybatis Plus 查询条件* <p>使用此方法 需要有如下几点注意:* <br>1.使用QueryWrapper 而非LambdaQueryWrapper;* <br>2.实例化QueryWrapper时不可将实体传入参数* <br>错误示例:如QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>(jeecgDemo);* <br>正确示例:QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>();* <br>3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例*/private static void installMplus(QueryWrapper<?> queryWrapper, Object searchObj, Map<String, String[]> parameterMap) {/** 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code}但是不支持在自定义SQL中写orgCode in #{sys_org_code} 当一个人只有一个部门 就直接配置等于条件: orgCode 等于 #{sys_org_code} 或者配置自定义SQL: orgCode = '#{sys_org_code}'*///区间条件组装 模糊查询 高级查询组装 简单排序 权限查询PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(searchObj);Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();//权限规则自定义SQL表达式for (String c : ruleMap.keySet()) {if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {queryWrapper.and(i -> i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));}}String name, type, column;// update-begin--Author:taoyan  Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------//定义实体字段和数据库字段名称的映射 高级查询中 只能获取实体字段 如果设置TableField注解 那么查询条件会出问题Map<String, String> fieldColumnMap = new HashMap<>(5);for (int i = 0; i < origDescriptors.length; i++) {//aliasName = origDescriptors[i].getName();  mybatis  不存在实体属性 不用处理别名的情况name = origDescriptors[i].getName();type = origDescriptors[i].getPropertyType().toString();try {if (judgedIsUselessField(name) || !PropertyUtils.isReadable(searchObj, name)) {continue;}Object value = PropertyUtils.getSimpleProperty(searchObj, name);column = getTableFieldName(searchObj.getClass(), name);if (column == null) {//column为null只有一种情况 那就是 添加了注解@TableField(exist = false) 后续都不用处理了continue;}fieldColumnMap.put(name, column);//数据权限查询if (ruleMap.containsKey(name)) {addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper);}//区间查询doIntervalQuery(queryWrapper, parameterMap, type, name, column);//判断单值  参数带不同标识字符串 走不同的查询//TODO 这种前后带逗号的支持分割后模糊查询(多选字段查询生效) 示例:,1,3,if (null != value && value.toString().startsWith(COMMA) && value.toString().endsWith(COMMA)) {String multiLikeval = value.toString().replace(",,", COMMA);String[] vals = multiLikeval.substring(1, multiLikeval.length()).split(COMMA);final String field = oConvertUtils.camelToUnderline(column);if (vals.length > 1) {queryWrapper.and(j -> {log.info("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);j = j.like(field, vals[0]);for (int k = 1; k < vals.length; k++) {j = j.or().like(field, vals[k]);log.info("---查询过滤器,Query规则 .or()---field:{}, rule:{}, value:{}", field, "like", vals[k]);}//return j;});} else {log.info("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);queryWrapper.and(j -> j.like(field, vals[0]));}} else {//根据参数值带什么关键字符串判断走什么类型的查询QueryRuleEnum rule = convert2Rule(value);value = replaceValue(rule, value);// add -begin 添加判断为字符串时设为全模糊查询//if( (rule==null || QueryRuleEnum.EQ.equals(rule)) && "class java.lang.String".equals(type)) {// 可以设置左右模糊或全模糊,因人而异//rule = QueryRuleEnum.LIKE;//}// add -end 添加判断为字符串时设为全模糊查询addEasyQuery(queryWrapper, column, rule, value);}} catch (Exception e) {log.error(e.getMessage(), e);}}// 排序逻辑 处理doMultiFieldsOrder(queryWrapper, parameterMap, fieldColumnMap);//高级查询doSuperQuery(queryWrapper, parameterMap, fieldColumnMap);// update-end--Author:taoyan  Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------}/*** 区间查询** @param queryWrapper query对象* @param parameterMap 参数map* @param type         字段类型* @param filedName    字段名称* @param columnName   列名称*/private static void doIntervalQuery(QueryWrapper<?> queryWrapper, Map<String, String[]> parameterMap, String type, String filedName, String columnName) throws ParseException {// 添加 判断是否有区间值String endValue = null, beginValue = null;if (parameterMap != null && parameterMap.containsKey(filedName + BEGIN)) {beginValue = parameterMap.get(filedName + BEGIN)[0].trim();addQueryByRule(queryWrapper, columnName, type, beginValue, QueryRuleEnum.GE);}if (parameterMap != null && parameterMap.containsKey(filedName + END)) {endValue = parameterMap.get(filedName + END)[0].trim();addQueryByRule(queryWrapper, columnName, type, endValue, QueryRuleEnum.LE);}//多值查询if (parameterMap != null && parameterMap.containsKey(filedName + MULTI)) {endValue = parameterMap.get(filedName + MULTI)[0].trim();addQueryByRule(queryWrapper, columnName.replace(MULTI, ""), type, endValue, QueryRuleEnum.IN);}}private static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper, Map<String, String[]> parameterMap, Map<String, String> fieldColumnMap) {Set<String> allFields = fieldColumnMap.keySet();String column = null, order = null;if (parameterMap != null && parameterMap.containsKey(ORDER_COLUMN)) {column = parameterMap.get(ORDER_COLUMN)[0];}if (parameterMap != null && parameterMap.containsKey(ORDER_TYPE)) {order = parameterMap.get(ORDER_TYPE)[0];}log.info("排序规则>>列:" + column + ",排序方式:" + order);//update-begin-author:scott date:2022-11-07 for:避免用户自定义表无默认字段{创建时间},导致排序报错//TODO 避免用户自定义表无默认字段创建时间,导致排序报错if (DataBaseConstant.CREATE_TIME.equals(column) && !fieldColumnMap.containsKey(DataBaseConstant.CREATE_TIME)) {column = "id";log.warn("检测到实体里没有字段createTime,改成采用ID排序!");}//update-end-author:scott date:2022-11-07 for:避免用户自定义表无默认字段{创建时间},导致排序报错if (oConvertUtils.isNotEmpty(column) && oConvertUtils.isNotEmpty(order)) {//字典字段,去掉字典翻译文本后缀if (column.endsWith(CommonConstant.DICT_TEXT_SUFFIX)) {column = column.substring(0, column.lastIndexOf(CommonConstant.DICT_TEXT_SUFFIX));}//update-begin-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效//判断column是不是当前实体的log.debug("当前字段有:" + allFields);if (!allColumnExist(column, allFields)) {throw new RuntimeException("请注意,将要排序的列字段不存在:" + column);}//update-end-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效//update-begin-author:scott date:2022-10-10 for:【jeecg-boot/issues/I5FJU6】doMultiFieldsOrder() 多字段排序方法存在问题//多字段排序方法没有读取 MybatisPlus 注解 @TableField 里 value 的值if (column.contains(",")) {List<String> columnList = Arrays.asList(column.split(","));String columnStrNew = columnList.stream().map(c -> fieldColumnMap.get(c)).collect(Collectors.joining(","));if (oConvertUtils.isNotEmpty(columnStrNew)) {column = columnStrNew;}} else {column = fieldColumnMap.get(column);}//update-end-author:scott date:2022-10-10 for:【jeecg-boot/issues/I5FJU6】doMultiFieldsOrder() 多字段排序方法存在问题//SQL注入checkSqlInjectionUtil.filterContent(column);//update-begin--Author:scott  Date:20210531 for:36 多条件排序无效问题修正-------// 排序规则修改// 将现有排序 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1,column2 desc"// 修改为 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1 desc,column2 desc"if (order.toUpperCase().indexOf(ORDER_TYPE_ASC) >= 0) {//queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(column));String columnStr = oConvertUtils.camelToUnderline(column);String[] columnArray = columnStr.split(",");queryWrapper.orderByAsc(Arrays.asList(columnArray));} else {//queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(column));String columnStr = oConvertUtils.camelToUnderline(column);String[] columnArray = columnStr.split(",");queryWrapper.orderByDesc(Arrays.asList(columnArray));}//update-end--Author:scott  Date:20210531 for:36 多条件排序无效问题修正-------}}//update-begin-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效/*** 多字段排序 判断所传字段是否存在** @return*/private static boolean allColumnExist(String columnStr, Set<String> allFields) {boolean exist = true;if (columnStr.indexOf(COMMA) >= 0) {String[] arr = columnStr.split(COMMA);for (String column : arr) {if (!allFields.contains(column)) {exist = false;break;}}} else {exist = allFields.contains(columnStr);}return exist;}//update-end-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效/*** 高级查询** @param queryWrapper   查询对象* @param parameterMap   参数对象* @param fieldColumnMap 实体字段和数据库列对应的map*/private static void doSuperQuery(QueryWrapper<?> queryWrapper, Map<String, String[]> parameterMap, Map<String, String> fieldColumnMap) {if (parameterMap != null && parameterMap.containsKey(SUPER_QUERY_PARAMS)) {String superQueryParams = parameterMap.get(SUPER_QUERY_PARAMS)[0];String superQueryMatchType = parameterMap.get(SUPER_QUERY_MATCH_TYPE) != null ? parameterMap.get(SUPER_QUERY_MATCH_TYPE)[0] : MatchTypeEnum.AND.getValue();MatchTypeEnum matchType = MatchTypeEnum.getByValue(superQueryMatchType);// update-begin--Author:sunjianlei  Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------try {superQueryParams = URLDecoder.decode(superQueryParams, "UTF-8");List<QueryCondition> conditions = JSON.parseArray(superQueryParams, QueryCondition.class);if (conditions == null || conditions.size() == 0) {return;}// update-begin-author:sunjianlei date:20220119 for: 【JTC-573】 过滤空条件查询,防止 sql 拼接多余的 andList<QueryCondition> filterConditions = conditions.stream().filter(rule -> oConvertUtils.isNotEmpty(rule.getField())&& oConvertUtils.isNotEmpty(rule.getRule())&& oConvertUtils.isNotEmpty(rule.getVal())).collect(Collectors.toList());if (filterConditions.size() == 0) {return;}// update-end-author:sunjianlei date:20220119 for: 【JTC-573】 过滤空条件查询,防止 sql 拼接多余的 andlog.info("---高级查询参数-->" + filterConditions);queryWrapper.and(andWrapper -> {for (int i = 0; i < filterConditions.size(); i++) {QueryCondition rule = filterConditions.get(i);if (oConvertUtils.isNotEmpty(rule.getField())&& oConvertUtils.isNotEmpty(rule.getRule())&& oConvertUtils.isNotEmpty(rule.getVal())) {log.debug("SuperQuery ==> " + rule.toString());//update-begin-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错Object queryValue = rule.getVal();if ("date".equals(rule.getType())) {queryValue = str2Date(rule.getVal(), date_sdf.get());} else if ("datetime".equals(rule.getType())) {queryValue = str2Date(rule.getVal(), datetimeFormat.get());}// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----String dbType = rule.getDbType();if (oConvertUtils.isNotEmpty(dbType)) {try {String valueStr = String.valueOf(queryValue);switch (dbType.toLowerCase().trim()) {case "int":queryValue = Integer.parseInt(valueStr);break;case "bigdecimal":queryValue = new BigDecimal(valueStr);break;case "short":queryValue = Short.parseShort(valueStr);break;case "long":queryValue = Long.parseLong(valueStr);break;case "float":queryValue = Float.parseFloat(valueStr);break;case "double":queryValue = Double.parseDouble(valueStr);break;case "boolean":queryValue = Boolean.parseBoolean(valueStr);break;default:}} catch (Exception e) {log.error("高级查询值转换失败:", e);}}// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----addEasyQuery(andWrapper, fieldColumnMap.get(rule.getField()), QueryRuleEnum.getByValue(rule.getRule()), queryValue);//update-end-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错// 如果拼接方式是OR,就拼接ORif (MatchTypeEnum.OR == matchType && i < (filterConditions.size() - 1)) {andWrapper.or();}}}//return andWrapper;});} catch (UnsupportedEncodingException e) {log.error("--高级查询参数转码失败:" + superQueryParams, e);} catch (Exception e) {log.error("--高级查询拼接失败:" + e.getMessage());e.printStackTrace();}// update-end--Author:sunjianlei  Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------}//log.info(" superQuery getCustomSqlSegment: "+ queryWrapper.getCustomSqlSegment());}/*** 根据所传的值 转化成对应的比较方式* 支持><= like in !** @param value* @return*/public static QueryRuleEnum convert2Rule(Object value) {// 避免空数据// update-begin-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常if (value == null) {return QueryRuleEnum.EQ;}String val = (value + "").toString().trim();if (val.length() == 0) {return QueryRuleEnum.EQ;}// update-end-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常QueryRuleEnum rule = null;//update-begin--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------//TODO 此处规则,只适用于 le lt ge gt// step 2 .>= =<int length2 = 2;int length3 = 3;if (rule == null && val.length() >= length3) {if (QUERY_SEPARATE_KEYWORD.equals(val.substring(length2, length3))) {rule = QueryRuleEnum.getByValue(val.substring(0, 2));}}// step 1 .> <if (rule == null && val.length() >= length2) {if (QUERY_SEPARATE_KEYWORD.equals(val.substring(1, length2))) {rule = QueryRuleEnum.getByValue(val.substring(0, 1));}}//update-end--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284---------------------// step 3 like//update-begin-author:taoyan for: /issues/3382 默认带*就走模糊,但是如果只有一个*,那么走等于查询if (rule == null && val.equals(STAR)) {rule = QueryRuleEnum.EQ;}//update-end-author:taoyan for: /issues/3382  默认带*就走模糊,但是如果只有一个*,那么走等于查询if (rule == null && val.contains(STAR)) {if (val.startsWith(STAR) && val.endsWith(STAR)) {rule = QueryRuleEnum.LIKE;} else if (val.startsWith(STAR)) {rule = QueryRuleEnum.LEFT_LIKE;} else if (val.endsWith(STAR)) {rule = QueryRuleEnum.RIGHT_LIKE;}}// step 4 inif (rule == null && val.contains(COMMA)) {//TODO in 查询这里应该有个bug  如果一字段本身就是多选 此时用in查询 未必能查询出来rule = QueryRuleEnum.IN;}// step 5 !=if (rule == null && val.startsWith(NOT_EQUAL)) {rule = QueryRuleEnum.NE;}// step 6 xx+xx+xx 这种情况适用于如果想要用逗号作精确查询 但是系统默认逗号走in 所以可以用++替换【此逻辑作废】if (rule == null && val.indexOf(QUERY_COMMA_ESCAPE) > 0) {rule = QueryRuleEnum.EQ_WITH_ADD;}//update-begin--Author:taoyan  Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------//特殊处理:Oracle的表达式to_date('xxx','yyyy-MM-dd')含有逗号,会被识别为in查询,转为等于查询if (rule == QueryRuleEnum.IN && val.indexOf(YYYY_MM_DD) >= 0 && val.indexOf(TO_DATE) >= 0) {rule = QueryRuleEnum.EQ;}//update-end--Author:taoyan  Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------return rule != null ? rule : QueryRuleEnum.EQ;}/*** 替换掉关键字字符** @param rule* @param value* @return*/private static Object replaceValue(QueryRuleEnum rule, Object value) {if (rule == null) {return null;}if (!(value instanceof String)) {return value;}String val = (value + "").toString().trim();//update-begin-author:taoyan date:20220302 for: 查询条件的值为等号(=)bug #3443if (QueryRuleEnum.EQ.getValue().equals(val)) {return val;}//update-end-author:taoyan date:20220302 for: 查询条件的值为等号(=)bug #3443if (rule == QueryRuleEnum.LIKE) {value = val.substring(1, val.length() - 1);//mysql 模糊查询之特殊字符下划线 (_、\)value = specialStrConvert(value.toString());} else if (rule == QueryRuleEnum.LEFT_LIKE || rule == QueryRuleEnum.NE) {value = val.substring(1);//mysql 模糊查询之特殊字符下划线 (_、\)value = specialStrConvert(value.toString());} else if (rule == QueryRuleEnum.RIGHT_LIKE) {value = val.substring(0, val.length() - 1);//mysql 模糊查询之特殊字符下划线 (_、\)value = specialStrConvert(value.toString());} else if (rule == QueryRuleEnum.IN) {value = val.split(",");} else if (rule == QueryRuleEnum.EQ_WITH_ADD) {value = val.replaceAll("\\+\\+", COMMA);} else {//update-begin--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------if (val.startsWith(rule.getValue())) {//TODO 此处逻辑应该注释掉-> 如果查询内容中带有查询匹配规则符号,就会被截取的(比如:>=您好)value = val.replaceFirst(rule.getValue(), "");} else if (val.startsWith(rule.getCondition() + QUERY_SEPARATE_KEYWORD)) {value = val.replaceFirst(rule.getCondition() + QUERY_SEPARATE_KEYWORD, "").trim();}//update-end--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------}return value;}private static void addQueryByRule(QueryWrapper<?> queryWrapper, String name, String type, String value, QueryRuleEnum rule) throws ParseException {if (oConvertUtils.isNotEmpty(value)) {//update-begin--Author:sunjianlei  Date:20220104 for:【JTC-409】修复逗号分割情况下没有转换类型,导致类型严格的数据库查询报错 -------------------// 针对数字类型字段,多值查询if (value.contains(COMMA)) {Object[] temp = Arrays.stream(value.split(COMMA)).map(v -> {try {return QueryGenerator.parseByType(v, type, rule);} catch (ParseException e) {e.printStackTrace();return v;}}).toArray();addEasyQuery(queryWrapper, name, rule, temp);return;}Object temp = QueryGenerator.parseByType(value, type, rule);addEasyQuery(queryWrapper, name, rule, temp);//update-end--Author:sunjianlei  Date:20220104 for:【JTC-409】修复逗号分割情况下没有转换类型,导致类型严格的数据库查询报错 -------------------}}/*** 根据类型转换给定的值** @param value* @param type* @param rule* @return* @throws ParseException*/private static Object parseByType(String value, String type, QueryRuleEnum rule) throws ParseException {Object temp;switch (type) {case "class java.lang.Integer":temp = Integer.parseInt(value);break;case "class java.math.BigDecimal":temp = new BigDecimal(value);break;case "class java.lang.Short":temp = Short.parseShort(value);break;case "class java.lang.Long":temp = Long.parseLong(value);break;case "class java.lang.Float":temp = Float.parseFloat(value);break;case "class java.lang.Double":temp = Double.parseDouble(value);break;case "class java.util.Date":temp = getDateQueryByRule(value, rule);break;default:temp = value;break;}return temp;}/*** 获取日期类型的值** @param value* @param rule* @return* @throws ParseException*/private static Date getDateQueryByRule(String value, QueryRuleEnum rule) throws ParseException {Date date = null;int length = 10;if (value.length() == length) {if (rule == QueryRuleEnum.GE) {//比较大于date = getTime().parse(value + " 00:00:00");} else if (rule == QueryRuleEnum.LE) {//比较小于date = getTime().parse(value + " 23:59:59");}//TODO 日期类型比较特殊 可能oracle下不一定好使}if (date == null) {date = getTime().parse(value);}return date;}/*** 根据规则走不同的查询** @param queryWrapper QueryWrapper* @param name         字段名字* @param rule         查询规则* @param value        查询条件值*/public static void addEasyQuery(QueryWrapper<?> queryWrapper, String name, QueryRuleEnum rule, Object value) {if (value == null || rule == null || oConvertUtils.isEmpty(value)) {return;}name = oConvertUtils.camelToUnderline(name);log.info("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", name, rule.getValue(), value);switch (rule) {case GT:queryWrapper.gt(name, value);break;case GE:queryWrapper.ge(name, value);break;case LT:queryWrapper.lt(name, value);break;case LE:queryWrapper.le(name, value);break;case EQ:case EQ_WITH_ADD:queryWrapper.eq(name, value);break;case NE:queryWrapper.ne(name, value);break;case IN:if (value instanceof String) {queryWrapper.in(name, (Object[]) value.toString().split(COMMA));} else if (value instanceof String[]) {queryWrapper.in(name, (Object[]) value);}//update-begin-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671else if (value.getClass().isArray()) {queryWrapper.in(name, (Object[]) value);} else {queryWrapper.in(name, value);}//update-end-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671break;case LIKE:queryWrapper.like(name, value);break;case LEFT_LIKE:queryWrapper.likeLeft(name, value);break;case RIGHT_LIKE:queryWrapper.likeRight(name, value);break;default:log.info("--查询规则未匹配到---");break;}}/*** @param name* @return*/private static boolean judgedIsUselessField(String name) {return "class".equals(name) || "ids".equals(name)|| "page".equals(name) || "rows".equals(name)|| "sort".equals(name) || "order".equals(name);}/*** 获取请求对应的数据权限规则 TODO 相同列权限多个 有问题** @return*/public static Map<String, SysPermissionDataRuleModel> getRuleMap() {Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<>(5);List<SysPermissionDataRuleModel> list = DataAutorUtils.loadDataSearchConditon();if (list != null && list.size() > 0) {if (list.get(0) == null) {return ruleMap;}for (SysPermissionDataRuleModel rule : list) {String column = rule.getRuleColumn();if (QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {column = SQL_RULES_COLUMN + rule.getId();}ruleMap.put(column, rule);}}return ruleMap;}private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper<?> queryWrapper) {QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());if (rule.equals(QueryRuleEnum.IN) && !propertyType.equals(String.class)) {String[] values = dataRule.getRuleValue().split(",");Object[] objs = new Object[values.length];for (int i = 0; i < values.length; i++) {objs[i] = NumberUtils.parseNumber(values[i], propertyType);}addEasyQuery(queryWrapper, name, rule, objs);} else {if (propertyType.equals(String.class)) {addEasyQuery(queryWrapper, name, rule, converRuleValue(dataRule.getRuleValue()));} else if (propertyType.equals(Date.class)) {String dateStr = converRuleValue(dataRule.getRuleValue());int length = 10;if (dateStr.length() == length) {addEasyQuery(queryWrapper, name, rule, str2Date(dateStr, date_sdf.get()));} else {addEasyQuery(queryWrapper, name, rule, str2Date(dateStr, datetimeFormat.get()));}} else {addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType));}}}public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {@Overrideprotected SimpleDateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd");}};public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {@Overrideprotected SimpleDateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");}};/*** 字符串转换成日期** @param str* @param sdf* @return*/public static Date str2Date(String str, SimpleDateFormat sdf) {if (null == str || "".equals(str)) {return null;}Date date = null;try {date = sdf.parse(str);return date;} catch (ParseException e) {e.printStackTrace();}return null;}public static String converRuleValue(String ruleValue) {//String value = JwtUtil.getUserSystemData(ruleValue,null);String value = datetimeFormat.get().format(Calendar.getInstance().getTime());return value != null ? value : ruleValue;}/*** @param ruleValue:* @author: scott* @Description: 去掉值前后单引号* @date: 2020/3/19 21:26* @Return: java.lang.String*/public static String trimSingleQuote(String ruleValue) {if (oConvertUtils.isEmpty(ruleValue)) {return "";}if (ruleValue.startsWith(QueryGenerator.SQL_SQ)) {ruleValue = ruleValue.substring(1);}if (ruleValue.endsWith(QueryGenerator.SQL_SQ)) {ruleValue = ruleValue.substring(0, ruleValue.length() - 1);}return ruleValue;}public static String getSqlRuleValue(String sqlRule) {try {Set<String> varParams = getSqlRuleParams(sqlRule);for (String var : varParams) {String tempValue = converRuleValue(var);sqlRule = sqlRule.replace("#{" + var + "}", tempValue);}} catch (Exception e) {log.error(e.getMessage(), e);}return sqlRule;}/*** 获取sql中的#{key} 这个key组成的set*/public static Set<String> getSqlRuleParams(String sql) {if (oConvertUtils.isEmpty(sql)) {return null;}Set<String> varParams = new HashSet<String>();String regex = "\\#\\{\\w+\\}";Pattern p = Pattern.compile(regex);Matcher m = p.matcher(sql);while (m.find()) {String var = m.group();varParams.add(var.substring(var.indexOf("{") + 1, var.indexOf("}")));}return varParams;}/*** 获取查询条件** @param field* @param alias* @param value* @param isString* @return*/public static String getSingleQueryConditionSql(String field, String alias, Object value, boolean isString) {return getSingleQueryConditionSql(field, alias, value, isString, null);}/*** 报表获取查询条件 支持多数据源** @param field* @param alias* @param value* @param isString* @param dataBaseType* @return*/public static String getSingleQueryConditionSql(String field, String alias, Object value, boolean isString, String dataBaseType) {if (value == null) {return "";}field = alias + oConvertUtils.camelToUnderline(field);QueryRuleEnum rule = QueryGenerator.convert2Rule(value);return getSingleSqlByRule(rule, field, value, isString, dataBaseType);}/*** 获取单个查询条件的值** @param rule* @param field* @param value* @param isString* @param dataBaseType* @return*/private static String getSingleSqlByRule(QueryRuleEnum rule, String field, Object value, boolean isString, String dataBaseType) {String res = "";switch (rule) {case GT:res = field + rule.getValue() + getFieldConditionValue(value, isString, dataBaseType);break;case GE:res = field + rule.getValue() + getFieldConditionValue(value, isString, dataBaseType);break;case LT:res = field + rule.getValue() + getFieldConditionValue(value, isString, dataBaseType);break;case LE:res = field + rule.getValue() + getFieldConditionValue(value, isString, dataBaseType);break;case EQ:res = field + rule.getValue() + getFieldConditionValue(value, isString, dataBaseType);break;case EQ_WITH_ADD:res = field + " = " + getFieldConditionValue(value, isString, dataBaseType);break;case NE:res = field + " <> " + getFieldConditionValue(value, isString, dataBaseType);break;case IN:res = field + " in " + getInConditionValue(value, isString);break;case LIKE:res = field + " like " + getLikeConditionValue(value, QueryRuleEnum.LIKE);break;case LEFT_LIKE:res = field + " like " + getLikeConditionValue(value, QueryRuleEnum.LEFT_LIKE);break;case RIGHT_LIKE:res = field + " like " + getLikeConditionValue(value, QueryRuleEnum.RIGHT_LIKE);break;default:res = field + " = " + getFieldConditionValue(value, isString, dataBaseType);break;}return res;}/*** 获取单个查询条件的值** @param rule* @param field* @param value* @param isString* @return*/private static String getSingleSqlByRule(QueryRuleEnum rule, String field, Object value, boolean isString) {return getSingleSqlByRule(rule, field, value, isString, null);}/*** 获取查询条件的值** @param value* @param isString* @param dataBaseType* @return*/private static String getFieldConditionValue(Object value, boolean isString, String dataBaseType) {String str = value.toString().trim();if (str.startsWith(SymbolConstant.EXCLAMATORY_MARK)) {str = str.substring(1);} else if (str.startsWith(QueryRuleEnum.GE.getValue())) {str = str.substring(2);} else if (str.startsWith(QueryRuleEnum.LE.getValue())) {str = str.substring(2);} else if (str.startsWith(QueryRuleEnum.GT.getValue())) {str = str.substring(1);} else if (str.startsWith(QueryRuleEnum.LT.getValue())) {str = str.substring(1);} else if (str.indexOf(QUERY_COMMA_ESCAPE) > 0) {str = str.replaceAll("\\+\\+", COMMA);}if (dataBaseType == null) {dataBaseType = getDbType();}if (isString) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType)) {return " N'" + str + "' ";} else {return " '" + str + "' ";}} else {// 如果不是字符串 有一种特殊情况 popup调用都走这个逻辑 参数传递的可能是“‘admin’”这种格式的if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK)) {return " N" + str;}return value.toString();}}private static String getInConditionValue(Object value, boolean isString) {//update-begin-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错String[] temp = value.toString().split(",");if (temp.length == 0) {return "('')";}if (isString) {List<String> res = new ArrayList<>();for (String string : temp) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {res.add("N'" + string + "'");} else {res.add("'" + string + "'");}}return "(" + String.join(",", res) + ")";} else {return "(" + value.toString() + ")";}//update-end-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错}/*** 先根据值判断 走左模糊还是右模糊* 最后如果值不带任何标识(*或者%),则再根据ruleEnum判断** @param value* @param ruleEnum* @return*/private static String getLikeConditionValue(Object value, QueryRuleEnum ruleEnum) {String str = value.toString().trim();if (str.startsWith(SymbolConstant.ASTERISK) && str.endsWith(SymbolConstant.ASTERISK)) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'%" + str.substring(1, str.length() - 1) + "%'";} else {return "'%" + str.substring(1, str.length() - 1) + "%'";}} else if (str.startsWith(SymbolConstant.ASTERISK)) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'%" + str.substring(1) + "'";} else {return "'%" + str.substring(1) + "'";}} else if (str.endsWith(SymbolConstant.ASTERISK)) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'" + str.substring(0, str.length() - 1) + "%'";} else {return "'" + str.substring(0, str.length() - 1) + "%'";}} else {if (str.indexOf(SymbolConstant.PERCENT_SIGN) >= 0) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {if (str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK)) {return "N" + str;} else {return "N" + "'" + str + "'";}} else {if (str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK)) {return str;} else {return "'" + str + "'";}}} else {//update-begin-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题// 走到这里说明 value不带有任何模糊查询的标识(*或者%)if (ruleEnum == QueryRuleEnum.LEFT_LIKE) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'%" + str + "'";} else {return "'%" + str + "'";}} else if (ruleEnum == QueryRuleEnum.RIGHT_LIKE) {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'" + str + "%'";} else {return "'" + str + "%'";}} else {if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) {return "N'%" + str + "%'";} else {return "'%" + str + "%'";}}//update-end-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题}}}/*** 根据权限相关配置生成相关的SQL 语句** @param clazz* @return*/@SuppressWarnings({"unchecked", "rawtypes"})public static String installAuthJdbc(Class<?> clazz) {StringBuffer sb = new StringBuffer();//权限查询Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(clazz);String sqlAnd = " and ";for (String c : ruleMap.keySet()) {if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {sb.append(sqlAnd + getSqlRuleValue(ruleMap.get(c).getRuleValue()));}}String name, column;for (int i = 0; i < origDescriptors.length; i++) {name = origDescriptors[i].getName();if (judgedIsUselessField(name)) {continue;}if (ruleMap.containsKey(name)) {column = getTableFieldName(clazz, name);if (column == null) {continue;}SysPermissionDataRuleModel dataRule = ruleMap.get(name);QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());Class propType = origDescriptors[i].getPropertyType();boolean isString = propType.equals(String.class);Object value;if (isString) {value = converRuleValue(dataRule.getRuleValue());} else {value = NumberUtils.parseNumber(dataRule.getRuleValue(), propType);}String filedSql = getSingleSqlByRule(rule, oConvertUtils.camelToUnderline(column), value, isString);sb.append(sqlAnd + filedSql);}}log.info("query auth sql is:" + sb.toString());return sb.toString();}/*** 根据权限相关配置 组装mp需要的权限** @param queryWrapper* @param clazz* @return*/public static void installAuthMplus(QueryWrapper<?> queryWrapper, Class<?> clazz) {//权限查询Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(clazz);for (String c : ruleMap.keySet()) {if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {queryWrapper.and(i -> i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));}}String name, column;for (int i = 0; i < origDescriptors.length; i++) {name = origDescriptors[i].getName();if (judgedIsUselessField(name)) {continue;}column = getTableFieldName(clazz, name);if (column == null) {continue;}if (ruleMap.containsKey(name)) {addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper);}}}/*** 转换sql中的系统变量** @param sql* @return*/public static String convertSystemVariables(String sql) {return getSqlRuleValue(sql);}/*** 获取所有配置的权限 返回sql字符串 不受字段限制 配置什么就拿到什么** @return*/public static String getAllConfigAuth() {StringBuffer sb = new StringBuffer();//权限查询Map<String, SysPermissionDataRuleModel> ruleMap = getRuleMap();String sqlAnd = " and ";for (String c : ruleMap.keySet()) {SysPermissionDataRuleModel dataRule = ruleMap.get(c);String ruleValue = dataRule.getRuleValue();if (oConvertUtils.isEmpty(ruleValue)) {continue;}if (oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)) {sb.append(sqlAnd + getSqlRuleValue(ruleValue));} else {boolean isString = false;ruleValue = ruleValue.trim();if (ruleValue.startsWith("'") && ruleValue.endsWith("'")) {isString = true;ruleValue = ruleValue.substring(1, ruleValue.length() - 1);}QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());String value = converRuleValue(ruleValue);String filedSql = getSingleSqlByRule(rule, c, value, isString);sb.append(sqlAnd + filedSql);}}log.info("query auth sql is = " + sb.toString());return sb.toString();}/*** 获取系统数据库类型*/private static String getDbType() {return CommonUtils.getDatabaseType();}/*** 获取class的 包括父类的** @param clazz* @return*/private static List<Field> getClassFields(Class<?> clazz) {List<Field> list = new ArrayList<Field>();Field[] fields;do {fields = clazz.getDeclaredFields();for (int i = 0; i < fields.length; i++) {list.add(fields[i]);}clazz = clazz.getSuperclass();} while (clazz != Object.class && clazz != null);return list;}/*** 获取表字段名** @param clazz* @param name* @return*/private static String getTableFieldName(Class<?> clazz, String name) {try {//如果字段加注解了@TableField(exist = false),不走DB查询Field field = null;try {field = clazz.getDeclaredField(name);} catch (NoSuchFieldException e) {//e.printStackTrace();}//如果为空,则去父类查找字段if (field == null) {List<Field> allFields = getClassFields(clazz);List<Field> searchFields = allFields.stream().filter(a -> a.getName().equals(name)).collect(Collectors.toList());if (searchFields != null && searchFields.size() > 0) {field = searchFields.get(0);}}if (field != null) {TableField tableField = field.getAnnotation(TableField.class);if (tableField != null) {if (tableField.exist() == false) {//如果设置了TableField false 这个字段不需要处理return null;} else {String column = tableField.value();//如果设置了TableField value 这个字段是实体字段if (!"".equals(column)) {return column;}}}}} catch (Exception e) {e.printStackTrace();}return name;}/*** mysql 模糊查询之特殊字符下划线 (_、\)** @param value:* @Return: java.lang.String*/private static String specialStrConvert(String value) {if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType()) || DataBaseConstant.DB_TYPE_MARIADB.equals(getDbType())) {String[] specialStr = QueryGenerator.LIKE_MYSQL_SPECIAL_STRS.split(",");for (String str : specialStr) {if (value.indexOf(str) != -1) {value = value.replace(str, "\\" + str);}}}return value;}
}

10

package com.hdx.contractor.util.query;/*** Query 规则 常量* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public enum QueryRuleEnum {/**查询规则 大于*/GT(">","gt","大于"),/**查询规则 大于等于*/GE(">=","ge","大于等于"),/**查询规则 小于*/LT("<","lt","小于"),/**查询规则 小于等于*/LE("<=","le","小于等于"),/**查询规则 等于*/EQ("=","eq","等于"),/**查询规则 不等于*/NE("!=","ne","不等于"),/**查询规则 包含*/IN("IN","in","包含"),/**查询规则 全模糊*/LIKE("LIKE","like","全模糊"),/**查询规则 左模糊*/LEFT_LIKE("LEFT_LIKE","left_like","左模糊"),/**查询规则 右模糊*/RIGHT_LIKE("RIGHT_LIKE","right_like","右模糊"),/**查询规则 带加号等于*/EQ_WITH_ADD("EQWITHADD","eq_with_add","带加号等于"),/**查询规则 多词模糊匹配*/LIKE_WITH_AND("LIKEWITHAND","like_with_and","多词模糊匹配————暂时未用上"),/**查询规则 自定义SQL片段*/SQL_RULES("USE_SQL_RULES","ext","自定义SQL片段");private String value;private String condition; private String msg;QueryRuleEnum(String value, String condition, String msg){this.value = value;this.condition = condition;this.msg = msg;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getCondition() {return condition;}public void setCondition(String condition) {this.condition = condition;}public static QueryRuleEnum getByValue(String value){if(oConvertUtils.isEmpty(value)) {return null;}for(QueryRuleEnum val :values()){if (val.getValue().equals(value) || val.getCondition().equals(value)){return val;}}return  null;}
}

11

package com.hdx.contractor.util.query;import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** sql注入处理工具类* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
@Slf4j
public class SqlInjectionUtil {/*** sign 用于表字典加签的盐值【SQL漏洞】* (上线修改值 20200501,同步修改前端的盐值)*/private final static String TABLE_DICT_SIGN_SALT = "20200501";private final static String XSS_STR = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|user()";/*** 正则 user() 匹配更严谨*/private final static String REGULAR_EXPRE_USER = "user[\\s]*\\([\\s]*\\)";/**正则 show tables*/private final static String SHOW_TABLES = "show\\s+tables";/*** sql注释的正则*/private final static Pattern SQL_ANNOTATION = Pattern.compile("/\\*.*\\*/");/*** 针对表字典进行额外的sign签名校验(增加安全机制)* @param dictCode:* @param sign:* @param request:* @Return: void*/public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {//表字典SQL注入漏洞,签名校验String accessToken = request.getHeader("X-Access-Token");String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;String javaSign = SecureUtil.md5(signStr);if (!javaSign.equals(sign)) {log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode);throw new RuntimeException("无权限访问!");}log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode);}/*** sql注入过滤处理,遇到注入关键字抛异常* @param value*/public static void filterContent(String value) {filterContent(value, null);}/*** sql注入过滤处理,遇到注入关键字抛异常* * @param value* @return*/public static void filterContent(String value, String customXssString) {if (value == null || "".equals(value)) {return;}// 校验sql注释 不允许有sql注释checkSqlAnnotation(value);// 统一转为小写value = value.toLowerCase();//SQL注入检测存在绕过风险 https://gitee.com/jeecg/jeecg-boot/issues/I4NZGE//value = value.replaceAll("/\\*.*\\*/","");String[] xssArr = XSS_STR.split("\\|");for (int i = 0; i < xssArr.length; i++) {if (value.indexOf(xssArr[i]) > -1) {log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}//update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号if (customXssString != null) {String[] xssArr2 = customXssString.split("\\|");for (int i = 0; i < xssArr2.length; i++) {if (value.indexOf(xssArr2[i]) > -1) {log.error("请注意,存在SQL注入关键词---> {}", xssArr2[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}}//update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}return;}/*** sql注入过滤处理,遇到注入关键字抛异常* @param values*/public static void filterContent(String[] values) {filterContent(values, null);}/*** sql注入过滤处理,遇到注入关键字抛异常* * @param values* @return*/public static void filterContent(String[] values, String customXssString) {String[] xssArr = XSS_STR.split("\\|");for (String value : values) {if (value == null || "".equals(value)) {return;}// 校验sql注释 不允许有sql注释checkSqlAnnotation(value);// 统一转为小写value = value.toLowerCase();//SQL注入检测存在绕过风险 https://gitee.com/jeecg/jeecg-boot/issues/I4NZGE//value = value.replaceAll("/\\*.*\\*/","");for (int i = 0; i < xssArr.length; i++) {if (value.indexOf(xssArr[i]) > -1) {log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}//update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号if (customXssString != null) {String[] xssArr2 = customXssString.split("\\|");for (int i = 0; i < xssArr2.length; i++) {if (value.indexOf(xssArr2[i]) > -1) {log.error("请注意,存在SQL注入关键词---> {}", xssArr2[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}}//update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}return;}/*** 【提醒:不通用】* 仅用于字典条件SQL参数,注入过滤** @param value* @return*///@Deprecatedpublic static void specialFilterContentForDictSql(String value) {String specialXssStr = " exec |extractvalue|updatexml| insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|user()";String[] xssArr = specialXssStr.split("\\|");if (value == null || "".equals(value)) {return;}// 校验sql注释 不允许有sql注释checkSqlAnnotation(value);// 统一转为小写value = value.toLowerCase();//SQL注入检测存在绕过风险 https://gitee.com/jeecg/jeecg-boot/issues/I4NZGE//value = value.replaceAll("/\\*.*\\*/","");for (int i = 0; i < xssArr.length; i++) {if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}return;}/*** 【提醒:不通用】*  仅用于Online报表SQL解析,注入过滤* @param value* @return*///@Deprecatedpublic static void specialFilterContentForOnlineReport(String value) {String specialXssStr = " exec |extractvalue|updatexml| insert | delete | update | drop | chr | mid | master | truncate | char | declare |user()";String[] xssArr = specialXssStr.split("\\|");if (value == null || "".equals(value)) {return;}// 校验sql注释 不允许有sql注释checkSqlAnnotation(value);// 统一转为小写value = value.toLowerCase();//SQL注入检测存在绕过风险 https://gitee.com/jeecg/jeecg-boot/issues/I4NZGE//value = value.replaceAll("/\\*.*\\*/"," ");for (int i = 0; i < xssArr.length; i++) {if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);log.error("请注意,值可能存在SQL注入风险!---> {}", value);throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}}if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);}return;}/*** 判断给定的字段是不是类中的属性* @param field 字段名* @param clazz 类对象* @return*/public static boolean isClassField(String field, Class clazz){Field[] fields = clazz.getDeclaredFields();for(int i=0;i<fields.length;i++){String fieldName = fields[i].getName();String tableColumnName = oConvertUtils.camelToUnderline(fieldName);if(fieldName.equalsIgnoreCase(field) || tableColumnName.equalsIgnoreCase(field)){return true;}}return false;}/*** 判断给定的多个字段是不是类中的属性* @param fieldSet 字段名set* @param clazz 类对象* @return*/public static boolean isClassField(Set<String> fieldSet, Class clazz){Field[] fields = clazz.getDeclaredFields();for(String field: fieldSet){boolean exist = false;for(int i=0;i<fields.length;i++){String fieldName = fields[i].getName();String tableColumnName = oConvertUtils.camelToUnderline(fieldName);if(fieldName.equalsIgnoreCase(field) || tableColumnName.equalsIgnoreCase(field)){exist = true;break;}}if(!exist){return false;}}return true;}/*** 校验是否有sql注释 * @return*/public static void checkSqlAnnotation(String str){Matcher matcher = SQL_ANNOTATION.matcher(str);if(matcher.find()){String error = "请注意,值可能存在SQL注入风险---> \\*.*\\";log.error(error);throw new RuntimeException(error);}}
}

12

package com.hdx.contractor.util.query;/*** @Description: 符号和特殊符号常用类* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public class SymbolConstant {/*** 符号:点*/public static final String SPOT = ".";/*** 符号:双斜杠*/public static final String DOUBLE_BACKSLASH = "\\";/*** 符号:冒号*/public static final String COLON = ":";/*** 符号:逗号*/public static final String COMMA = ",";/*** 符号:左花括号 }*/public static final String LEFT_CURLY_BRACKET = "{";/*** 符号:右花括号 }*/public static final String RIGHT_CURLY_BRACKET = "}";/*** 符号:井号 #*/public static final String WELL_NUMBER = "#";/*** 符号:单斜杠*/public static final String SINGLE_SLASH = "/";/*** 符号:双斜杠*/public static final String DOUBLE_SLASH = "//";/*** 符号:感叹号*/public static final String EXCLAMATORY_MARK = "!";/*** 符号:下划线*/public static final String UNDERLINE = "_";/*** 符号:单引号*/public static final String SINGLE_QUOTATION_MARK = "'";/*** 符号:星号*/public static final String ASTERISK = "*";/*** 符号:百分号*/public static final String PERCENT_SIGN = "%";/*** 符号:美元 $*/public static final String DOLLAR = "$";/*** 符号:和 &*/public static final String AND = "&";/*** 符号:和 =*/public static final String equals = "=";/*** 符号:../*/public static final String SPOT_SINGLE_SLASH = "../";/*** 符号:..\\*/public static final String SPOT_DOUBLE_BACKSLASH = "..\\";/*** 系统变量前缀 #{*/public static final String SYS_VAR_PREFIX = "#{";/*** 符号 {{*/public static final String DOUBLE_LEFT_CURLY_BRACKET = "{{";/*** 符号:[*/public static final String SQUARE_BRACKETS_LEFT = "[";/*** 符号:]*/public static final String SQUARE_BRACKETS_RIGHT = "]";}

13

package com.hdx.contractor.util.query;import java.util.Date;/*** <p>* 菜单权限规则表* </p>* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
public class SysPermissionDataRuleModel {/*** id*/private String id;/*** 对应的菜单id*/private String permissionId;/*** 规则名称*/private String ruleName;/*** 字段*/private String ruleColumn;/*** 条件*/private String ruleConditions;/*** 规则值*/private String ruleValue;/*** 创建时间*/private Date createTime;/*** 创建人*/private String createBy;/*** 修改时间*/private Date updateTime;/*** 修改人*/private String updateBy;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getPermissionId() {return permissionId;}public void setPermissionId(String permissionId) {this.permissionId = permissionId;}public String getRuleName() {return ruleName;}public void setRuleName(String ruleName) {this.ruleName = ruleName;}public String getRuleColumn() {return ruleColumn;}public void setRuleColumn(String ruleColumn) {this.ruleColumn = ruleColumn;}public String getRuleConditions() {return ruleConditions;}public void setRuleConditions(String ruleConditions) {this.ruleConditions = ruleConditions;}public String getRuleValue() {return ruleValue;}public void setRuleValue(String ruleValue) {this.ruleValue = ruleValue;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public String getCreateBy() {return createBy;}public void setCreateBy(String createBy) {this.createBy = createBy;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getUpdateBy() {return updateBy;}public void setUpdateBy(String updateBy) {this.updateBy = updateBy;}
}

14

package com.hdx.contractor.util;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;/*** Spring Context 工具类* @Author: xu* @Date: 2024-10-06* @Version: V1.0*/
@Component
public class SpringContextUtils implements ApplicationContextAware {public static ApplicationContext applicationContext; @Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {SpringContextUtils.applicationContext = applicationContext;}public static Object getBean(String name) {return applicationContext.getBean(name);}public static <T> T getBean(Class<T> requiredType) {return applicationContext.getBean(requiredType);}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);}/*** 获取HttpServletRequest*/public static HttpServletRequest getHttpServletRequest() {return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();}/*** 获取applicationContext** @return*/public static ApplicationContext getApplicationContext() {return applicationContext;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/440831.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLO11改进|卷积篇|引入线性可变形卷积LDConv

目录 一、【LDConv】卷积1.1【LDConv】卷积介绍1.2【LDConv】核心代码 二、添加【LDConv】卷积2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【LDConv】卷积 1.1【LDConv】卷积介绍 下图是【LDCNV】的结构图&#xff0c;让我们简单分析…

Ajax面试题:(第一天)

目录 1.说一下网络模型 2.在浏览器地址栏键入URL&#xff0c;按下回车之后会经历以下流程&#xff1a; 3.什么是三次握手和四次挥手&#xff1f; 4.http协议和https协议的区别 1.说一下网络模型 注&#xff1a;各层含义按自己理解即可 2.在浏览器地址栏键入URL&#xff0c;…

盲拍合约:让竞拍更公平与神秘的创新解决方案

目录 前言 一、盲拍合约是什么&#xff1f; 二、盲拍合约工作原理 1、合约创建与初始化 2、用户出价&#xff08;Bid&#xff09; 3、出价结束 4、披露出价&#xff08;Reveal&#xff09; 5、处理最高出价 6、结束拍卖 7、退款与提款 三、解析盲拍合约代码…

阿里云域名解析和备案

文章目录 1、域名解析2、新手引导3、ICP备案 1、域名解析 2、新手引导 3、ICP备案

类的特殊成员函数——三之法则、五之法则、零之法则

系统中的动态资源、文件句柄&#xff08;socket描述符、文件描述符&#xff09;是有限的&#xff0c;在类中若涉及对此类资源的操作&#xff0c;但是未做到妥善的管理&#xff0c;常会造成资源泄露问题&#xff0c;严重的可能造成资源不可用&#xff0c;如申请内存失败、文件句…

【redis-05】redis保证和mysql数据一致性

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…

57.对称二叉树

迭代 class Solution {public boolean isSymmetric(TreeNode root) {if(rootnull){return true;}Deque<TreeNode> denew LinkedList<>();TreeNode l,r;int le;de.offer(root.left);de.offer(root.right);while(!de.isEmpty()){lde.pollFirst();rde.pollLast();if(…

BMC pam认证的使用

1.说明 1.1 文档参考资料 https://www.chiark.greenend.org.uk/doc/libpam-doc/html/Linux-PAM_ADG.htmlhttp://www.fifi.org/doc/libpam-doc/html/pam_appl-3.htmlpdf文档: https://fossies.org/linux/Linux-PAM-docs/doc/adg/Linux-PAM_ADG.pdflinux-pam 中文文档pam 旧文p…

<数据集>工程机械识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2644张 标注数量(xml文件个数)&#xff1a;2644 标注数量(txt文件个数)&#xff1a;2644 标注类别数&#xff1a;3 标注类别名称&#xff1a;[dump truck, wheel loader, excavators] 序号类别名称图片数框数1dum…

SpringBootWeb快速入门!详解如何创建一个简单的SpringBoot项目?

在现代Web开发中&#xff0c;SpringBoot以其简化的配置和快速的开发效率而受到广大开发者的青睐。本篇文章将带领你从零开始&#xff0c;搭建一个基于SpringBoot的简单Web应用~ 一、前提准备 想要创建一个SpringBoot项目&#xff0c;需要做如下准备&#xff1a; idea集成开发…

wordpress Contact form 7发件人邮箱设置

此教程仅适用于演示站有留言的主题&#xff0c;演示站没有留言的主题&#xff0c;就别往下看了&#xff0c;免费浪费时间。 使用了Contact form 7插件的简站WordPress主题&#xff0c;在有人留言时&#xff0c;就会发邮件到网站的系统邮箱(一般与管理员邮箱为同一个)里。上面显…

SpringCloud简介 Ribbon Eureka 远程调用RestTemplate类 openfeign

〇、SpringCloud 0.区别于单体项目和soa架构&#xff0c;微服务架构每个服务独立&#xff0c;灵活。 1. spring cloud是一个完整的微服务框架&#xff0c;springCloud包括三个体系&#xff1a; spring cloud Netflix spring cloud Alibaba spring 其他 2.spring cloud 版本命名…

论文阅读笔记-LogME: Practical Assessment of Pre-trained Models for Transfer Learning

前言 在NLP领域,预训练模型(准确的说应该是预训练语言模型)似乎已经成为各大任务必备的模块了,经常有看到文章称后BERT时代或后XXX时代,分析对比了许多主流模型的优缺点,这些相对而言有些停留在理论层面,可是有时候对于手上正在解决的任务,要用到预训练语言模型时,面…

软件设计师(软考学习)

数据库技术 数据库基础知识 1. 数据库中的简单属性、多值属性、复合属性、派生属性简单属性&#xff1a;指不能够再分解成更小部分的属性&#xff0c;通常是数据表中的一个列。例如学生表中的“学号”、“姓名”等均为简单属性。 多值属性&#xff1a;指一个属性可以有多个值…

sql-labs:42~65

less42&#xff08;单引号闭合、报错回显&#xff09; login_useradmin login_password123 and if(11,sleep(2),1) # # 单引号闭合 ​ login_useradmin login_password123and updatexml(1,concat(0x7e,database(),0x7e),1)# # 报错回显…

mysql UDF提权(实战案例)

作者&#xff1a;程序那点事儿 日期&#xff1a;2024/09/29 16:10 什么是UDF? 全称 User Define Function &#xff08;用户自定义函数&#xff09;UDF提权&#xff0c;就是通过自定义函数&#xff0c;实现执行系统的命令。 dll&#xff08;windows&#xff0c;dll文件是c语…

5.人员管理模块(以及解决运行Bug)——帝可得管理系统

目录 前言一、页面修改表单展示修改 二、新增对话框修改三、修改对话框修改修改时展示创建时间 四、解决页面展示错误五 、 解决【java.lang.NullPointerException: null】 Bug 前言 提示&#xff1a;本篇完成人员管理模块的开发&#xff0c;具体需求、修改代码的路径和最终效…

车辆种类分类识别数据集,可以识别7种汽车类型,已经按照7:2:1比 例划分数据集,训练集1488张、验证集507张,测试集31张, 共计2026张。

车 车辆种类分类识别数据集&#xff0c;可以识别7种汽车类型&#xff0c;已经按照7:2:1比 例划分数据集&#xff0c;训练集1488张、验证集507张,测试集31张&#xff0c; 共计2026张。 数据集分为一类客车(tinycar) &#xff0c;类客车(midcar) &#xff0c;三类 客车(bigcar) ,…

重学SpringBoot3-集成Redis(六)之消息队列

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;六&#xff09;之消息队列 1. 什么是发布/订阅&#xff08;Pub/Sub&#xff09;&#xff1f;2. 场景应用3. Spring Boot 3 整合 R…

感知机学习算法

感知机 一、感知机简介二、感知机模型2.1 感知机的基本组成2.2 求和函数2.2.1 时间总合2.2.2 空间总合 2.3 激活函数2.4 学习算法2.4.1 赫布学习规则2.4.2 Delta学习规则 三、 结论参考文献 一、感知机简介 M-P神经元模型因其对生物神经元激发过程的极大简化而成为神经网络研究…