【Java】【搬运】SpringBoot系列

写在前面:博客推行版本更新,成果积累制度,已经写过的博客还会再次更新,不断地琢磨,高质量高数量都是要追求的,工匠精神是学习必不可少的精神 。因此,大家有何建议欢迎在评论区踊跃发言,你们的支持是我最大的动力,你们敢投,我就敢肝搬运链接 https://www.cnblogs.com/sam-uncle/category/1196696.html
spring boot 系列之一:spring boot 入门一、什么是spring boot ? spring boot是干嘛的?Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程 。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置 。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者 。
二、spring boot 入门实例创建maven项目

【Java】【搬运】SpringBoot系列

文章插图

【Java】【搬运】SpringBoot系列

文章插图

【Java】【搬运】SpringBoot系列

文章插图

【Java】【搬运】SpringBoot系列

文章插图
配置pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>spring-boot</groupId><artifactId>study</artifactId><version>0.0.1-SNAPSHOT</version><!-- 指定parent项目 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.10.RELEASE</version></parent><properties><!-- spring boot默认的jdk 版本为1.6,我们在这里改为1.8 --><java.version>1.8</java.version></properties><dependencies><dependency><!-- 引入spring-boot-starter-web 依赖 --><!-- 由于在spring boot 顶层POM文件中定义了相关dependencyManagement,因此这里就不需要配置 <version></version>,相关说明可以参考 https://blog.csdn.net/liutengteng130/article/details/46991829 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies></project>创建controller
package com.study.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * 这里@RestController = @ Controller + @ ResponseBody,** 会将方法的返回结果直接放入http 返回报文的正文部分,直接显示到页面 * */@RestControllerpublic class HelloController {@RequestMapping("/hello")public String sayHello() {return "hello ,spring boot";}}创建app启动类
package com.study;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}}测试
1.上述步骤完成之后,还有一个错误需要解决,根据其提示进行修复即可
【Java】【搬运】SpringBoot系列

文章插图
2.最终的目录结构如下:
【Java】【搬运】SpringBoot系列

文章插图

3.运行App的main 方法:Run As-->Java Application
启动log如下:
【Java】【搬运】SpringBoot系列

文章插图
4.通过浏览器访问,正常返回controller中的配置内容
【Java】【搬运】SpringBoot系列

文章插图
三、总结从上述例子我们看到spring boot默认替我们做了一些操作
  1. 嵌入的Tomcat,无需部署WAR文件,默认端口号为8080
  2. 简化Maven配置,自动为我们引入依赖
  1. 自动配置Spring,省去了我们配置spring xml文件的麻烦
  2. 默认我们的项目命名空间为"/"
  1. 还有一个比较重要但是例子中未能显示体现出来的是:spring boot 默认自动扫描 配置了@SpringBootApplication注解的类所在的包及其子包,并且这个类不能放在默认包下,否则会报错** WARNING ** : Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package. 并且不能正常启动 。
spring boot 系列之二:spring boot 如何修改默认端口号和contextpath一、问题解决:在src/main/resources目录下新建文件application.properties,并进行配置,来重写spring boot的默认配置
#指定端口号server.port=8090#指定context pathserver.context-path=/test目录结构如下:
【Java】【搬运】SpringBoot系列

文章插图
启动服务,我们发现context和端口号都变了
【Java】【搬运】SpringBoot系列

文章插图
正常访问:
【Java】【搬运】SpringBoot系列

文章插图
二、知识点引申其实上面application.properties一共有四个目录可以放置:
  1. 外置,在相对于应用程序运行目录的/congfig子目录里
  2. 外置,在应用程序运行的目录里
  1. 内置,在config包内
  2. 内置,在classpath根目录(即我们上述实例中的方式)
其中1和2适用于生产环境,打包后由于发布包不能修改,配置文件放在发布包之外,可以很方便的配置 。
位置如下:
【Java】【搬运】SpringBoot系列

文章插图
3和4适用于开发环境,位置如下:
【Java】【搬运】SpringBoot系列

文章插图
如果同时在四个地方都有配置文件,配置文件的优先级是 1 > 2 > 3 >4 。
spring boot 系列之三:spring boot 整合JdbcTemplate一、代码实现修改pom文件,引入相关依赖
<!-- 引入jdbc 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- 引入 mysql 数据库连接依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>配置数据库信息,在application.properties中添加如下内容:
spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=root创建实体类并创建数据库
package com.study.entity;public class User {private Integer id;private String userName;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}
【Java】【搬运】SpringBoot系列

