「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
5、@Schedule
定时任务几乎是项目的标配了, SpringBoot内置了Sping Schedule定时框架,通过注解驱动方式添加所注解方法到定时任务,根据配置定时信息定时执行
主要是以下两步:
1、开启定时器
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableCircuitBreaker
@EnableCaching
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2、在方法上加上注解
//每天凌晨1点执行
@Scheduled(cron = "0 0 1 * * ?")
public void doTask() {
}
6、async异步调用
异步调用主要处理一些不要求及时返回的任务,springboot提供了支持
SpringBoot中使用 async实现异步调用
基于注解的使用方式包括如下三步:
- 启动类加上@EnableAsync(也可以在配置类中加上)
- 配置类中完成异步线程池的导入(这一个可以不要,采用默认的)
- 需要异步调用的方法加上@Async
定义线程池
package com.aispeech.bj.bams.msproduct.config;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync(mode = AdviceMode.ASPECTJ)
public class ExecutorConfig {
/** Set the ThreadPoolExecutor's core pool size. */
private int corePoolSize = 10;
/** Set the ThreadPoolExecutor's maximum pool size. */
private int maxPoolSize = 300;
/** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */
private int queueCapacity = 10;
@Bean
public Executor myAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("MyExecutor-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
使用异步 @Async 注解
@Async("myAsync")
void notifyProductInfo(String thirdPartyId, ThirdPartyProductVO thirdPartyProductVO) {}
7、request 的获取方式和线程安全
request 是来自前端的请求,怎么才能安全的获取request,线程安全的request 才能取出正确的数据,主要有下面几种方式
1、静态类获取
HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
2、函数参数
Controller中获取request对象后,如果要在其他方法中(如service方法、工具类方法等)使用request对象,需要在调用这些方法时将request对象作为参数传入
此时request对象是方法参数,相当于局部变量,毫无疑问是线程安全的。
@RequestMapping("/test")
public void test(HttpServletRequest request) {
......
}
3、自动注入
@Autowired
private HttpServletRequest request; //自动注入request
对象是线程局部变量(ThreadLocal),因此request对象也是线程局部变量;这就保证了request对象的线程安全性。
不会有线程安全问题的 实际上spring 注入的是一个代理类