SpringBoot2.x开发学习笔记

第一节、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配置文件中覆盖该变量重新配置即可
  • 基本互联网企业静态资源文件一般存储在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字符串
  • 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都会被调用,用于资源清理
    • 按照注册顺序进行拦截,先注册,先被拦截
  • 拦截器不生效常见问题:
- 是否有加@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等
  • 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秒再次执行

第二十一节、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注解,异步任务才会生效
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值