天天看點

Spring Boot學習随記

由于早年在管理領域耕耘了一段時間,完美錯過了Spring的活躍期,

多少對這個經典的技術帶有一種遺憾的心态在裡面的,

從下面的我的生涯手繪圖中大概可以看出來我的經曆。

Spring Boot學習随記

最近由于新介入到了工業數字化領域,工作也專注于業務應用,

不怎麼搞平台了,平台更多的是采取與友商戰略合作的方式,

也有機會重新認識并學習一下這個被完美錯過的經典技術。

以下是本次的随記。

一、本次的代碼位址

https://github.com/quchunhui/demo-macket/tree/master/springboot

二、一個簡單的需求場景

Spring Boot學習随記

1)  從雲平台按照一定頻率拉取資料(每次間隔5秒)。

2)  将待擷取的資料儲存至本地資料庫(MySQL)。

3)提供可視化web頁面供檢視流轉資料狀态。

4)  由DView工業軟體從資料庫中拉取資料(每次間隔5秒)。

5)  按照一定數量間隔向PLC下發加工資料(每次5個)。

其中,紅色字型部分,為本次随記的範圍。

三、學習書籍

我本在在正式開始學習及開發之前,通過書籍和付費視訊對Spring boot進行了簡單掃盲

學習的書籍為:《Spring 5企業級開發實戰》

學習的收費視訊為:極客時間《Spring全家桶》

書籍可以采用快速閱讀的方式進行架構性學習

視訊可以采用2倍速,按照需要先挑選部分子產品學習

四、學習筆記

===初始化工程===

https://start.spring.io/

可以通過這個位址初始化工程

也可以通過IDEA的Spring initializr來進行初始設計。

Spring Boot學習随記

可以選擇一下元件:

Developer Tools

→Lombok

→Spring Configuration Processor

Web

→Spring Web

SQL

→Spring Boot JPA

→MySQL Driver

Ops

→Spring Boot Actuator

===spring boot actuator===

用于健康檢查的子產品,可以考慮引入進來。

===lombok===

Lombok想要解決了的是在我們實體Bean中大量的Getter/Setter方法,以及toString,hashCode等可能不會用到,

在使用Lombok之後,将由其來自動幫你實作代碼生成,注意,其是 在運作過程中,幫你自動生成的 。就是說,将極大減少你的代碼總量。

===JDBC與JPA差別===

1.定義

JDBC提供一種接口,它是由各種資料庫廠商提供類和接口組成的資料庫驅動,為多種資料庫提供統一通路。我們使用資料庫時隻需要調用JDBC接口就行了。

JDBC的用途:與資料庫建立連接配接、發送操作資料庫的語句并處理結果。

JPA是Java持久層API。它是對java應用程式通路ORM(對象關系映射)架構的規範。為了我們能用相同的方法使用各種ORM架構。

JPA用途:簡化現有Java EE和Java SE應用開發工作;整合ORM技術。

2.不同點:

1)使用的sql語言不同:

JDBC使用的是基于關系型資料庫的标準SQL語言;

JPA通過面向對象而非面向資料庫的查詢語言查詢資料,避免程式的SQL語句緊密耦合。

2)操作的對象不同:

JDBC操作的是資料,将資料通過SQL語句直接傳送到資料庫中執行:

JPA操作的是持久化對象,由底層持久化對象的資料更新到資料庫中。

3)資料狀态不同:

JDBC操作的資料是“瞬時”的,變量的值無法與資料庫中的值保持一緻;

JPA操作的資料時可持久的,即持久化對象的資料屬性的值是可以跟資料庫中的值保持一緻的。

===mvn package報錯===

錯誤日志

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
      

問題原因:

Mybatis沒有找到合适的加載類,其實是大部分spring - datasource - url沒有加載成功,

解決辦法:

在application.propertier中增加如下代碼之後,編譯通過。

spring.datasource.url=jdbc:mysql://localhost:3306/read_data?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username: root
spring.datasource.password: 123456
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
      

  

參考部落格:

https://www.cnblogs.com/wuxiang12580/archive/2019/01/25/10319914.html

===運作報錯===

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
      

問題原因:

