文章目录
- 第一节、SpringBoot2.x常用注解
- 第二节、SpringBoot2.x目录文件结构和官方推荐的目录规范、静态资源访问
- 第三节、SpringBoot2.x启动类位置常见形式
- 第四节、SpringBoot2.x启动方式和部署
- 第五节、SpringBoot2.x项目打包后的Jar包目录结构
- 第六节、SpringBoot2.x之定制JSON字段
- 第七节、springboot2.x热部署配置
- 第八节、SpringBoot2.x配置文件
- 第九节、SpringBoot2.x注解配置文件映射属性和实体类
- 第十节、软件开发中常用测试方法
- 第十一节、SpringBoot2.x中单元测试的使用
- 第十二节、Springboot2.X全局异常处理
- 第十三节、Servlet3.0和SpringBoot2.X过滤器-拦截器
- 第十四节、回归本质Servlet3.0的注解原生Servlet实战
- 第十五节、Servlet3.0+SpringBoot2.X 注解Listener常用监听器
- 第十六节、SpringBoot2.X拦截器配置
- 第十七节、SpringBoot2.X starter和模板引擎介绍
- 第十八节、SpringBoot2.X整合模板引擎freemarker
- 第十九节、SpringBoot2.X整合模板引擎thymeleaf
- 第二十节、SpringBoot2.X定时任务schedule
- 第二十一节、SpringBoot2.x异步任务EnableAsync
第一节、SpringBoot2.x常用注解
-
@Controller:
- 作用:用于标记这个类是一个控制器,返回页面的时候使用;如果要返回JSON,则需要使用@ResponseBody才可以
-
@RestController
- 作用:用于标记这个类是一个控制器,返回JSON数据的时候使用,如果使用这个注解,则接口返回数据会被序列化为JSON
- 所以RestController=@Controller+@ResponseBody
-
@RequestMapping
- 作用:路由映射,用于类上做一级路径;常用于某个方法上做子路径。
-
@SpringBootApplication
-
作用:用于标记SpringBoot应用,里面包含多个子注解,即:
@SpringBootApplication = @Configuration+@EnableAutoConfiguration+@ComponentScan @Configuration: 主要标注在某个类上,⽤用于spring扫描注入,⼀般结合@Bean使⽤用 @EnableAutoConfiguration: 启用Spring的自动加载配置,⾃自动载⼊入应用程序所需的所有Bean @ComponentScan:告诉spring扫描包的范围,默认是Applocation类所在的全部⼦子包,可以指定 其他包 @ComponentScan({"net.xdclass.package1","net.xdclass.package2"})
-
-
@GetMapping=@RequestMapping(method=RequestMethod.GET)
- PostMapping:同理
- PutMapping
- DeleteMapping
-
@RequestBody:标注Action的参数,表示可以将请求过来的json参数映射到对象中
第二节、SpringBoot2.x目录文件结构和官方推荐的目录规范、静态资源访问
- 主要目录:
src/main/java:存放代码
src/main/resources
static: 存放静态文件,比如 css、js、image, (访问方式 http://localhost:8080/js/main.js)
templates:存放静态⻚面jsp,html,tpl
config:存放配置文件,application.properties
resources:
-
同一个文件的加载顺序,静态资源文件SpringBoot默认会挨个从以下
- META/resources
- resources
- static
- public
里面是否存在相应的资源,如果有则直接返回,不在默认加载的目录,则找不到
-
默认配置:
- spring.resources.static-locations = classpath:/META-
INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ - 如果需要特殊配置,在application.properties配置文件中覆盖该变量重新配置即可
- spring.resources.static-locations = classpath:/META-
-
基本互联网企业静态资源文件一般存储在CDN(如html,css,图片等),
-
CDN:内容分发网络
-
文件服务器:阿里云OSS
第三节、SpringBoot2.x启动类位置常见形式
- 三种形式
- 当启动类和controller在同一类中时,在该类上添加注解@Controller即可
- 当启动类跟Controller分开时,启动类要放在根目录下,启动类上只需要加@SpringBootApplication注解即可。
- 当启动类和controller分开时,如果启动类在非根目录下,需要在启动类中增加注解@ComponentScan注解,并配置需要扫码的包,如(basePackages={“com.test.controller”,“com.test.service”})
- 工作中推荐第二种方式,不然漏配置扫描包,项目庞大,出现问题很难排查
第四节、SpringBoot2.x启动方式和部署
-
IDEA开发中启动
- 本地开发中常用
-
外置Tomcat中启动
- 接近淘汰
- tomcat版本兼容问题复杂
- 微服务容器化部署复杂
-
Jar方式打包启动
- 官方推荐,工作中最常用
- 步骤:pom文件新增maven插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> 如果没有加,则执行jar包,报错如下: java -jar spring-boot-demo-0.0.1-SNAPSSHOT.jar no main mainfest attribute,in spring-boot-demo-0.0.1SNAPSHOT.jar
-
必备打包、启动命令
构建:mvn install 构建跳过测试类 mvn install -Dmaven.test.skip=true target⽬目录下有对应的jar包就是打包后项⽬目 进到对应的target⽬目录启动 java -jar xxxxx.jar 即可 想后台运⾏行行,就⽤用守护进程 nohup java -jar xxx.jar &
第五节、SpringBoot2.x项目打包后的Jar包目录结构
- 获取对应的jar包,解压
- 解压后项目结构
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
第六节、SpringBoot2.x之定制JSON字段
-
常⽤框架 阿里 fastjson,⾕歌gson等
-
序列化为Json,
- 性能:Jackson > FastJson > Gson > Json-lib 同个结构
- Jackson、FastJson、Gson类库各有优点,各有⾃己的专长
- 空间换时间,时间换空间
-
jackson处理相关字段
- 指定字段不返回:@JsonIgnore
-
指定⽇期格式:@JsonFormat(pattern=“yyyy-MM-dd hh:mm:ss”,locale=“zh”,timezone=“GMT+8”)
- 空字段不返回:@JsonInclude(Include.NON_NULL)
- 指定别名:@JsonProperty
-
开发功能:视频创建时间返回自定义格式;过滤用户敏感信息
-
序列化和反序列化操作
//序列化操作
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(list);
System.out.println(jsonStr);
//反序列化操作
List<Video> temp = objectMapper.readValue(jsonStr,List.class);
第七节、springboot2.x热部署配置
-
什么是热部署
- 应用正在运行的时候升级功能, 不需要重新启动应用
- 对于Java应用程序来说, 热部署就是在运行时更新Java类文件
-
好处:不需要重新手工启动应用,提高本地开发效率
-
常⻅实现热部署的方式
- Jrebel
- Spring Loaded
- spring-boot-devtools
-
SpringBoot2.X结合dev-tool 实现IDEA项目热部署
-
步骤
- pom文件添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork><!--必须添加这个配置--> </configuration> </plugin> </plugins> </build>
- 在"settings" --> “Build,Execution,Deployment”–>"Compiler"中勾选”Build project automatically“选项
- 打开Registry(快捷键ctrl+shift+alt+/),勾选compiler.automake.allow.when.app.runing选项
-
第八节、SpringBoot2.x配置文件
- 常见配置文件格式
xml、porterties、json、yml
-
SpringBoot里面常用xx.yml
- YAML(Yet Another Markup Language)
- 写 YAML 要比写 XML 快得多(无需关注标签或引号) 使用空格 Space 缩进表示分层,不同层次之间的缩进可以使⽤不同的空格数目
- 注意:key后面的冒号,后面一定要跟一个空格,树状结构
server:
port: 8080 //设置启动端口号为8080
house:
family:
name: Doe
parents:
- John
- Jane
children:
- Paul
- Mark
- Simone
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345
-
Springboot⾥⾯常用 xx.properties(推荐)
- Key=Value格式
- 语法简单,不容易出错
server.port=8082 #session失效时间,30m表示30分钟 server.servlet.session.timeout=30m # Maximum number of connections that the server accepts and processes at any given time. server.tomcat.max-connections=10000 # Maximum size of the HTTP post content. server.tomcat.max-http-post-size=2MB server.tomcat.max-http-form-post-size=2MB # Maximum amount of worker threads server.tomcat.max-threads=200
-
官⽅文档配置
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties -
如果需要修改,直接复制对应的配置文件加到application.properties⾥面,一般不需要调整
第九节、SpringBoot2.x注解配置文件映射属性和实体类
-
配置⽂文件加载
-
方式⼀
1、Controller上⾯面配置 @PropertySource({“classpath:resource.properties”})
2、增加属性 @Value(“${test.name}”) private String name; -
方式⼆:实体类配置文件
1、添加 @Component 注解;
2、使用 @PropertySource 注解指定配置文件位置;
3、使用 @ConfigurationProperties 注解,设置相关属性;
4、必须 通过注入IOC对象Resource 进来,才能在类中使用获取的配置文件值。
@Autowired private ServerSettings serverSettings;
例例⼦子: @Configuration @ConfigurationProperties(prefix="wxpay") @PropertySource(value="classpath:wxconfig.properties") public class WXConfig { @Value("${appid}") private String payAppid; @Value("${secret}") private String paySecret; @Value("${mechid}") private String payMechId; public String getPayAppid() { return payAppid; } public void setPayAppid(String payAppid) { this.payAppid = payAppid; } public String getPaySecret() { return paySecret; } public void setPaySecret(String paySecret) { this.paySecret = paySecret; } public String getPayMechId() { return payMechId; } public void setPayMechId(String payMechId) { this.payMechId = payMechId; } }
-
第十节、软件开发中常用测试方法
-
简介:讲解公司里⾯软件开发测试
需求分析->设计->开发->测试->上线 -
测试⾥⾯的种类
-
单元测试:
完成最小的软件设计单元的验证工作,目标是确保模块被正确的编码
-
黑盒测试
不考虑内部结构,主要测试功能是否满足需求 -
白盒测试
针对代码级别,测试开发工程师一般具备白盒测试能⼒,针对程序内部的逻辑结构 进⾏代码级别的测试 -
回归测试
对原先提出的缺陷进行二次验证,开发人员修复后进行二次的验证 -
集成测试
测试模块和模块之间的整合,且测试主要的业务功能 -
系统测试
针对整个产品系统进行的测试,验证系统是否满足产品业务需求
-
第十一节、SpringBoot2.x中单元测试的使用
步骤:
* 引入相关依赖
<!--springboot程序测试依赖,如果是⾃自动创建项目默认添加-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
* 配置相关注解
@RunWith(SpringRunner.class) //底层⽤用junit SpringJUnit4ClassRunner
@SpringBootTest(classes={XdclassApplication.class})//启动整个springboot⼯工程
public class SpringBootTests {
}
- 常用单元测试的注解
* @Before:测试前执行- Test
- After:测试后执行
- 断言
- 判断程序结果是否符合预期
- Springboot单元测试Controller层接⼝口
@RunWith(SpringRunner.class) //底层⽤用junit SpringJUnit4ClassRunner
@SpringBootTest(classes={XdclassApplication.class})//启动整个springboot⼯工程
public class SpringBootTests {
@Autowired
private UserController userController;
@Test
public void loginTest(){
User user = new User();
user.setUsername("jack");
user.setPwd("1234");
JsonData jsonData = userController.login(user);
System.out.println(jsonData.toString());
TestCase.assertEquals(0,jsonData.getCode());
}
}
运行loginTest()方法,如果程序运行结果不符合预期,则运行结果将会给出预期结果和实际运行结果之间的差异
- SpringBoot单元测试Service
//此处省略类定义以及相应注解,写法同上Controller
@Autowired
private VideoService videoService;
@Test
public void testVideoList(){
List<Video> videoList = videoService.listVideo();
TestCase.assertTrue(videoList.size()>0);
}
-
MockMvc调用Controller层API接⼝口
使用步骤:
- 在测试类上增加类注解 @AutoConfigureMockMvc
- 注⼊入⼀一个MockMvc类
- 编写代码调用相关API :
- perform执行⼀一个RequestBuilder请求
- andExpect:添加ResultMatcher->MockMvcResultMatchers验证规则
- andReturn:最后返回相应的MvcResult->Response
-
使用示例:
@RunWith(SpringRunner.class) //底层⽤用junit SpringJUnit4ClassRunner @SpringBootTest(classes={XdclassApplication.class})//启动整个springboot⼯工程 @AutoConfigureMockMvc public class SpringBootTests { @Autowired private MockMvc mockMvc; @Test public void testVideoListApi()throws Exception{ MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/pub/video/list")) .andExpect(MockMvcResultMatchers.status().isOk()).andReturn(); int status = mvcResult.getResponse().getStatus(); System.out.println(status); //会乱码 //String result = mvcResult.getResponse().getContentAsString(); // 使用下面这个,增加 编码 说明,就不会乱码打印 String result = mvcResult.getResponse().getContentAsString(Charset.forName("utf-8")); System.out.println(result); } }
第十二节、Springboot2.X全局异常处理
-
配置步骤:
- 类添加注解
- @ControllerAdvice,如果需要返回json数据,则方法需要加@ResponseBody
- @RestControllerAdvice, 默认返回json数据,方法不需要加@ResponseBody
- 方法添加处理理器器
- 捕获全局异常,处理所有不可知的异常
@ExceptionHandler(value=Exception.class)
- 捕获全局异常,处理所有不可知的异常
- 使用示例
@RestControllerAdvice public class CustomExtHandler { @ExceptionHandler(value = Exception.class) JsonData handlerException(Exception e, HttpServletRequest request){ return JsonData.buildError(-2,"服务端出问题了!"); } } //如果需要返回错误页面,则将@RestControllerAdvice改成@ControllerAdvice
- 类添加注解
第十三节、Servlet3.0和SpringBoot2.X过滤器-拦截器
-
SpringBoot2.X里面的过滤器
* ApplicationContextHeaderFilter * OrderedCharacterEncodingFilter * OrderedFormContentFilter * OrderedRequestContextFilter
-
那么多过滤器,哪个优先级高呢?
-
Ordered.HIGHEST_PRECEDENCE Ordered.LOWEST_PRECEDENCE
低位值意味着更高的优先级 Higher values are interpreted as lower priority
-
自定义Filter,避免和默认的Filter优先级一样,不然会冲突
-
注册Filter配置两种⽅方式
- bean FilterRegistrationBean
- Servlet3.0 webFileter
-
-
使用Servlet3.0注解开发⾃自定义的过滤器
- 使用Servlet3.0的注解进行配置步骤
- 启动类里⾯增加 @ServletComponentScan,进行扫描
- 新建一个Filter类,implements Filter,并实现对应的接⼝
- @WebFilter 标记一个类为filter,被spring进行扫描
- urlPatterns:拦截规则,支持正则
- 控制chain.doFilter的方法的调用,来实现是否通过放行
- 不放行,web应用resp.sendRedirect(“/index.html”) 或者 返回json字符串
- 使用Servlet3.0的注解进行配置步骤
-
filter使用场景:权限控制、用户登录状态控制,也可以交给拦截器处理等
-
登陆验证filter使用示例
@WebFilter(urlPatterns = {"/api/v1/pri/*"},filterName = "loginFilter")
public class LoginFilter implements Filter {
//Json转换工具类
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 容器加载时候
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init LoginFilter");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String token = req.getHeader("token");
if (StringUtils.isEmpty(token)) {
token = req.getParameter("token");
}
if(!StringUtils.isEmpty(token)){
User user = UserServiceImpl.sessionMap.get(token);
if(user!=null){
filterChain.doFilter(req,resp);
}else{
JsonData jsonData = JsonData.buildError(-2,"登录失败,Token无效");
String jsonStr = objectMapper.writeValueAsString(jsonData);
renderJson(resp, jsonStr);
}
}else{
JsonData jsonData = JsonData.buildError(-3,"未登录");
String jsonStr = objectMapper.writeValueAsString(jsonData);
renderJson(resp, jsonStr);
}
}
//将json数据返回页面
private void renderJson(HttpServletResponse response,String json){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try(PrintWriter writer = response.getWriter()){
writer.print(json);
}catch (Exception e){
e.printStackTrace();
}
}
}
注意:使用filter,在application启动入口加入@ServletComponentScan
第十四节、回归本质Servlet3.0的注解原生Servlet实战
- 使用 Servlet3.0的注解自定义原生Servlet
- javaweb的使用doPost和doGet方法使用Servlet3.0替代更轻量级
@WebServlet(name = "userServlet", urlPatterns = "/api/v1/test/customs" )
class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("this is my custom servlet");
writer.flush();
writer.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doGet(req,resp);
}
}
第十五节、Servlet3.0+SpringBoot2.X 注解Listener常用监听器
- 监听器:应用启动监听器,会话监听器,请求监听器
- 作用
- ServletContextListener 应用启动监听
- HttpSessionLisener 会话监听
- ServletRequestListener 请求监听
- 常⽤的监听器 ServletContextListener、HttpSessionListener、ServletRequestListener)
- 使用示例
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("======contextDestroyed========");
}
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("======contextInitialized========");
}
}
第十六节、SpringBoot2.X拦截器配置
- 拦截器: 和过滤器用途基本类似
- SpringBoot2.x使用步骤
- SpringBoot2.X 新版配置拦截器 implements WebMvcConfigurer
- 自定义拦截器 HandlerInterceptor
- preHandle:调⽤Controller某个方法之前
- postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法
- afterCompletion:不管有没有异常,这个afterCompletion都会被调用,用于资源清理
- 自定义拦截器 HandlerInterceptor
- 按照注册顺序进行拦截,先注册,先被拦截
- SpringBoot2.X 新版配置拦截器 implements WebMvcConfigurer
- 拦截器不生效常见问题:
- 是否有加@Configuration
- 拦截路径是否有问题 ** 和 *
- 拦截器最后路径一定要 /** 如果是⽬目录的话则是 /*/
- 场景:权限控制、用户登录状态控制等
- 和Filter过滤器的区别
Filter和Interceptor二者都是AOP编程思想的体现,功能基本都可以实现
拦截器功能更强大些,Filter能做的事情它都能做
Filter在只在Servlet前后起作用,而Interceptor够深入到方法前后、异常抛出前后等
filter依赖于Servlet容器即web应⽤用中,而Interceptor不依赖于Servlet容器所以可以运行在多种环境。
在接口调用的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
Filter和Interceptor的执行顺序
过滤前->拦截前->action执行->拦截后->过滤后
- 配置不拦截某些路路径
registry.addInterceptor(new
LoginIntercepter()).addPathPatterns("/api/v1/pri/**")
//配置不拦截某些路径,比如静态资源
.excludePathPatterns("/**/*.html","/**/*.js");
第十七节、SpringBoot2.X starter和模板引擎介绍
- SpringBoot2.X常⽤用start介绍
- starter主要简化依赖⽤用的
- spring-boot-starter-web->里面包含多种依赖
- 查看 pom⽂文件 spring-boot-starter-parent -> spring-boot-dependencies 里⾯综合的很多依赖包
- 常用是starter:thymeleaf、freemarker、web等
- starter主要简化依赖⽤用的
- JSP(后端渲染,消耗性能)
Java Server Pages 动态网页技术,由应用服务器中的JSP引擎来编译和执行,再将生成的整个页面返回给客户端
可以写java代码
支持表达式语言(el、jstl)
内建函数
JSP->Servlet(占用JVM内存)permSize
javaweb官⽅方推荐
springboot官⽅不推荐
- Freemarker
FreeMarker Template Language(FTL) 文件一般保存为 xxx.ftl
严依赖MVC模式,不依赖Servlet容器(不占用JVM内存)
支持内建函数
- Thymeleaf (主推)
轻量级的模板引擎(复杂逻辑业务的不推荐,解析DOM或者XML会占用多的内存)
可以直接在浏览器中打开且正确显示模板页面
直接是html结尾,直接编辑xdlcass.net/user/userinfo.html
第十八节、SpringBoot2.X整合模板引擎freemarker
步骤:
- 引入Freemarker相关maven依赖
<!-- 引⼊入freemarker模板引擎的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
- Freemarker基础配置
# 是否开启thymeleaf缓存,本地为false,生产建议为true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.allow-request-override=false
spring.freemarker.check-template-location=true
#类型
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
#文件后缀
spring.freemarker.suffix=.ftl
#路路径
spring.freemarker.template-loader-path=classpath:/templates/
- 建⽴文件夹
1)src/main/resources/templates/fm/user/
2)建立一个index.ftl
3)user文件夹下面建立一个user.html
- 简单测试代码编写和访问
第十九节、SpringBoot2.X整合模板引擎thymeleaf
- 官⽹网地址:https://www.thymeleaf.org/doc/articles/thymeleaf3migration.html
整合步骤:
- 引入thymeleaf相关maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- thymeleaf基础配置
#开发时关闭缓存,不然没法看到实时页面
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML5
#前缀
spring.thymeleaf.prefix=classpath:/templates/
#编码
spring.thymeleaf.encoding=UTF-8
#类型
spring.thymeleaf.content-type=text/html
#名称的后缀
spring.thymeleaf.suffix=.html
- 建⽴⽂件夹
1)src/main/resources/templates/tl/
2)建立一个index.html
- 简单测试代码编写和访问
注意:$表达式只能写在th标签内部
快速⼊门:https://www.thymeleaf.org/doc/articles/standarddialect5minutes.html
第二十节、SpringBoot2.X定时任务schedule
- 什么是定时任务,使用场景
- 某个时间定时处理某个任务
- 发邮件、短信等
- 消息提醒
- 订单通知
- 统计报表系统
…
- 常见定时任务实现方式:
- Java自带的java.util.Timer类配置比较烦,时间延后问题
- Quartz框架: 配置更简单,xml或者注解适合分布式或者大型调度作业
- SpringBoot框架自带
- SpringBoot使用注解方式开启定时任务
- 启动类里面 @EnableScheduling开启定时任务,自动扫描
- 定时任务业务类 加注解 @Component被容器扫描
- 定时执行的方法加上注解 @Scheduled(fixedRate=2000) 定期执行一次
- 示例:
@Component
public class VideoOrderTask {
/**
* 每2秒执行一次
*/
@Scheduled(fixedRate = 2000)
public void sum(){
//从数据库中查询,此处只做模拟效果使用
System.out.println(LocalDateTime.now()+" 当前交易额="+Math.random());
}
}
注意:启动类需要加@EnableScheduling,定时任务才能生效
- 多中定时任务类型
- cron 定时任务表达式 @Scheduled(cron=“*/1 * * * * *”) 表示每秒
- crontab 工具 https://tool.lu/crontab/
- fixedRate: 定时多久执行一次(上一次开始执行时间点后xx秒再次执行;)
- fixedDelay: 上一次执行结束时间点后xx秒再次执行
- cron 定时任务表达式 @Scheduled(cron=“*/1 * * * * *”) 表示每秒
第二十一节、SpringBoot2.x异步任务EnableAsync
- 什么是异步任务和使用场景:
- 适⽤用于处理理log、发送邮件、短信……等
- 下单接口->查库存 1000
- 余额校验 1500
- 风控用户1000
使用步骤:
- 启动类里面使用@EnableAsync注解开启功能,自动扫描
- 定义异步任务类并使用@Component标记组件被容器扫描
- 异步方法加上@Async(@Async也可以加在类上,则里面的方法全部是异步方法)
获取返回结果:
- Future类获取结果
- T:需要当前任务返回的数据类型
- 定义异步任务类需要获取结果
- 要把异步任务封装到类里面,不能直接写到Controller
- 增加Future 返回结果 AsyncResult(“task执行完成”);
- 如果需要拿到结果 需要循环判断全部的 task.isDone()
使用示例:
@Component
@Async
public class AsyncTask {
public void task1(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task 1");
}
public void task2(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task 2");
}
public void task3(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task 3");
}
public Future<String> task4(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("Task 4");
}
public Future<String> task5(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("Task 5");
}
}
//controller中使用示例
//1、注入异步任务类
@Autowired
private AsyncTask asyncTask;
@GetMapping("async")
public JsonData testAsync(){
long begin = System.currentTimeMillis();
//2、调用异步任务
asyncTask.task1();
asyncTask.task2();
asyncTask.task3();
//3、需要获取结果的情况
Future<String> task4 = asyncTask.task4();
Future<String> task5 = asyncTask.task5();
for(;;){
if(task4.isDone()&&task5.isDone()){
try {
String task4Str = task4.get();
System.out.println(task4Str);
String task5Str = task5.get();
System.out.println(task5Str);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
break;
}
}
}
long end = System.currentTimeMillis();
return JsonData.buildSuccess(end-begin);
}
注意 启动类上需要加 @EnableAsync注解,异步任务才会生效