由于早年在管理領域耕耘了一段時間,完美錯過了Spring的活躍期,
多少對這個經典的技術帶有一種遺憾的心态在裡面的,
從下面的我的生涯手繪圖中大概可以看出來我的經曆。
最近由于新介入到了工業數字化領域,工作也專注于業務應用,
不怎麼搞平台了,平台更多的是采取與友商戰略合作的方式,
也有機會重新認識并學習一下這個被完美錯過的經典技術。
以下是本次的随記。
一、本次的代碼位址
https://github.com/quchunhui/demo-macket/tree/master/springboot
二、一個簡單的需求場景
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來進行初始設計。
可以選擇一下元件:
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()
===@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,是以沒能轉換成功。