資料庫連接配接相關的配置不正确,連接配接不上資料庫

application.propertier中的資料庫連接配接資訊修改為正确的即可。修改後如下:

spring.datasource.url=jdbc:mysql://localhost:3306/visual?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username: root
spring.datasource.password: 123456
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
      

===@Builder注解===

在出現lombok之後,對象的建立工作更提供Builder方法,

它提供在設計資料實體時,對外保持private setter,而對屬性的指派采用Builder的方式,

這種方式最優雅,也更符合封裝的原則,不對外公開屬性的寫操作!

@Builder聲明實體,表示可以進行Builder方式初始化,

@Value注解,表示隻公開getter,對所有屬性的setter都封閉,即private修飾,是以它不能和@Builder一起使用

https://www.cnblogs.com/lori/p/9024933.html

===Builder注解沒有builder方法===

在IDEA中下載下傳lombok插件解決。vscode一樣。

https://blog.csdn.net/Butterfly_resting/article/details/101377756

===Lombok中的@Data注解===

@Data:該注解相當于同時加上以下注解@Setter @Getter,@ToString,@EqualsAndHashCode

@Getter:生成getter方法

@Setter:生成setter方法

@AllArgsConstructor:全參構造

@NoArgsContructor:無參構造

===JdbcTemplate與NamedParameterJdbcTemplate===

SimpleJdbcTemplate加入了Java5的特性支援,例如可變參數、自動拆包封包、泛型等支援。

JdbcTemplate,已經基本能看到相對于JDBC比較強大的能力,

但是它有一個問題很不友善,就是使用參數的占位符時,必須得按照順序來寫參數,如果順序不對,則操作失敗,

NamedParameterJdbcTemplate可以用來解決這個問題,它提供了一個方式,可以通過參數名來映射參數而不是傳統的"?"

可以使用SqlParameterSourceUtils.createBatch()方法,将list裡的東西變成一個batch的值

List<Foo> list = new ArrayList<>();
list.add(Foo.builder().id(100L).bar("b-100").build());
list.add(Foo.builder().id(101L).bar("b-101").build());
namedParameterJdbcTemplate.batchUpdate("INSERT INTO FOO (ID, BAR) VALUES (:id, :bar)",
SqlParameterSourceUtils.createBatch(list));
      

===spring boot的定時任務(Scheduled)===

@Scheduled中的參數說明

@Scheduled(fixedRate=2000):上一次開始執行時間點後2秒再次執行;

Scheduled(fixedDelay=2000):上一次執行完畢時間點後2秒再次執行;

@Scheduled(initialDelay=1000, fixedDelay=2000):第一次延遲1秒執行,然後在上一次執行完畢時間點後2秒再次執行;

@Scheduled(cron="* * * * * ?"):按cron規則執行。

https://www.cnblogs.com/mmzs/p/10161936.html

===Spring boot Scheduled沒有被定時執行===

@ComponentScan(basePackages = {"com.xxx"})

這是spring掃描路徑,Test 是否在 com.xxx 包下面

@ComponentScan做的事情就是告訴Spring從哪裡找到bean

@Component 和 @ComponentScan的使用目的不一樣

@Component注解,表明當需要建立類時,這個被注解的類是一個候選類。就像是舉手。

@ComponentScan 用于掃描指定包下的類。就像看都有哪些舉手了

https://blog.csdn.net/Lamb_IT/article/details/80918704

===JPA的一些注解===

主體

@Entity

@MappedSuperclass 

@Table(name)

主鍵

@Id

@GeneratedValue(strategy, generator)

@SuquenceGenerator(name, sequenceName)

@GeneratedValue注解的strategy屬性提供四種值:

-AUTO主鍵由程式控制, 是預設選項 ,不設定就是這個

-IDENTITY 主鍵由資料庫生成, 采用資料庫自增長, Oracle不支援這種方式

-SEQUENCE 通過資料庫的序列産生主鍵, MYSQL  不支援

-Table 提供特定的資料庫産生主鍵, 該方式更有利于資料庫的移植

映射

@Column(name, nullable, length, insertable, updatable)

@JoinTable(name)

@JoinColumn(name)