文章插图
实现dao层
@Repositorypublic class UserDao {@AutowiredJdbcTemplate jdbcTemplate;public void save(User user) {String sql = "insert into t_user(user_name, password) values(?,?)";jdbcTemplate.update(sql, user.getUserName(), user.getPassword());}}实现service
接口
public interface UserService {public void save(User user);}实现类
@Servicepublic class UserServiceImpl implements UserService {@AutowiredUserDao userDao;public void save(User user){userDao.save(user);}}实现controller
@RestControllerpublic class UserController {@AutowiredUserService service;@RequestMapping("/saveUser")public String saveUser(User user) {service.save(user);return "save user successful";}}测试
【Java】【搬运】SpringBoot系列

文章插图
【Java】【搬运】SpringBoot系列

文章插图
二、总结由此我们发现,spring boot 只是简化了xml的配置麻烦,并没有减少我们java代码的编写量 。
spring boot 不是spring 功能的增强,而是提供了一种快速使用spring 的方式:开箱即用,没有代码生成,也无需XML配置 。
spring boot 系列之四:spring boot 整合JPA一、代码实现 修改pom,引入依赖<!-- 引入jpa 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>修改application.proerties,配置相关信息#修改tomcat默认端口号server.port=8090#修改context pathserver.context-path=/test#配置数据源信息spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=root#配置jpaspring.jpa.hibernate.ddl-auto=updatespring.jpa.show-sql=truespring.jackson.serialization.indent_output=true创建实体类package com.study.entity;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name="t_user")public class User {@Id @GeneratedValue(strategy=GenerationType.AUTO)private Integer id;private String userName;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}创建repository接口并继承CrudRepositorypackage com.study.repository;import org.springframework.data.jpa.repository.Query;import org.springframework.data.repository.CrudRepository;import org.springframework.data.repository.query.Param;import com.study.entity.User;/** * 注意: * 1.这里这里是interface,不是class ** 2.CrudRepository里面的泛型,第一个是实体类,第二个是主键的类型 ** 3.由于crudRepository 里面已经有一些接口了,如deleteAll,findOne等,我们直接调用即可 ** 4.当然,我们也可以根据自己的情况来实现自己的接口,如下面的getUser()方法,jpql语句和hql语句差不多 ** */public interface UserRepository extends CrudRepository<User, Integer> {/*** 我们这里只需要写接口,不需要写实现,spring boot会帮忙自动实现** */@Query("from User where id =:id ")public User getUser(@Param("id") Integer id);}创建service接口
package com.study.service;import com.study.entity.User;public interface UserService {public User getUser(Integer id);}实现
package com.study.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.study.entity.User;import com.study.repository.UserRepository;import com.study.service.UserService;@Servicepublic class UserServiceImpl implements UserService {@AutowiredUserRepository repository;@Overridepublic User getUser(Integer id) {//有两种方式://1.调用crudRepository的接口//return repository.findOne(id);//2.调用我们自己写的接口return repository.getUser(id);}}创建controllerpackage com.study.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.study.entity.User;import com.study.service.UserService;@RestControllerpublic class UserController {@AutowiredUserService service;@RequestMapping("/getUser/{id}")public User getUser(@PathVariable("id") Integer id){return service.getUser(id);}}测试页面以json格式显示数据库值
【Java】【搬运】SpringBoot系列

文章插图
二、知识点引申关于Repository知识点,可以去看下下面这篇文章
https://segmentfault.com/a/1190000012346333
spring boot 系列之五:spring boot 通过devtools进行热部署在上述代码操作的过程中肯定也发现了一个问题:哪怕是一个个小小的修改,都必须要重新启动服务才能使修改生效 。
那能不能通过配置实现spring boot的热部署呢?答案是肯定的 。
接下来我们来一起看下怎么通过devtools实现spring boot的热部署 。很简单,只需要简单几步:
引入依赖
<!-- 引入devtools 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><!-- optional=true,依赖不会传递--><optional>true</optional></dependency>对于eclipse,还需要加上maven-plugin插件
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin></plugins></build>Project --> Build Automatically 要勾上
【Java】【搬运】SpringBoot系列

文章插图
spring boot 系列之六:深入理解spring boot的自动配置我们知道,spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子:
  • Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自动配置一个JdbcTemplate的Bean
  • Thymeleaf是不是在Classpath里面?如果是,则自动配置Thymeleaf的模板解析器、视图解析器、模板引擎
那个这个是怎么实现的呢?原因就在于它利用了Spring的条件化配置,条件化配置允许配置存在于应用中,但是在满足某些特定条件前会忽略这些配置 。
要实现条件化配置我们要用到@Conditional条件化注解 。
本篇随笔从如下三个方面进行展开:
  1. @Conditional小例子,来说明条件化配置的实现方式
  2. spring boot 的条件化配置详解
  1. spring boot 自动配置源码分析
  2. 自己动手实现spring boot starter pom
一、@Conditional小例子我们知道在windows下显示列表的命令是dir,而在linux系统下显示列表的命令是ls,基于条件配置,我们可以实现在不同的操作系统下返回不同的值 。
判断条件定义a.windows下的判定条件
/*** 实现spring 的Condition接口,并且重写matches()方法,如果操作系统是windows就返回true**/public class WindowsCondition implements Condition{@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return context.getEnvironment().getProperty("os.name").contains("Windows");}}【【Java】【搬运】SpringBoot系列】b.linux下的判定条件
/** * 实现spring 的Condition接口,并且重写matches()方法,如果操作系统是linux就返回true * */public class LinuxCondition implements Condition{@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return context.getEnvironment().getProperty("os.name").contains("Linux");}}不同系统下的bean的类接口
public interface ListService {public String showListLine();}windows下的bean类
public class WindowsListService implements ListService{@Overridepublic String showListLine() {return "dir";}}linux下的bean的类
public class LinuxListService implements ListService{@Overridepublic String showListLine() {return "ls";}}配置类@Configurationpublic class ConditionConfig {/*** 通过@Conditional 注解,符合windows条件就返回WindowsListService实例**/@Bean@Conditional(WindowsCondition.class)public ListService windonwsListService() {return new WindowsListService();}/*** 通过@Conditional 注解,符合linux条件就返回LinuxListService实例**/@Bean@Conditional(LinuxCondition.class)public ListService linuxListService() {return new LinuxListService();}}测试类public class ConditionTest {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);ListService listService = context.getBean(ListService.class);System.out.println(context.getEnvironment().getProperty("os.name") + " 系统下的列表命令为: " + listService.showListLine());}}运行测试类,由于我的是windows7 系统,因此结果是
Windows 7 系统下的列表命令为: dir
如果你的是linux系统,则结果就会是
Linux 系统下的列表命令为: ls
二、spring boot 的条件化配置在spring boot项目中会存在一个名为spring-boot-autoconfigure的jar包
【Java】【搬运】SpringBoot系列

