搬運鏈接 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專案




配置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 回傳報文的正文部分,直接顯示到頁面
*
*/
@RestController
public 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;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
測驗
1.上述步驟完成之后,還有一個錯誤需要解決,根據其提示進行修復即可

2.最終的目錄結構如下:

3.運行App的main 方法:Run As-->Java Application
啟動log如下: 
4.通過瀏覽器訪問,正常回傳controller中的配置內容

三、總結
從上述例子我們看到spring boot默認替我們做了一些操作
- 嵌入的Tomcat,無需部署WAR檔案,默認埠號為8080
- 簡化Maven配置,自動為我們引入依賴
- 自動配置Spring,省去了我們配置spring xml檔案的麻煩
- 默認我們的專案命名空間為"/"
- 還有一個比較重要但是例子中未能顯示體現出來的是: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 path
server.context-path=/test
目錄結構如下:

啟動服務,我們發現context和埠號都變了

正常訪問:

二、知識點引申
其實上面application.properties一共有四個目錄可以放置:
- 外置,在相對于應用程式運行目錄的/congfig子目錄里
- 外置,在應用程式運行的目錄里
- 內置,在config包內
- 內置,在classpath根目錄(即我們上述實體中的方式)
其中1和2適用于生產環境,打包后由于發布包不能修改,組態檔放在發布包之外,可以很方便的配置,
位置如下:

3和4適用于開發環境,位置如下:

如果同時在四個地方都有組態檔,組態檔的優先級是 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.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.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;
}
}

實作dao層
@Repository
public class UserDao {
@Autowired
JdbcTemplate 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);
}
實作類
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
public void save(User user){
userDao.save(user);
}
}
實作controller
@RestController
public class UserController {
@Autowired
UserService service;
@RequestMapping("/saveUser")
public String saveUser(User user) {
service.save(user);
return "save user successful";
}
}
測驗


二、總結
由此我們發現,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 path
server.context-path=/test
#配置資料源資訊
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
#配置jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.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介面并繼承CrudRepository
package 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;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserRepository repository;
@Override
public User getUser(Integer id) {
//有兩種方式:
//1.呼叫crudRepository的介面
// return repository.findOne(id);
//2.呼叫我們自己寫的介面
return repository.getUser(id);
}
}
創建controller
package 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;
@RestController
public class UserController {
@Autowired
UserService service;
@RequestMapping("/getUser/{id}")
public User getUser(@PathVariable("id") Integer id){
return service.getUser(id);
}
}
測驗頁面以json格式顯示資料庫值

二、知識點引申
關于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 要勾上