關系

@OneToOne

@OneToMany

@ManyToOne

@ManyToMany

@OrderBy

===幾種注解的關系===

@Repository、@Service、@Controller 和 @Component 将類辨別為Bean

@Repository注解便屬于最先引入的一批,它用于将資料通路層 (DAO 層 ) 的類辨別為 Spring Bean

@Component 是一個泛化的概念,僅僅表示一個元件 (Bean) ,可以作用在任何層次。

@Service 通常作用在業務層,但是目前該功能與 @Component 相同。

@Constroller 通常作用在控制層,但是目前該功能與 @Component 相同。

通過在類上使用 @Repository、@Component、@Service 和 @Constroller 注解,

Spring會自動建立相應的 BeanDefinition 對象,并注冊到 ApplicationContext 中。

這些類就成了Spring受管元件。

這三個注解除了作用于不同軟體層次的類,其使用方式與 @Repository 是完全相同的。

===@GeneratedValue===

在JPA中

@GeneratedValue注解存在的意義主要就是為一個實體生成一個唯一辨別的主鍵(JPA要求每一個實體Entity,必須有且隻有一個主鍵)

@GeneratedValue提供了主鍵的生成政策。

@GeneratedValue注解有兩個屬性,分别是strategy和generator

generator屬性的值是一個字元串,預設為"",其聲明了主鍵生成器的名稱(對應于同名的主鍵生成器@SequenceGenerator和@TableGenerator)

PA為開發人員提供了四種主鍵生成政策,其被定義在枚舉類GenerationType中,包括

GenerationType.TABLE:

GenerationType.SEQUENCE:

GenerationType.IDENTITY:

GenerationType.AUTO:

https://blog.csdn.net/u012493207/article/details/50846616

===@Id 和 @GeneratedValue 注解===

@Id 标注用于聲明一個實體類的屬性映射為資料庫的主鍵列。

該屬性通常置于屬性聲明語句之前,可與聲明語句同行,也可寫在單獨行上。

https://blog.csdn.net/Jae_Wang/article/details/80533137

===@Query===

@Query(value=" 這裡就是查詢語句")

@Query支援hql和原生sql兩種方式,預設是hql,hql就是語句中用的是實體名字和實體屬性,原生sql用的表名字和表字段, 

hql方式不支援select * 要想查詢全部字段可以用select 實體名 這裡省略了value,參數使用了占位置符 ?1代表第一個參數?2代表第二個

@Param 代替參數占位符,hql或者sql裡就用:firstname替換方法裡的參數順序可以打亂

如果是更新或者删除操作,方法上面要加@Modifying預設開啟的事務隻是可讀的,更新操作加入@Modifying就會關閉可讀

原生sql方式 不能和Pageable pageable 同時使用,要用自己的limit實作分頁,原生的方式就和sql文法完全一樣,使用的表名字,表字段

@Data 屬于lombok注解,與jpa無關,自動生成getter/setter/equals/hashcode/tostring等方法

@Entity, @Table jpa注解,表示這個類與db的表關聯,具體比對的是表 money

@Id @GeneratedValue 作用與自增主鍵

@Column表明這個屬性與表中的某列對應

@CreateDate根據目前時間來生成預設的時間戳

https://blog.csdn.net/qq_27886997/article/details/82982936

===啟動報錯===

Field processedDataDao in rexel.controller.RexelMiddlewareController required a bean of type 'rexel.dao.ProcessedDataDao' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
      

包掃描路徑不正确

@ComponentScan("rexel")

Composite-id class must implement Serializable: rexel.entity.DViewVarNameDic
      

如果該實體類對應的表隻有一個主鍵,即圖中的id,把linkName上面的@Id注解删除即可,重新啟動就不會報錯了。

如果該實體類對應的表确實使用的兩個字段(聯合主鍵),則要求該實體類必須可序列化,該類要實作 Serializable 接口,并添加如下代碼:

private static final long serialVersionUID = 1L;
public class DViewVarNameDic implements Serializable {
      

 

http://www.mamicode.com/info-detail-2681892.html

Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class rexel.entity.DViewVarNameDicEntity] does not define an IdClass
      