文章插图
条件化配置就是在这个jar里面实现的,它用到了如下的条件化注解,这些注解都是以@ConditionalOn开头的,他们都是应用了@Conditional的组合注解:
【Java】【搬运】SpringBoot系列

文章插图
接下来我们看个源码的列子:
以JdbcTemplateAutoConfiguration为例,它里面有这段代码:
@Bean@Primary@ConditionalOnMissingBean(JdbcOperations.class)public JdbcTemplate jdbcTemplate() {return new JdbcTemplate(this.dataSource);}只有在不存在JdbcOperations(如果查看JdbcTemplate的源码,你会发现JdbcTemplate类实现了JdbcOperations接口)实例的时候,才会初始化一个JdbcTemplate 的Bean 。
基于以上内容,我们就可以阅读自动配置相关的源码了 。
三、spring boot 自动配置源码分析spring boot项目的启动类用的注解--@SpringBootApplication是一个组合注解,其中@EnableAutoConfiguration是自动配置相关的 。
【Java】【搬运】SpringBoot系列

文章插图
而这个@EnableAutoConfiguration注解里面有个@Import注解导入了EnableAutoConfigurationImportSelector用来实现具体的功能
【Java】【搬运】SpringBoot系列

文章插图
(注:由于我本地的spring boot版本不是最新的,这里的EnableAutoConfigurationImportSelector已经不建议使用了,新版本可能已经换成了其他类,但是不影响我们看代码)
这个类继承了AutoConfigurationImportSelector
【Java】【搬运】SpringBoot系列

