tsurumure 10 месяцев назад
Родитель
Сommit
feca61c8fc

+ 1 - 1
db/sys_user_role_module.sql

@@ -41,7 +41,7 @@ INSERT INTO sys_user_role_module(id, parent_id, module_name, sort) VALUES
         ('3.1', '3', '系统用户-列表 (在线的)', null),
         ('3.2', '3', '系统用户-列表', null),
             ('3.2.1', '3.2', '查询用户信息', null),
-            ('3.2.1.2', '3.2', '查询他人用户信息', null),
+            ('3.2.1.2', '3.2', '查询他人用户信息', null),
             ('3.2.2', '3.2', '系统用户-创建', null),
             ('3.2.3', '3.2', '系统用户-编辑', null),
             ('3.2.4', '3.2', '系统用户-删除', null),

+ 15 - 5
src/main/java/com/backendsys/modules/system/controller/SysUserV2Controller.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.system.controller;
 
+import com.backendsys.entity.PageDTO;
 import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.security.enums.SecurityEnum;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
@@ -23,10 +24,17 @@ public class SysUserV2Controller {
     @Autowired
     private SysUserV2Service sysUserV2Service;
 
+    @Operation(summary = "获得系统用户列表")
+    @PreAuthorize("@sr.hasPermission('3.2')")
+    @GetMapping("/api/v2/system/user/getUserList")
+    public Result getUserList(SysUserInfo sysUserInfo) {
+        return Result.success().put("data", sysUserV2Service.selectUserList(sysUserInfo));
+    }
+
     /**
      * 权限:
      * - 查询用户信息 (3.2.1)
-     * - 查询他人的用户信息 (3.2.1.2)
+     * - 查询他人用户信息 (3.2.1.2)
      */
     @Operation(summary = "获得系统用户详情")
     @PreAuthorize("@sr.hasPermission('3.2.1')")
@@ -46,12 +54,14 @@ public class SysUserV2Controller {
         return Result.success().put("data", sysUserV2Service.selectUserInfo(user_id));
     }
 
-
-    @Operation(summary = "获得系统用户权限")
+    /**
+     * 权限:
+     * - 查询用户权限 (3.4.1)
+     * - 查询他人用户权限 (3.4.1.2)
+     */
+    @Operation(summary = "获得系统用户权限列表")
     @PreAuthorize("@sr.hasPermission('3.4.1')")
     @GetMapping("/api/v2/system/user/getUserPermission")
-//    public Result getUserPermission(@Validated(SysUserInfo.Primarys.class) SysUserInfo userInfo) {
-//    public Result getUserPermission(@NotEmpty(message = "user_id 不能为空") String user_id) {
     public Result getUserPermission(@Parameter(description = "用户ID") Long user_id) {
 
         // 查询自身的用户信息 (不传参数)

+ 5 - 0
src/main/java/com/backendsys/modules/system/service/SysUserV2Service.java

@@ -2,12 +2,17 @@ package com.backendsys.modules.system.service;
 
 import com.backendsys.modules.system.entity.SysUser.SysUser;
 import com.backendsys.modules.system.entity.SysUser.SysUserInfo;
+import com.backendsys.utils.response.PageEntity;
+import com.backendsys.utils.response.PageInfoResult;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import java.util.List;
 
 public interface SysUserV2Service extends IService<SysUser> {
 
+    // 获得系统用户列表
+    PageEntity selectUserList(SysUserInfo sysUserInfo);
+
     // 获得系统用户详情
     SysUserInfo selectUserInfo(Long user_id);
 

+ 28 - 0
src/main/java/com/backendsys/modules/system/service/impl/SysUserV2ServiceImpl.java

@@ -1,14 +1,20 @@
 package com.backendsys.modules.system.service.impl;
 
 import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.StrUtil;
 import com.backendsys.modules.system.dao.*;
 import com.backendsys.modules.system.entity.SysUser.SysUser;
 import com.backendsys.modules.system.entity.SysUser.SysUserInfo;
 import com.backendsys.modules.system.entity.SysUser.SysUserRole;
 import com.backendsys.modules.system.entity.SysUser.SysUserRoleRelation;
 import com.backendsys.modules.system.service.SysUserV2Service;
+import com.backendsys.utils.response.PageEntity;
+import com.backendsys.utils.response.PageInfoResult;
+import com.backendsys.utils.v2.PageUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.pagehelper.PageHelper;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -32,6 +38,28 @@ public class SysUserV2ServiceImpl extends ServiceImpl<SysUserDao, SysUser> imple
     @Autowired
     private SysUserRoleModuleRelationDao sysUserRoleModuleRelationDao;
 
+
+    /**
+     * 获得系统用户列表
+     */
+    @Override
+    public PageEntity selectUserList(SysUserInfo sysUserInfo) {
+        // 分页
+        PageUtils.startPage();
+        //
+        System.out.println(sysUserInfo);
+        // QueryWrapper<SysUserInfo> queryWrapper = new QueryWrapper<SysUserInfo>().setEntity(sysUserInfo);
+//        LambdaQueryWrapper<SysUserInfo> queryWrapper = new LambdaQueryWrapper<SysUserInfo>().setEntity(sysUserInfo);
+        QueryWrapper<SysUserInfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.like(StrUtil.isNotEmpty(sysUserInfo.getNickname()), "nickname", sysUserInfo.getNickname());
+
+        // 如何在 setEntity 时,非空字段不加入条件筛选?
+
+        List<SysUserInfo> list = sysUserInfoDao.selectList(queryWrapper);
+        return new PageInfoResult(list).toEntity();
+    }
+
+
     /**
      * 获得系统用户详情
      */

+ 12 - 0
src/main/java/com/backendsys/utils/response/PageEntity.java

@@ -0,0 +1,12 @@
+package com.backendsys.utils.response;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class PageEntity {
+    private Long total;
+    private List<Object> list;
+    private Integer page_num;
+    private Integer page_size;
+}

+ 8 - 0
src/main/java/com/backendsys/utils/response/PageInfoResult.java

@@ -23,4 +23,12 @@ public class PageInfoResult extends PageInfo {
         map.put("page_size", getPageSize());
         return map;
     }
+    public PageEntity toEntity() {
+        PageEntity entity = new PageEntity();
+        entity.setTotal(getTotal());
+        entity.setList(getList());
+        entity.setPage_num(getPageNum());
+        entity.setPage_size(getPageSize());
+        return entity;
+    }
 }

+ 83 - 0
src/main/java/com/backendsys/utils/v2/PageDomain.java

@@ -0,0 +1,83 @@
+package com.backendsys.utils.v2;
+
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 分页数据
+ */
+public class PageDomain
+{
+    /** 当前记录起始索引 */
+    private Integer page_num;
+
+    /** 每页显示记录数 */
+    private Integer page_size;
+
+    /** 排序列 */
+    private String order_by_column;
+
+    /** 排序的方向desc或者asc */
+    private String is_asc = "asc";
+
+    /** 分页参数合理化 */
+    private Boolean reasonable = true;
+
+    public String getOrderBy()
+    {
+        if (StrUtil.isEmpty(order_by_column))
+        {
+            return "";
+        }
+        return StrUtil.toUnderlineCase(order_by_column) + " " + is_asc;
+    }
+
+    public Integer getPageNum()
+    {
+        return page_num;
+    }
+
+    public void setPageNum(Integer page_num)
+    {
+        this.page_num = page_num;
+    }
+
+    public Integer getPageSize()
+    {
+        return page_size;
+    }
+
+    public void setPageSize(Integer page_size)
+    {
+        this.page_size = page_size;
+    }
+
+    public String getOrderByColumn()
+    {
+        return order_by_column;
+    }
+
+    public void setOrderByColumn(String order_by_column)
+    {
+        this.order_by_column = order_by_column;
+    }
+
+    public String getIsAsc()
+    {
+        return is_asc;
+    }
+
+    public void setIsAsc(String isAsc)
+    {
+        this.is_asc = is_asc;
+    }
+
+    public Boolean getReasonable()
+    {
+        return reasonable;
+    }
+
+    public void setReasonable(Boolean reasonable)
+    {
+        this.reasonable = reasonable;
+    }
+}

+ 31 - 0
src/main/java/com/backendsys/utils/v2/PageUtils.java

@@ -0,0 +1,31 @@
+package com.backendsys.utils.v2;
+
+import com.github.pagehelper.PageHelper;
+
+/**
+ * 分页工具类
+ */
+public class PageUtils extends PageHelper
+{
+    /**
+     * 设置请求分页数据
+     */
+    public static void startPage()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+        Boolean reasonable = pageDomain.getReasonable();
+
+        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+    }
+
+    /**
+     * 清理分页的线程变量
+     */
+    public static void clearPage()
+    {
+        PageHelper.clearPage();
+    }
+}

+ 214 - 0
src/main/java/com/backendsys/utils/v2/ServletUtils.java

@@ -0,0 +1,214 @@
+package com.backendsys.utils.v2;
+
+import cn.hutool.core.convert.Convert;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * 客户端工具类
+ */
+public class ServletUtils
+{
+    /**
+     * 定义移动端请求的所有可能类型
+     */
+    private final static String[] agent = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     * 
+     * @param response 渲染对象
+     * @param string 待渲染的字符串
+     * @return null
+     */
+    public static String renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 判断User-Agent 是不是来自于手机
+     */
+    public static boolean checkAgentIsMobile(String ua)
+    {
+        boolean flag = false;
+        if (!ua.contains("Windows NT") || (ua.contains("Windows NT") && ua.contains("compatible; MSIE 9.0;")))
+        {
+            // 排除 苹果桌面系统
+            if (!ua.contains("Windows NT") && !ua.contains("Macintosh"))
+            {
+                for (String item : agent)
+                {
+                    if (ua.contains(item))
+                    {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * 内容编码
+     * 
+     * @param str 内容
+     * @return 编码后的内容
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, "UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 内容解码
+     * 
+     * @param str 内容
+     * @return 解码后的内容
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, "UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+}

+ 68 - 0
src/main/java/com/backendsys/utils/v2/SqlUtil.java

@@ -0,0 +1,68 @@
+package com.backendsys.utils.v2;
+
+import cn.hutool.core.util.StrUtil;
+import com.backendsys.exception.CustException;
+
+/**
+ * sql操作工具类
+ */
+public class SqlUtil
+{
+    /**
+     * 定义常用的 sql关键字
+     */
+    public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
+
+    /**
+     * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
+     */
+    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 限制orderBy最大长度
+     */
+    private static final int ORDER_BY_MAX_LENGTH = 500;
+
+    /**
+     * 检查字符,防止注入绕过
+     */
+    public static String escapeOrderBySql(String value)
+    {
+        if (StrUtil.isNotEmpty(value) && !isValidOrderBySql(value))
+        {
+            throw new CustException("参数不符合规范,不能进行查询");
+        }
+        if (StrUtil.length(value) > ORDER_BY_MAX_LENGTH)
+        {
+            throw new CustException("参数已超过最大限制,不能进行查询");
+        }
+        return value;
+    }
+
+    /**
+     * 验证 order by 语法是否符合规范
+     */
+    public static boolean isValidOrderBySql(String value)
+    {
+        return value.matches(SQL_PATTERN);
+    }
+
+    /**
+     * SQL关键字检查
+     */
+    public static void filterKeyword(String value)
+    {
+        if (StrUtil.isEmpty(value))
+        {
+            return;
+        }
+        String[] sqlKeywords = SQL_REGEX.split( "\\|");
+        for (String sqlKeyword : sqlKeywords)
+        {
+            if (StrUtil.indexOfIgnoreCase(value, sqlKeyword) > -1)
+            {
+                throw new CustException("参数存在SQL注入风险");
+            }
+        }
+    }
+}

+ 668 - 0
src/main/java/com/backendsys/utils/v2/StringUtils.java

@@ -0,0 +1,668 @@
+package com.backendsys.utils.v2;
+
+import org.springframework.util.AntPathMatcher;
+
+import java.util.*;
+
+/**
+ * 字符串工具类
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /** 星号 */
+    private static final char ASTERISK = '*';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     * 
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     * 
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     * 
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     * 
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     * 
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     * 
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     * 
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 替换指定字符串的指定区间内字符为"*"
+     *
+     * @param str 字符串
+     * @param startInclude 开始位置(包含)
+     * @param endExclude 结束位置(不包含)
+     * @return 替换后的字符串
+     */
+    public static String hide(CharSequence str, int startInclude, int endExclude)
+    {
+        if (isEmpty(str))
+        {
+            return NULLSTR;
+        }
+        final int strLength = str.length();
+        if (startInclude > strLength)
+        {
+            return NULLSTR;
+        }
+        if (endExclude > strLength)
+        {
+            endExclude = strLength;
+        }
+        if (startInclude > endExclude)
+        {
+            // 如果起始位置大于结束位置,不替换
+            return NULLSTR;
+        }
+        final char[] chars = new char[strLength];
+        for (int i = 0; i < strLength; i++)
+        {
+            if (i >= startInclude && i < endExclude)
+            {
+                chars[i] = ASTERISK;
+            }
+            else
+            {
+                chars[i] = str.charAt(i);
+            }
+        }
+        return new String(chars);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+     */
+//    public static String format(String template, Object... params)
+//    {
+//        if (isEmpty(params) || isEmpty(template))
+//        {
+//            return template;
+//        }
+//        return StrFormatter.format(template, params);
+//    }
+
+    /**
+     * 是否为http(s)://开头
+     * 
+     * @param link 链接
+     * @return 结果
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link, "http://", "https://");
+    }
+
+    /**
+     * 字符串转set
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @return set集合
+     */
+    public static final Set<String> str2Set(String str, String sep)
+    {
+        return new HashSet<String>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 字符串转list
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @param filterBlank 过滤纯空白
+     * @param trim 去掉首尾空白
+     * @return list集合
+     */
+    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+    {
+        List<String> list = new ArrayList<String>();
+        if (StringUtils.isEmpty(str))
+        {
+            return list;
+        }
+
+        // 过滤空白字符串
+        if (filterBlank && StringUtils.isBlank(str))
+        {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split)
+        {
+            if (filterBlank && StringUtils.isBlank(string))
+            {
+                continue;
+            }
+            if (trim)
+            {
+                string = string.trim();
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+     *
+     * @param collection 给定的集合
+     * @param array 给定的数组
+     * @return boolean 结果
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
+     *
+     * @param cs 指定字符串
+     * @param searchCharSequences 需要检查的字符串数组
+     * @return 是否包含任意一个字符串
+     */
+    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+    {
+        if (isEmpty(cs) || isEmpty(searchCharSequences))
+        {
+            return false;
+        }
+        for (CharSequence testStr : searchCharSequences)
+        {
+            if (containsIgnoreCase(cs, testStr))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 驼峰转下划线命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     * 
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 删除最后一个字符串
+     *
+     * @param str 输入字符串
+     * @param spit 以什么类型结尾的
+     * @return 截取后的字符串
+     */
+    public static String lastStringDel(String str, String spit)
+    {
+        if (!StringUtils.isEmpty(str) && str.endsWith(spit))
+        {
+            return str.subSequence(0, str.length() - 1).toString();
+        }
+        return str;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     * 
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法
+     * 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+     * 
+     * @param str 指定字符串
+     * @param strs 需要检查的字符串数组
+     * @return 是否匹配
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断url是否与规则配置: 
+     * ? 表示单个字符; 
+     * * 表示一层路径内的任意字符串,不可跨层级; 
+     * ** 表示任意层路径;
+     * 
+     * @param pattern 匹配规则
+     * @param url 需要匹配的url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+     * 
+     * @param num 数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+     * 
+     * @param s 原始字符串
+     * @param size 字符串指定长度
+     * @param c 用于补齐的字符
+     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}

+ 55 - 0
src/main/java/com/backendsys/utils/v2/TableSupport.java

@@ -0,0 +1,55 @@
+package com.backendsys.utils.v2;
+
+import cn.hutool.core.convert.Convert;
+
+/**
+ * 表格数据处理
+ *
+ * @author ruoyi
+ */
+public class TableSupport
+{
+    /**
+     * 当前记录起始索引
+     */
+    public static final String PAGE_NUM = "page_num";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "page_size";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "order_by_column";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "is_asc";
+
+    /**
+     * 分页参数合理化
+     */
+    public static final String REASONABLE = "reasonable";
+
+    /**
+     * 封装分页对象
+     */
+    public static PageDomain getPageDomain()
+    {
+        PageDomain pageDomain = new PageDomain();
+        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+        return pageDomain;
+    }
+
+    public static PageDomain buildPageRequest()
+    {
+        return getPageDomain();
+    }
+}