在Entity類前面加上@IdClass()

Spring Boot學習随記

===@Configuration和@Bean===

@Configuration底層是含有@Component ,是以@Configuration 具有和 @Component 的作用。

@Configuration可了解為用spring的時候xml裡面的<beans>标簽。

@Configuration注解可以達到在Spring中使用xml配置檔案的作用。

@Configuration标注在類上,相當于把該類作為spring的xml配置檔案中的<beans>,作用為:配置spring容器(應用上下文)

https://blog.csdn.net/qq_36472252/article/details/86623630

===RestRemplate樣例程式運作報錯===

Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class rexel.webservice.bean.ProcessedDataBean] and content type [text/html;charset=utf-8]
      

按照這個網址可以解決

https://www.jianshu.com/p/95bf08696cd7

然後再次運作,又會提示其他錯誤

Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'H24': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'H24': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (PushbackInputStream); line: 6, column: 20]
      

檢查之後,發現是我在postman裡定義的json格式不正确引起的。

Shit,多少有些2B了,暫時放過自己一次。

===增加了事務注解,但是無法復原===

我這裡發生的原因是用@Transactional(rollbackFor = Exception.class)标注的方法沒有是public

https://blog.csdn.net/zdyueguanyun/article/details/80236401

===讀取application.properties檔案的幾種方法===

第一種方式:使用@ConfigurationProperties(prefix = "com.zyd")注解在class頭

第二種方式:使用@Value("${propertyName}")注解在變量上

第三種方式:使用Environment evn; env.getProperty("com.zyd.type2")

第四種方式:使用Properties properties = PropertiesLoaderUtils.loadAllProperties(propertyFileName);

https://www.cnblogs.com/FraserYu/p/11261916.html

===Http報頭Accept與Content-Type的差別===

Http報頭分為通用報頭,請求報頭,響應報頭和實體報頭。

1.Accept屬于請求頭, Content-Type屬于實體頭。 

Http報頭分為通用報頭,請求報頭,響應報頭和實體報頭。 

請求方的http報頭結構:通用報頭|請求報頭|實體報頭 

響應方的http報頭結構:通用報頭|響應報頭|實體報頭

2.Accept代表發送端(用戶端)希望接受的資料類型。 

比如:Accept:text/xml; 

代表用戶端希望接受的資料類型是xml類型

3.Content-Type代表發送端(用戶端|伺服器)發送的實體資料的資料類型。 

比如:Content-Type:text/html; 

代表發送端發送的資料格式是html。

二者合起來, 

Accept:text/xml; 

Content-Type:text/html 

即代表希望接受的資料類型是xml格式,本次請求發送的資料的資料格式是html。

Caused by: org.hibernate.AnnotationException: No identifier specified for entity: rexel.entity.AccessTokenEntity
at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:266) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:211) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:781) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1214) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1245) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
      

問題原因:  

當使用idclass時,實體中須有和idclass類中屬性個數的主鍵,并且一緻

https://blog.csdn.net/Mosqiote/article/details/89227931

===Springboot的entity,dao,controller,service層級了解===

1.Dao層:持久層,主要與資料庫互動

DAO層首先會建立Dao接口,接着就可以在配置檔案中定義該接口的實作類;

接着就可以在子產品中調用Dao的接口進行資料業務的處理,而不用關注此接口的具體實作類是哪一個類,

Dao層的資料源和資料庫連接配接的參數都是在配置檔案中進行配置的。

2.Entity層:實體層,資料庫在項目中的類

主要用于定義與資料庫對象應的屬性,提供get/set方法,tostring方法,有參無參構造函數。

3.Service層:業務層 控制業務

業務子產品的邏輯應用設計,和DAO層一樣都是先設計接口,再建立要實作的類,然後在配置檔案中進行配置其實作的關聯。

接下來就可以在service層調用接口進行業務邏輯應用的處理。

好處:封裝Service層的業務邏輯有利于業務邏輯的獨立性和重複利用性。

4.Controller層:控制層 控制業務邏輯

具體的業務子產品流程的控制,controller層主要調用Service層裡面的接口控制具體的業務流程,控制的配置也要在配置檔案中進行。