文章插图
进入父类,里面有个方法selectImports()调用了方法getCandidateConfigurations(),进而调用了SpringFactoriesLoader.loadFactoryNames()方法
【Java】【搬运】SpringBoot系列

文章插图

【Java】【搬运】SpringBoot系列

文章插图
在SpringFactoriesLoader.loadFactoryNames()方法里面,我们看到会查询META-INF/spring.factories这个配置文件
【Java】【搬运】SpringBoot系列

文章插图
SpringFactoriesLoader.loadFactoryNames方法会扫描具有META-INF/spring.factories文件的jar包,而我们的spring-boot-autoconfigure.jar里面就有一个这样的文件,此文件中声明了具体有哪些自动配置:
【Java】【搬运】SpringBoot系列

文章插图
我们上面提到的JdbcTemplateAutoConfiguration自动配置类就在里面 。
四、编写自己的spring boot starter pom接下来,我们就来写一个简单的spring boot starter pom 。
步骤如下:
  1. 新建starter maven项目spring-boot-starter-hello
  2. 修改pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.sam</groupId><artifactId>spring-boot-starter-hello</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><dependencies><!-- 这里需要引入spring boot的自动配置作为依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>1.5.1.RELEASE</version></dependency></dependencies></project>
  1. 属性配置
/*** @ConfigurationProperties* 自动匹配application.properties文件中hello.msg的值,然后赋值给类属性msg,这里的msg默认值为“spring boot”**/@ConfigurationProperties(prefix="hello")public class HelloServiceProperties {private static final String MSG = "spring boot";private String msg = MSG;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}
  1. 判定依据类
/** * 后面的代码会依据此类是否存在,来决定是否生产对应的Bean * */public class HelloService {private String msg;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String sayHello() {return "hello " + msg;}}
  1. 自动配置类
@Configuration@EnableConfigurationProperties(HelloServiceProperties.class)@ConditionalOnClass(HelloService.class)@ConditionalOnProperty(prefix = "hello", matchIfMissing = true, value = "https://tazarkount.com/read/enabled")public class HelloServiceAutoConfiguration {@AutowiredHelloServiceProperties helloServiceProperties;@Bean@ConditionalOnMissingBean(HelloService.class)public HelloService helloService() {HelloService service = new HelloService();service.setMsg(helloServiceProperties.getMsg());return service;}}
  1. 注册配置,需要到META-INF/spring.factories文件中注册改自动配置类:在src/main/source目录下新建改文件,然后进行配置 。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.sam.spring_boot_starter_hello.HelloServiceAutoConfiguration
  1. 对该工程进行mvn clean install,将jar推送到本地maven仓库,供后续使用 。