spring boot 系列之六:深入理解spring boot的自動配置
我們知道,spring boot自動配置功能可以根據不同情況來決定spring配置應該用哪個,不應該用哪個,舉個例子:
- Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自動配置一個JdbcTemplate的Bean
- Thymeleaf是不是在Classpath里面?如果是,則自動配置Thymeleaf的模板決議器、視圖決議器、模板引擎
那個這個是怎么實作的呢?原因就在于它利用了Spring的條件化配置,條件化配置允許配置存在于應用中,但是在滿足某些特定條件前會忽略這些配置,
要實作條件化配置我們要用到@Conditional條件化注解,
本篇隨筆從如下三個方面進行展開:
- @Conditional小例子,來說明條件化配置的實作方式
- spring boot 的條件化配置詳解
- spring boot 自動配置原始碼分析
- 自己動手實作spring boot starter pom
一、@Conditional小例子
我們知道在windows下顯示串列的命令是dir,而在linux系統下顯示串列的命令是ls,基于條件配置,我們可以實作在不同的作業系統下回傳不同的值,
判斷條件定義
a.windows下的判定條件
/**
* 實作spring 的Condition介面,并且重寫matches()方法,如果作業系統是windows就回傳true
*
*/
public class WindowsCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}
b.linux下的判定條件
/**
* 實作spring 的Condition介面,并且重寫matches()方法,如果作業系統是linux就回傳true
*
*/
public class LinuxCondition implements Condition{
@Override
public 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{
@Override
public String showListLine() {
return "dir";
}
}
linux下的bean的類
public class LinuxListService implements ListService{
@Override
public String showListLine() {
return "ls";
}
}
配置類
@Configuration
public 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包

條件化配置就是在這個jar里面實作的,它用到了如下的條件化注解,這些注解都是以@ConditionalOn開頭的,他們都是應用了@Conditional的組合注解:

接下來我們看個原始碼的列子:
以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是自動配置相關的,

而這個@EnableAutoConfiguration注解里面有個@Import注解匯入了EnableAutoConfigurationImportSelector用來實作具體的功能

(注:由于我本地的spring boot版本不是最新的,這里的EnableAutoConfigurationImportSelector已經不建議使用了,新版本可能已經換成了其他類,但是不影響我們看代碼)
這個類繼承了AutoConfigurationImportSelector

進入父類,里面有個方法selectImports()呼叫了方法getCandidateConfigurations(),進而呼叫了SpringFactoriesLoader.loadFactoryNames()方法


在SpringFactoriesLoader.loadFactoryNames()方法里面,我們看到會查詢META-INF/spring.factories這個組態檔

SpringFactoriesLoader.loadFactoryNames方法會掃描具有META-INF/spring.factories檔案的jar包,而我們的spring-boot-autoconfigure.jar里面就有一個這樣的檔案,此檔案中宣告了具體有哪些自動配置:

我們上面提到的JdbcTemplateAutoConfiguration自動配置類就在里面,
四、撰寫自己的spring boot starter pom
接下來,我們就來寫一個簡單的spring boot starter pom,
步驟如下:
- 新建starter maven專案spring-boot-starter-hello
- 修改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>
- 屬性配置
/**
* @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;
}
}
- 判定依據類
/**
* 后面的代碼會依據此類是否存在,來決定是否生產對應的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;
}
}
- 自動配置類
@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix = "hello", matchIfMissing = true, value = "https://www.cnblogs.com/yyyyfly1/p/enabled")
public class HelloServiceAutoConfiguration {
@Autowired
HelloServiceProperties helloServiceProperties;
@Bean
@ConditionalOnMissingBean(HelloService.class)
public HelloService helloService() {
HelloService service = new HelloService();
service.setMsg(helloServiceProperties.getMsg());
return service;
}
}
- 注冊配置,需要到META-INF/spring.factories檔案中注冊改自動配置類:在src/main/source目錄下新建改檔案,然后進行配置,
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sam.spring_boot_starter_hello.HelloServiceAutoConfiguration
- 對該工程進行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
@RestController
public class HelloController {
//代碼中沒有配置這個helloService Bean,但是自動配置能夠幫忙實體化,因此可以直接注入
@Autowired
HelloService helloService;
@RequestMapping(value="https://www.cnblogs.com/helloService")
public String sayHello() {
return helloService.sayHello();
}
}
頁面訪問/helloService介面

在application.properties里面配置hello.msg=sam,然后再次訪問/helloService介面

spring boot 系列之七:SpringBoot整合Mybatis
springboot已經很流行,但是它仍需要搭配一款ORM框架來實作資料的CRUD,之前已經分享過JdbcTemplete和JPA的整合,本次分享下Mybatis的整合,
對于mybatis的使用,需要創建mapper類和mapper.xml檔案,這種創建比較煩,并且基本都是模板樣式的,可以通過之前分享的《IDEA中mybatis generator使用》來自動創建完整的檔案,由于本次deom中只有一個查詢方法,就直接手寫了,不再使用該插件了,
代碼整體結構:
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.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC
spring.datasource.username=root
spring.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/*.xml
3.啟動器
@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;
}
@Override
public 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 mapper
PUBLIC "-//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
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> getUserList(User user) {
return userMapper.getUserList(user);
}
}
8.controller
@RestController
public class UserController {
@Autowired
UserService 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后查看控制臺
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
@Component
public class JdkSchedule {
@Autowired
UserService 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 {
@Override
public 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.創建job
JobDetail job = JobBuilder.newJob(MyJob.class).build();
//2.創建trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?"))
.build();
//3.創建schedule
Scheduler 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使用方法
*/
@Configuration
public class QuartzConfig {
/**
* 創建job物件
* @return
*/
@Bean
public JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(MyJob.class);
return jobDetailFactoryBean;
}
/**
* 創建trigger物件 - cron運算式物件
* @param jobDetailFactoryBean
* @return
*/
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setCronExpression("0/5 * * * * ?");
// 關聯JobDetail物件
cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
return cronTriggerFactoryBean;
}
/**
* 創建trigger物件 - 一般物件
* @param jobDetailFactoryBean
* @return
*/
@Bean
public 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
*/
@Bean
public 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 觸發執行...
在黑夜里夢想著光,心中覆寫悲傷,在悲傷里忍受孤獨,空守一絲溫暖,
我的淚水是無底深海,對你的愛已無言,相信無盡的力量,那是真愛永在,
我的信仰是無底深海,澎湃著心中火焰,燃燒無盡的力量,那是忠誠永在
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/440341.html
標籤:Java