Controller和Service的差別是:Controller負責具體的業務子產品流程的控制;Service層負責業務子產品的邏輯應用設計

5、View層

此層與控制層結合比較緊密,需要二者結合起來協同工發。View層主要負責前台jsp頁面的表示

總結:

Controller層調用了Service層的方法,Service層調用Dao層的方法,其中調用的參數是使用Entity層進行傳遞的。

https://www.cnblogs.com/almm/p/10802419.html

===請求報錯===

Invalid character found in method name. HTTP method names must be tokens
      

請求由https修改為http之後解決。

===後端如何将資料傳回給前端?===

@RequestBody:

用于讀取Http請求的body部分資料——就是我們的請求資料。比如json或者xml。然後把資料綁定到 controller中方法的參數上

@ReponseBody:

放在controller層的方法上,将Controller的方法傳回的對象,通過适當的HttpMessageConverter轉換為指定格式後,寫入到Response對象的body資料區。

使用時機: 當我們想讓頁面知道我們傳回的資料不是按照html标簽的頁面來解析,而是其他某種格式的資料解析時(如json、xml等)使用。

javax.persistence.TransactionRequiredException: Executing an update/delete query
	at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:409) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
	at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1601) ~[hibernate-core-5.4.8.Final.jar:5.4.8.Final]
      

問題原因

在@Query注解中編寫JPQL語句, 但必須使用@Modifying進行修飾。以通知SpringData,這是一個UPDATE或DELETE操作 

其中,nativeQuery = true 就代表使用原始 sql

修改之後代碼如下:

@Modifying
@Query(nativeQuery = true, value = "insert into COLLECT_SWITCH(collect) values (:#{#entity.collect})")
public void insert(@Param("entity") CollectSwitchEntity entity);
      

===運作錯誤===

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://3dd39ca6-40bd-41ae-a045-ff80d0e6aca8.mock.pstmn.io/openapi/ipm/wait/process/query": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
      

增加對RestRemplate連接配接時間的配置。

解決後代碼

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        factory.setReadTimeout(15000);
        return factory;
    }
}
      

===mysql傳入時間正确,但是插入到資料庫時間錯誤,相差幾個小時===

直接在資料庫連接配接位址後面添加引号内的内容“&serverTimezone=GMT%2B8”

spring.datasource.url=jdbc:mysql://192.168.29.100:3306/rexel_hzzg?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
      

===saveAll為啥每次都要查詢資料?===

原因請參考部落格:

https://www.cnblogs.com/blog5277/p/10661096.html

自己寫插入的語句,不适用JPA自帶的saveAll方法。

====運作錯誤===

錯誤日志:

2019-11-22 16:20:13.862 ERROR 98860 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task

org.springframework.web.client.HttpClientErrorException$NotFound: 404 Not Found
	at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:85) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:123) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
      

原因:

已經釋出的系統,其中有一個quartz的定時器運作了一段時間後突然挂掉了。

并報錯:Unexpected error occurred in scheduled task.

調查發現因為:定時器的動作是調用一個同步線程,而某一次該線程運作時間過長即鎖未釋放,而第二次定時器動作又并發執行了,是以就導緻了沖突。

1、增加config配置

2、----------------------------不要使用https請求。。。。。。。。。。。。。

補充:

在博文最開始共享的代碼中,我已經删除了ScheduleConfig的配置,代碼中已經找不到這個配置了。

===mysql在桌上型電腦上安裝報錯(Windows10作業系統)===

mysql啟動服務報錯

Found option without preceding group in config file
      

mysql裡面的配置檔案my.ini檔案格式是utf-8。

隻要把my.ini檔案格式改為ANSI就可以了。

===程式運作了一段時間之後,報錯===

Hibernate: select collectswi0_.collect as collect1_1_ from COLLECT_SWITCH collectswi0_
Hibernate: select accesstoke0_.token as token1_0_, accesstoke0_.insertTime as insertTi2_0_ from ACCESS_TOKEN accesstoke0_ order by accesstoke0_.insertTime desc
2019-11-25 08:20:49.772 ERROR 15728 --- [pool-1-thread-2] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task

