SpringBoot(六、任务,日志,多环境配置)
2019-05-14 本文已影响0人
强某某
任务
常见任务实现
1、常见定时任务 Java自带的java.util.Timer类
- timer:配置比较麻烦,时间延后问题
- timertask:不推荐
2、Quartz框架
- 配置更简单
- xml或者注解
3、SpringBoot使用注解方式开启定时任务
- 1)启动类里面 @EnableScheduling开启定时任务,自动扫描
- 2)定时任务业务类 加注解 @Component被容器扫描
- 3)定时执行的方法加上注解 @Scheduled(fixedRate=2000) 定期执行一次/s
方式三定时注解分类
-
1、cron 定时任务表达式 @Scheduled(cron="*/1 * * * * *") 表示每秒
-
2、fixedRate: 定时多久执行一次(上一次开始执行时间点后xx秒再次执行;)
-
3、fixedDelay: 上一次执行结束时间点后xx秒再次执行
-
4、fixedDelayString: 字符串形式,可以通过配置文件指定
@SpringBootApplication
@ServletComponentScan
@MapperScan("com.techsel.mapper")
@EnableScheduling //定时任务
@EnableAsync //异步任务
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class);
}
}
@Component
public class TestTask {
@Scheduled(fixedRate = 2000) //代表2S执行一次
public void show() {
System.out.println("当前时间: "+new Date());
}
@Scheduled(fixedDelay = 2000)//代表上次执行完毕之后2S再次执行,如果方法内部有延时,则下次执行时间间隔会超过2s
public void show1() {
System.out.println("当前时间: "+new Date());
}
@Scheduled(fixedRateString = "2000")
// @Scheduled(fixedDelayString = "2000")
public void show2() {
System.out.println("当前时间: "+new Date());
}
}
异步任务
应用场景: 用于处理log、发送邮件、短信
步骤
- 启动类里面使用@EnableAsync注解
- 任务类/方法上面添加@Async注解
注意点
- 1)要把异步任务封装到类里面,不能直接写到Controller
- 2)增加Future<String> 返回结果 AsyncResult<String>("task执行完成");
- 3)如果需要拿到结果 需要判断全部的 task.isDone()
@Component
@Async
public class TestAsyncTask {
public void task1() throws InterruptedException {
long begin=System.currentTimeMillis();
Thread.sleep(1000L);
long end=System.currentTimeMillis();
System.out.println("任务一耗时: "+(end-begin));
}
public void task2() throws InterruptedException {
long begin=System.currentTimeMillis();
Thread.sleep(2000L);
long end=System.currentTimeMillis();
System.out.println("任务二耗时: "+(end-begin));
}
public void task3() throws InterruptedException {
long begin=System.currentTimeMillis();
Thread.sleep(3000L);
long end=System.currentTimeMillis();
System.out.println("任务三耗时: "+(end-begin));
}
public Future<String> task4() throws InterruptedException {
long begin=System.currentTimeMillis();
Thread.sleep(2000L);
long end=System.currentTimeMillis();
System.out.println("任务四耗时: "+(end-begin));
return new AsyncResult<>("任务4");
}
public Future<String> task5() throws InterruptedException {
long begin=System.currentTimeMillis();
Thread.sleep(3000L);
long end=System.currentTimeMillis();
System.out.println("任务五耗时: "+(end-begin));
return new AsyncResult<>("任务4");
}
}
控制器类
@RequestMapping("/v3/task")
@RestController
public class TaskController {
@Autowired
private TestAsyncTask testAsyncTask;
//该方法执行时间不包含1,2,3个任务时间,直接返回
@GetMapping("async")
public String async() throws InterruptedException {
long begin=System.currentTimeMillis();
testAsyncTask.task1();
testAsyncTask.task2();
testAsyncTask.task3();
long end=System.currentTimeMillis();
System.out.println("执行:"+(end-begin));
return "ok";
}
//该方法也是异步任务只不过需要任务处理返回结果的时候使用
//时间是多个任务中时间耗时最长的
@GetMapping("asyncret")
public String asyncGetRes() throws InterruptedException {
long begin=System.currentTimeMillis();
Future<String> tash4= testAsyncTask.task4();
Future<String> tash5= testAsyncTask.task5();
for (;;) {
if (tash4.isDone() && tash5.isDone()) {
break;
}
}
long end=System.currentTimeMillis();
System.out.println("执行:"+(end-begin));
return "okrest";
}
}
如果把任务类的@Async注解添加上,则所有任务都会变成同步任务,耗时是累加和
日志记录(Logback)
Logback的核心对象
- Logger:日志记录器
- Appender:指定日志输出的目的地,目的地可以是控制台,文件
- Layout:日志布局 格式化日志信息的输出
日志级别:DEBUG < INFO < WARN < ERROR
log4j.properties
===========log4j示例===========
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=D://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=D://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
===========logback============
支持log4j.properties转换为logback.xml,不支持 log4j.xml转换为logback.xml
集成步骤
- application.yml中添加配置
#通过触发器,去控制什么时候进行热加载部署新的文件
spring:
devtools:
restart.trigger-file: trigger.txt
#自定义启动banner文件的路径
spring:
banner:
location: banner.txt
- logback-spring.xml
放到application.yml同级目录即可
默认加载加载配置顺序 logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</layout>
</appender>
<appender name="fileInfoApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</encoder>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 路径 -->
<fileNamePattern>app_log/log/app.info.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<appender name="fileErrorApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
</pattern>
</encoder>
<!-- 设置滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 路径 -->
<fileNamePattern>app_log/log/app.err.%d.log</fileNamePattern>
<!-- 控制保留的归档文件的最大数量,超出数量就删除旧文件,假设设置每个月滚动,
且<maxHistory> 是1,则只保存最近1个月的文件,删除之前的旧文件 -->
<MaxHistory>1</MaxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="consoleApp"/>
<appender-ref ref="fileInfoApp"/>
<appender-ref ref="fileErrorApp"/>
</root>
</configuration>
- 类中使用
@RestController
@RequestMapping("/api/v1")
public class UserController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("log")
public Object testLog(){
logger.debug("this is debug level");
logger.info("this is info level ");
logger.warn("this is warn level ");
logger.error("this is error level");
return JsonData.buildSuccess();
}
}
- 通过添加lombok的slf4j的辅助实现简化
@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("执行");
return true;
}
}
多环境配置
区分生产,测试,开发等多种环境
步骤(在resoureces文件夹下面的config文件夹下)
- 新建application.yml
#springboot多环境配置======begin
test:
url: local
#指定哪个profile
# 如下下面的不开启,则使用上面的默认配置
#spring.profiles.active=dev #dev就去找application-dev.yml,test就去找application-test.yml
#springboot多环境配置======end
- 新建application-dev.yml
test;
url: dev.com
- 新建application-test.yml
test;
url: test.com