1、ylb
1.1页数校验
在common模块util包,创建一个工具类CommonUtil类:
package com.bjpowernode.common.util;
public class CommonUtil {
/*处理pageNo*/
public static int defaultPageNo(Integer pageNo) {
int pNo = pageNo;
if (pageNo == null || pageNo < 1) {
pNo = 1;
}
return pNo;
}
/*处理pageSize*/
public static int defaultPageSize(Integer pageSize) {
int pSize = pageSize;
if (pageSize == null || pageSize < 1) {
pSize = 1;
}
return pSize;
}
}
1.2 service实现类
package com.bjpowernode.dataservice.service;
import com.bjpowernode.api.model.ProductInfo;
import com.bjpowernode.api.pojo.MultiProduct;
import com.bjpowernode.api.service.ProductService;
import com.bjpowernode.common.constants.YLBConstant;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.dataservice.mapper.ProductInfoMapper;
import org.apache.dubbo.config.annotation.DubboService;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@DubboService(interfaceClass = ProductService.class,version = "1.0")
public class ProductServiceImpl implements ProductService {
@Resource
private ProductInfoMapper productInfoMapper;
/*按类型分页查询产品*/
@Override
public List<ProductInfo> queryByTypeLimit(Integer pType, Integer pageNo, Integer pageSize) {
List<ProductInfo> productInfos = new ArrayList<>();
if( pType == 0 || pType == 1 || pType == 2){
pageNo = CommonUtil.defaultPageNo(pageNo);
pageSize = CommonUtil.defaultPageSize(pageSize);
int offset = (pageNo - 1) * pageSize;
productInfos = productInfoMapper.selectByTypeLimit(pType, offset, pageSize);
}
return productInfos;
}
/*某个产品类型的记录总数*/
@Override
public Integer queryRecordNumsByType(Integer pType) {
Integer counts = 0;
if( pType == 0 || pType == 1 || pType == 2){
counts = productInfoMapper.selectCountByType(pType);
}
return counts;
}
}
2、reggie
2.1 配置MP分页插件
package com.itzq.reggie.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置MP的分页插件
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
2.2 page方法
在controller类上,编写page方法:
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
log.info("page = {}, pageSize = {}, name = {}",page,pageSize,name);
//构造分页构造器
Page pageInfo = new Page(page, pageSize);
//构造条件构造器
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
//添加过滤条件
queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
//添加排序添加
queryWrapper.orderByDesc(Employee::getUpdateTime);
//执行查询
employeeService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
3、ruoyi
3.1 PageHelper分页插件
在admin模块,application.yml中配置分页插件:
# 项目相关配置
ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.8.6
# 版权年份
copyrightYear: 2023
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8080
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数,默认为100
accept-count: 1000
threads:
# tomcat最大线程数,默认为200
max: 800
# Tomcat启动初始化的线程数,默认值10
min-spare: 100
# 日志配置
logging:
level:
com.ruoyi: debug
org.springframework: warn
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间(默认10分钟)
lockTime: 10
# Spring配置
spring:
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: druid
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
# 服务模块
devtools:
restart:
# 热部署开关
enabled: true
# redis 配置
redis:
# 地址
host: localhost
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期(默认30分钟)
expireTime: 30
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
helperDialect: mysql
supportMethodsArguments: true
params: count=countSql
# Swagger配置
swagger:
# 是否开启swagger
enabled: true
# 请求前缀
pathMapping: /dev-api
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
3.2 分页工具类PageUtils
在common模块,utils包下,分页工具类PageUtils
package com.ruoyi.common.utils;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
* 分页工具类
*
* @author ruoyi
*/
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();
}
}
3.3 封装分页对象getPageDomain()
在common模块,core.page包下,表格数据处理TableSupport
package com.ruoyi.common.core.page;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ServletUtils;
/**
* 表格数据处理
*
* @author ruoyi
*/
public class TableSupport
{
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
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();
}
}
3.4 分页数据
在common模块,core.page包下,分页数据PageDomain
用于传递给下列方法所需的参数(pageNum, pageSize, orderBy)、(reasonable)
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
package com.ruoyi.common.core.page;
import com.ruoyi.common.utils.StringUtils;
/**
* 分页数据
*
* @author ruoyi
*/
public class PageDomain
{
/** 当前记录起始索引 */
private Integer pageNum;
/** 每页显示记录数 */
private Integer pageSize;
/** 排序列 */
private String orderByColumn;
/** 排序的方向desc或者asc */
private String isAsc = "asc";
/** 分页参数合理化 */
private Boolean reasonable = true;
public String getOrderBy()
{
if (StringUtils.isEmpty(orderByColumn))
{
return "";
}
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum()
{
return pageNum;
}
public void setPageNum(Integer pageNum)
{
this.pageNum = pageNum;
}
public Integer getPageSize()
{
return pageSize;
}
public void setPageSize(Integer pageSize)
{
this.pageSize = pageSize;
}
public String getOrderByColumn()
{
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn)
{
this.orderByColumn = orderByColumn;
}
public String getIsAsc()
{
return isAsc;
}
public void setIsAsc(String isAsc)
{
if (StringUtils.isNotEmpty(isAsc))
{
// 兼容前端排序类型
if ("ascending".equals(isAsc))
{
isAsc = "asc";
}
else if ("descending".equals(isAsc))
{
isAsc = "desc";
}
this.isAsc = isAsc;
}
}
public Boolean getReasonable()
{
if (StringUtils.isNull(reasonable))
{
return Boolean.TRUE;
}
return reasonable;
}
public void setReasonable(Boolean reasonable)
{
this.reasonable = reasonable;
}
}
3.5 排序SQL处理
在common模块,utils.sql包下,sql操作工具类SqlUtil
package com.ruoyi.common.utils.sql;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.StringUtils;
/**
* sql操作工具类
*
* @author ruoyi
*/
public class SqlUtil
{
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 检查字符,防止注入绕过
*/
public static String escapeOrderBySql(String value)
{
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new UtilException("参数不符合规范,不能进行查询");
}
return value;
}
/**
* 验证 order by 语法是否符合规范
*/
public static boolean isValidOrderBySql(String value)
{
return value.matches(SQL_PATTERN);
}
/**
* SQL关键字检查
*/
public static void filterKeyword(String value)
{
if (StringUtils.isEmpty(value))
{
return;
}
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
{
throw new UtilException("参数存在SQL注入风险");
}
}
}
}
3.6 controller上设置分页方法
- 请求分页数据
- 请求排序数据
- 清理分页的线程变量
- 响应请求分页数据
在common模块,core.controller包下,web通用数据处理BaseController
package com.ruoyi.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
* web层通用数据处理
*
* @author ruoyi
*/
public class BaseController
{
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageUtils.startPage();
}
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/**
* 清理分页的线程变量
*/
protected void clearPage()
{
PageUtils.clearPage();
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
/**
* 返回成功
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
* 返回失败消息
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
* 返回成功消息
*/
public AjaxResult success(Object data)
{
return AjaxResult.success(data);
}
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
* 返回警告消息
*/
public AjaxResult warn(String message)
{
return AjaxResult.warn(message);
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
/**
* 页面跳转
*/
public String redirect(String url)
{
return StringUtils.format("redirect:{}", url);
}
/**
* 获取用户缓存信息
*/
public LoginUser getLoginUser()
{
return SecurityUtils.getLoginUser();
}
/**
* 获取登录用户id
*/
public Long getUserId()
{
return getLoginUser().getUserId();
}
/**
* 获取登录部门id
*/
public Long getDeptId()
{
return getLoginUser().getDeptId();
}
/**
* 获取登录用户名
*/
public String getUsername()
{
return getLoginUser().getUsername();
}
}
在实际controller上,admin模块,web.controller.pill包下:
package com.ruoyi.web.controller.pill;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.pill.domain.PillDrug;
import com.ruoyi.pill.service.IPillDrugService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 药品信息Controller
*
* @author ljh
* @date 2023-07-06
*/
@RestController
@RequestMapping("/pill/drug")
public class PillDrugController extends BaseController
{
@Autowired
private IPillDrugService pillDrugService;
/**
* 查询药品信息列表
*/
@PreAuthorize("@ss.hasPermi('pill:drug:list')")
@GetMapping("/list")
public TableDataInfo list(PillDrug pillDrug)
{
startPage();
List<PillDrug> list = pillDrugService.selectPillDrugList(pillDrug);
return getDataTable(list);
}
/**
* 导出药品信息列表
*/
@PreAuthorize("@ss.hasPermi('pill:drug:export')")
@Log(title = "药品信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, PillDrug pillDrug)
{
List<PillDrug> list = pillDrugService.selectPillDrugList(pillDrug);
ExcelUtil<PillDrug> util = new ExcelUtil<PillDrug>(PillDrug.class);
util.exportExcel(response, list, "药品信息数据");
}
/**
* 获取药品信息详细信息
*/
@PreAuthorize("@ss.hasPermi('pill:drug:query')")
@GetMapping(value = "/{drugId}")
public AjaxResult getInfo(@PathVariable("drugId") Long drugId)
{
return success(pillDrugService.selectPillDrugByDrugId(drugId));
}
/**
* 新增药品信息
*/
@PreAuthorize("@ss.hasPermi('pill:drug:add')")
@Log(title = "药品信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody PillDrug pillDrug)
{
return toAjax(pillDrugService.insertPillDrug(pillDrug));
}
/**
* 修改药品信息
*/
@PreAuthorize("@ss.hasPermi('pill:drug:edit')")
@Log(title = "药品信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody PillDrug pillDrug)
{
return toAjax(pillDrugService.updatePillDrug(pillDrug));
}
/**
* 删除药品信息
*/
@PreAuthorize("@ss.hasPermi('pill:drug:remove')")
@Log(title = "药品信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{drugIds}")
public AjaxResult remove(@PathVariable Long[] drugIds)
{
return toAjax(pillDrugService.deletePillDrugByDrugIds(drugIds));
}
}