org.springframework.web.client.HttpClientErrorException$TooManyRequests: 429 Too Many Requests
        at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:97) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:123) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:785) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:605) ~[spring-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at rexel.schedule.MiddleWareSchedule.exchange(MiddleWareSchedule.java:318) ~[classes!/:0.0.1]
        at rexel.schedule.MiddleWareSchedule.getProcessData(MiddleWareSchedule.java:218) ~[classes!/:0.0.1]
        at rexel.schedule.MiddleWareSchedule.scheduleProcess(MiddleWareSchedule.java:111) ~[classes!/:0.0.1]
        at rexel.schedule.MiddleWareSchedule$$FastClassBySpringCGLIB$$3847585e.invoke(<generated>) ~[classes!/:0.0.1]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) ~[spring-tx-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at rexel.schedule.MiddleWareSchedule$$EnhancerBySpringCGLIB$$3bdb64f9.scheduleProcess(<generated>) ~[classes!/:0.0.1]
        at sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_77]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_77]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [na:1.8.0_77]
        at java.util.concurrent.FutureTask.runAndReset(Unknown Source) [na:1.8.0_77]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) [na:1.8.0_77]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) [na:1.8.0_77]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_77]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_77]
        at java.lang.Thread.run(Unknown Source) [na:1.8.0_77]
      

原因是potstman已經達到了模拟請求的極限,需要更新到專業版

You’ve reached your limit for mock requests. Upgrade to Pro for more.

===cron表達式===

cron一共有7位,但是最後一位是年,可以留白,是以我們一般可以隻寫6位:

第一位,表示秒,取值0-59

第二位,表示分,取值0-59

第三位,表示小時,取值0-23

第四位,日期天/日,取值1-31

第五位,日期月份,取值1-12

第六位,星期,取值1-7,星期一,星期二…注意:1表示星期天,2表示星期一。

第7為,年份,可以留白,取值1970-2099

樣例:

每隔5秒執行一次:*/5 * * * * ? 
每隔1分鐘執行一次:0 */1 * * * ?
每天淩晨1點執行一次:0 0 1 * * ?
每天23點執行一次:0 0 23 * * ?
每月最後一天23點執行一次:0 0 23 L * ?
每月1号淩晨1點執行一次:0 0 1 1 * ?
每天3點5分執行:0 5 3 * * ?
每天3點5分執行,與上面作用相同:0 5 3 ? * *
每天3點的 5分,15分,25分,35分,45分,55分這幾個時間點執行:0 5/10 3 * * ?
每周星期天,3點10分 執行,注:1表示星期天:0 10 3 ? * 1
每個月的第三個星期,星期天 執行,注:#号隻能出現在星期的位置:0 10 3 ? * 1#3
在26分、29分、33分執行一次:0 26,29,33 * * * ?
每天的0點、13點、18點、21點都執行一次:0 0 0,13,18,21 * * ?      

===@Scope("prototype")===

spring中bean的scope屬性,有如下5種類型:

1)singleton 表示在spring容器中的單例,通過spring容器獲得該bean時總是傳回唯一的執行個體

2)prototype表示每次獲得bean都會生成一個新的對象

3)request表示在一次http請求内有效(隻适用于web應用)

4)session表示在一個使用者會話内有效(隻适用于web應用)

5)globalSession表示在全局會話内有效(隻适用于web應用)

在多數情況,我們隻會使用singleton和prototype兩種scope,如果在spring配置檔案内未指定scope屬性,預設為singleton。

===接口Service有多個實作類===

//接口.java
public interface DeService {
}

//接口實作類1.java
@Service("ud")
public class DeServiceImplUD implements DeService{
}

//接口實作類2.java
@Service("ug")
public class DeServiceImplUG implements DeService{
}

//調用類.java
@Autowired
@Qualifier("ug")
private DeService ds;      

===all elements are null===

使用spring jpa查詢書庫的時候,資料庫中明明有資料,查詢出來的結果卻顯示all elements are null。

可以看出,實際上List中有38條資料,隻不過都沒能正确轉換為Entity。

後來調查原因是因為我用的PostgreSQL中資料有的字段為null,是以沒能轉換成功。