使用方法:在调用sql语句前,调用 PageHelper.startPage(); 方法就行了(若依包装过了,调用startPage();方法)
1.pagehelper的功能
·实现数据库的分页查询
2.操作步骤
2.1在pom文件中加入maven依赖
com.github.pagehelper
pagehelper
5.1.10
2.2在mybatis主配置文件在加入plugin
·一定要注意这个插件的代码是写在environment配置的上面,而且是写在mybatis的主配置文件中,不是写在pom文件中的。
2.3在查询的代码中调用方法
PageHelper.startPage(1,3);
List students = dao.selectAll();
分页工具类(被若依包装过了)
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();
}
}
自定义线程池的三种方式
package com.ruoyi.framework.config;
import com.ruoyi.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
*
* @author ruoyi
**/
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);//最大空闲时间 超出则 删除线程
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService()
{
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy())
{
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
//使用
package com.ruoyi.framework.manager;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.ruoyi.common.utils.Threads;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
* 异步任务管理器
*
* @author ruoyi
*/
public class AsyncManager
{
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager(){}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me()
{
return me;
}
/**
* 执行任务
*
* @param task 任务
*/
public void execute(TimerTask task)
{
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/**
* 停止任务线程池
*/
public void shutdown()
{
Threads.shutdownAndAwaitTermination(executor);
}
}
Job(任务):是一个接口,有一个方法 void execute(JobExecutionContext context) ,可以通过实现该接口来定义需要执行的任务(具体的逻辑代码)。
JobDetail:Quartz每次执行Job时,都重新创建一个Job实例,会接收一个Job实现类,以便运行的时候通过newInstance()的反射调用机制去实例化Job。JobDetail是用来描述Job实现类以及相关静态信息,比如任务在scheduler中的组名等信息。
Trigger(触发器):描述触发Job执行的时间触发规则实现类SimpleTrigger和CronTrigger可以通过crom表达式定义出各种复杂的调度方案。
Calendar:是一些日历特定时间的集合。一个Trigger可以和多个 calendar关联,比如每周一早上10:00执行任务,法定假日不执行,则可以通过calendar进行定点排除。
Scheduler(调度器):代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。Scheduler可以将Trigger绑定到某一JobDetail上,这样当Trigger被触发时,对应的Job就会执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
————————————————
版权声明:本文为CSDN博主「李巴巴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52850476/article/details/123140549
应用场景
1.更新缓存
2.读写日志
3.发送邮件
4.定期将redis数据持久化至Mysql中,保证两者之间的数据同步,兼顾效率与数据安全
5.使用Quartz定时器定期将体温数据持久化到本地
看的一些视频
Quartz定时任务 高可用 超简易上手
这个人对Quartz进行了封装,上手 更简单
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-79Vu6dnG-1666788050355)(D:/GitCode/tuchuang/img/image-20221012185653662.png)]
2.1 实现org.quartz.Job接口
2.2 添加调度注解,使用注解CronExp添加任务的调度策略(任务id,执行频率), 使用注解@Component将任务注入到容器中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hxgQGm4i-1666788050356)(D:/GitCode/tuchuang/img/image-20221012185941557.png)]
2.2重写execute方法
在日常项目运行中,我们总会有需求在某一时间段周期性的执行某个动作,比如每天在某个时间段导出报表,或者每隔多久统计一次现在在线的用户量等
在springBoot中 有java自带的java.util.timer类,SpringBoot自带的Scheduled来实现,也有强大的调度器Quarzet。Scheduled在Spring3.x引入,默认SpringBoot自带该功能,使用起来也很简单,在启动类级别添加@EnableScheduling 注解即可引入定时环境任务。但遗憾的是Scheduled默认不支持分布式环境,这里主要讲解Quartz始终调度框架与SpringBoot集成。
1.环境整合配置–引入dependency
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ehSfs2xJ-1666788050356)(D:/GitCode/tuchuang/img/image-20221012184549443.png)]
2.源代码添加
定义job,需要实现Job接口 ,job接口来自Quarzet
重写execute方法,把任务写在这里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bm4TOVqo-1666788050357)(D:/GitCode/tuchuang/img/image-20221012184628562.png)]
构建配置调度类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tkIEeNE-1666788050357)(D:/GitCode/tuchuang/img/image-20221012184927234.png)]
https://www.bilibili.com/video/BV1Ek4y117mm/?spm_id_from=333.337.search-card.all.click&vd_source=e985eba9865594055b36f262b6a2a3de
https://www.bilibili.com/video/BV1KT4y1G7hs/?spm_id_from=333.337.search-card.all.click&vd_source=e985eba9865594055b36f262b6a2a3de
SpringBoot实战项目教程】AOP记录日志,面试技术亮点,10分钟速成
1.添加注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-baE9itqG-1666788050359)(D:/GitCode/tuchuang/img/image-20221014204425924.png)]
2.开发注解
![在这里插入图片描述](https://img-blog.csdnimg.cn/714b7042e6784d0c949ccc971d8511ee.png#pic_center)定义切面 定义了通知和切点的关系 ,上面那个注解就是切点
@Pointcut是切入点,后面的表达式代表 只要标注了LogAnnotation这个注解的都是切入点 pt(), 对切入点pt()的通知方式为环绕通知 ,表达式有很多种
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9L3vBpGo-1666788050360)(D:/GitCode/tuchuang/img/image-20221014204821739.png)]
在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。
全局接口异常处理,与@ExceptionHandler(value = Exception.class)
一起使用可以全局捕获指定异常。
http://www.icodebang.com/article/252255.html
看@RestControllerAdvice源码可以知道,它就是@ControllerAdvice和@ResponseBody的合并。此注解通过对异常的拦截实现的统一异常返回处理,如果大家在项目中有类似的需求,不妨试一下,好用又方便。
当自定义类加@ControllerAdvice注解时,方法需要返回json数据时,每个方法还需要添加@ResponseBody注解
当自定义类加@RestControllerAdvice注解时,方法自动返回json数据,每个方法无需再添加@ResponseBody注解
若依的全局异常处理类
package com.ruoyi.framework.web.exception;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
/**
* 全局异常处理器
*
* @author ruoyi
*/
@RestControllerAdvice
public class GlobalExceptionHandler
{
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 权限校验异常
*/
@ExceptionHandler(AccessDeniedException.class)
public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
}
/**
* 请求方式不支持
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return AjaxResult.error(e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(ServiceException.class)
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
}
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public AjaxResult handleBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return AjaxResult.error(message);
}
/**
* 自定义验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
{
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return AjaxResult.error(message);
}
/**
* 演示模式异常
*/
@ExceptionHandler(DemoModeException.class)
public AjaxResult handleDemoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
}
}