使用starter,使用我们这个starter 需要新建一个或使用既存的一个spring boot工程(这里我用的是既存的),然后
修改pom,引入上述的依赖
<dependency><groupId>com.sam</groupId><artifactId>spring-boot-starter-hello</artifactId><version>0.0.1-SNAPSHOT</version></dependency>实现controller
@RestControllerpublic class HelloController {//代码中没有配置这个helloService Bean,但是自动配置能够帮忙实例化,因此可以直接注入@AutowiredHelloService helloService;@RequestMapping(value="https://tazarkount.com/helloService")public String sayHello() {return helloService.sayHello();}}页面访问/helloService接口
【Java】【搬运】SpringBoot系列

文章插图
在application.properties里面配置hello.msg=sam,然后再次访问/helloService接口
【Java】【搬运】SpringBoot系列

文章插图
spring boot 系列之七:SpringBoot整合Mybatisspringboot已经很流行,但是它仍需要搭配一款ORM框架来实现数据的CRUD,之前已经分享过JdbcTemplete和JPA的整合,本次分享下Mybatis的整合 。
对于mybatis的使用,需要创建mapper类和mapper.xml文件,这种创建比较烦,并且基本都是模板样式的,可以通过之前分享的《IDEA中mybatis generator使用》来自动创建完整的文件 。由于本次deom中只有一个查询方法,就直接手写了,不再使用该插件了 。
代码整体结构:

【Java】【搬运】SpringBoot系列

文章插图
1.pom配置<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.sam</groupId><artifactId>springboot</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--mybatis依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><!--mysql db连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.14</version></dependency><!--热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin></plugins></build></project>2.application.propertis# jdbc配置spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=UTCspring.datasource.username=rootspring.datasource.password=123456# 连接池spring.datasource.type=com.alibaba.druid.pool.DruidDataSource#mybatis的package别名#mybatis.type-aliases-package=com.sam.springboot.pojo#指定mybatis映射文件的路径mybatis.mapper-locations=classpath:com/sam/springboot/mapper/*.xml3.启动器@SpringBootApplication@MapperScan("com.sam.springboot.mapper") //扫描该包下的mapper文件public class SpringbootApplication { public static void main(String[] args) {SpringApplication.run(SpringbootApplication.class, args); }}4.db脚本CREATE TABLE `users`(`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) NULL DEFAULT NULL,`age` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE);-- ------------------------------ Records of users-- ----------------------------INSERT INTO `users` VALUES (1, 'sam', 32);INSERT INTO `users` VALUES (2, 'hah ', 10);5.pojo类package com.sam.springboot.pojo;/** * @description: * @author JAVA开发老菜鸟 * @date: 2021-09-05 19:31 */public class User {private Integer id;private String name;private Integer age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}}6.mapper文件和mapper.xml/** * @description: * @author: JAVA开发老菜鸟 * @date: 2021-09-05 19:34 */public interface UserMapper {public List<User> getUserList(User user);}<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.sam.springboot.mapper.UserMapper"><select id="getUserList" resultType="com.sam.springboot.pojo.User">select * from users</select></mapper>7.service接口和实现public interface UserService {List<User> getUserList(User user);}/** * @description: * @author: JAVA开发老菜鸟 * @date: 2021-09-05 19:39 */@Servicepublic class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepublic List<User> getUserList(User user) {return userMapper.getUserList(user);}}8.controller@RestControllerpublic class UserController {@AutowiredUserService userService;@GetMapping("/getUserList.do")public void getUser() {List<User> list = userService.getUserList(new User());for (User user :list ){System.out.println(user.toString());}}}9.调试浏览器访问http://localhost:8080/getUserList.do后查看控制台

【Java】【搬运】SpringBoot系列

文章插图
spring boot 系列之八:SpringBoot处理定时任务一、cron表达式无论上面说的哪种实现方式,都需要用到cron表达式,因此不得不先介绍下它 。
Cron表达式是一个字符串,由6或7个域组成,每个域有不同的含义,每个域之间用空格隔开 。有2中格式:
Seconds Minutes Hours DayofMonth Month DayofWeek Year (7个域)
Seconds Minutes Hours DayofMonth Month DayofWeek (6个域)
每个域可能出现的值:
Seconds:有效范围为0-59的整数
Minutes:有效范围为0-59的整数
Hours:有效范围为0-23的整数
DayofMonth:有效范围为0-31的整数
Month:有效范围为1-12的整数或JAN-DEC DayofWeek:有效范围为1-7的整数或SUN-SAT两个范围 。1表示星期天,2表示星期一,依次类推
Year:有效范围为1970-2099年
除了以上内容外,还可能出现一些特殊字符:
(1)*:表示匹配该域的任意值,假如在Minutes域使用*, 即表示每分钟都会触发事件 。
(2)?:只能用在DayofMonth和DayofWeek两个域 。它也匹配域的任意值,但实际不会 。因为DayofMonth和DayofWeek会相互影响 。例如想在每月的10日触发调度,不管10日到底是星期几,则只能使用如下写法: 13 13 15 10 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样 。
(3)-:表示范围,例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
(4)/:表示起始时间开始触发,然后每隔固定时间触发一次,例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.
(5),:表示列出枚举值值 。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次 。
(6)L:表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发 。
(7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件 。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发 。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发 。另外一点,W的最近寻找不会跨过月份
(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五 。
(9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域 。例如在4#2,表示某月的第二个星期三 。
举例
@Scheduled(cron = “0 0 1 1 1 ?”)//每年一月的一号的 1:00:00 执行一次
@Scheduled(cron = “0 0 1 1 1,6 ?”) //一月和六月的一号的 1:00:00 执行一次
@Scheduled(cron = “0 0 1 1 1,4,7,10 ?”) //每个季度的第一个月的一号的 1:00:00 执行一次
@Scheduled(cron = “0 0 1 1 * ?”)//每月一号 1:00:00 执行一次
@Scheduled(cron=“0 0 1 * * *”) //每天凌晨 1 点执行一次
以上看上去有点复杂,不过不用担心,记住常用的就行了 。另外,现在网上还有 在线Cron表达式生成器可以帮助我们设定确定相关表达式内容 。
二、@Schedule实现1.引入依赖<!--添加schedule依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency>2.代码实现新建类JdkSchedule
@Componentpublic class JdkSchedule {@AutowiredUserService userService;@Scheduled(cron = "0/2 * * * * ?") //每个两秒触发一次public void scheduleGetUserList() {System.out.println("**触发JDK 定时器***");List<User> list = userService.getUserList(new User());for (User user :list ){System.out.println(user.toString());}}}里面userService为上一次添加的内容
启动类添加注解,启动定时任务
@EnableScheduling
3.测试效果每隔两秒打印一次:
**触发JDK 定时器***
User{id=1, name='sam', age=32}
User{id=2, name='hah ', age=10}
三、Quartz实现1.Quartz介绍Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间 。它包括调度器、触发器、作业 。
组成
描述
Job--任务
做什么事?
Trigger--触发器
什么时候做?
Scheduler--调度器
什么时候需要去做什么事情?
2.基本使用引入依赖
<!--引入quartz依赖--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId></dependency>创建job类
public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("...quartz job 触发执行...");}}需要实现Quarz的Job接口
编写测试类
/** * quartz原生态用法 */public class JobTestMain {public static void main(String[] args) throws SchedulerException {//1.创建jobJobDetail job = JobBuilder.newJob(MyJob.class).build();//2.创建triggerCronTrigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")).build();//3.创建scheduleScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();scheduler.scheduleJob(job, trigger);scheduler.start();}}3.springboot整合使用引入依赖
<!--添加schedule依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!--引入quartz依赖--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId></dependency><!--引入spring tx依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency>Springboot整合的时候,需要添加这三个依赖
编写配置类
/*** springboot整合quartz使用方法*/@Configurationpublic class QuartzConfig {/*** 创建job对象* @return*/@Beanpublic JobDetailFactoryBean jobDetailFactoryBean() {JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();jobDetailFactoryBean.setJobClass(MyJob.class);return jobDetailFactoryBean;}/*** 创建trigger对象 - cron表达式对象* @param jobDetailFactoryBean* @return*/@Beanpublic CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();cronTriggerFactoryBean.setCronExpression("0/5 * * * * ?");// 关联JobDetail对象cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());return cronTriggerFactoryBean;}/*** 创建trigger对象 - 一般对象* @param jobDetailFactoryBean* @return*/@Beanpublic SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean) {SimpleTriggerFactoryBean simpleTriggerFactoryBean = new SimpleTriggerFactoryBean();// 关联JobDetail对象simpleTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());// 设置重复次数,这里配置的是重复次数,而不是总次数; 总次数=重复次数+1,也就是说这里配置的次数是:执行完一次之后,再重复执行的次数simpleTriggerFactoryBean.setRepeatCount(1);// 设置间隔时间simpleTriggerFactoryBean.setRepeatInterval(2000);return simpleTriggerFactoryBean;}/*** 创建schedule对象* @param triggerFactoryBean* @return*/@Beanpublic SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean triggerFactoryBean){SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();schedulerFactoryBean.setTriggers(triggerFactoryBean.getObject());return schedulerFactoryBean;}}这里需要注意下,schedulerFactoryBean()方法中传入的参数如果是CronTriggerFactoryBean,则执行的是cronTriggerFactoryBean()对应的设置;参数如果是SimpleTriggerFactoryBean,则执行的是simpleTriggerFactoryBean()对应的设置 。
启动类添加注解
@EnableScheduling
测试效果
每5秒钟执行一次:...quartz job 触发执行...
如果前面的@Schedule和这里的Quartz的定时任务放在一起了,则执行效果为两个Job一起执行:
...quartz job 触发执行...User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}**触发JDK 定时器***User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}**触发JDK 定时器***User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}**触发JDK 定时器***...quartz job 触发执行...User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}**触发JDK 定时器***User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}**触发JDK 定时器***User{id=1, name='sam', age=32}User{id=2, name='hah ', age=10}...quartz job 触发执行...在黑夜里梦想着光,心中覆盖悲伤,在悲伤里忍受孤独,空守一丝温暖 。我的泪水是无底深海,对你的爱已无言,相信无尽的力量,那是真爱永在 。我的信仰是无底深海,澎湃着心中火焰,燃烧无尽的力量,那是忠诚永在