為什么@RestController返回的Date類型是Long型


最近項目中發現一個好玩的事情:本地調試時,返回的date是日期格式yyyy-MM-dd HH:mm:ss,但發布到服務器后就變為Long型的時間戳了 

最后查到的原因很簡單,因為發布服務器啟動時的腳本加下如下的參數,而本地沒有加

java -Djava.security.egd=file:/dev/urandom -Dspring.jackson.serialization.write-dates-as-timestamps=true -jar -Xms2048m -Xmx2048m xxx.jar

就是因為加了這個spring參數,才會使date類型都轉變為Long型(除了代碼中加如下注解的Date型)

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getCreateDate() {
  return createDate;
}

當然,本地如果也想返回Long型時間戳,可以在yml中加上如下配置

spring.jackson.serialization.write-dates-as-timestamps: true

但在調查過程中順便把Spring的一些地方給了解了一遍,總結如下幾點

1. 有關注解

   比如@RestController

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any
     * @since 4.0.1
     */
    String value() default "";

}

 

  回顧下這些常用的注解

  1)元注解

@Document:是否編入Javadoc
@Target:使用范圍(TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、PACKAGE等)
@Retention:保留范圍(SOURCE、CLASS、RUNTIME)
@Inherited:子類繼承父類的注解

  2)常用注解

1. @Autowired和@Qualifier:后者可以根據名稱尋找依賴(常用於對同class的多個bean)
2. 別稱:類似@Controller、@Service實質都是Component
3. @RestController = Controller + ResponseBody
4. @Transactional(事務控制的注解,很重要)

於是因為@Transactional想順便研究下Spring的事務機制...

 

2. Spring事務 

  比如@Transactional,Spring Framework 默認使用 AOP 代理,在代碼運行時生成一個代理對象,根據@Transactional 的屬性配置信息,這個代理對象決定該聲明@Transactional 的目標方法是否由攔截器 TransactionInterceptor 來使用攔截,在 TransactionInterceptor 攔截時,會在在目標方法開始執行之前創建並加入事務,並執行目標方法的邏輯, 最后根據執行情況是否出現異常,利用抽象事務管理器(圖 2 有相關介紹)AbstractPlatformTransactionManager 操作數據源 DataSource 提交或回滾事務, 如下圖所示。

 

這里涉及到的Spring抽象事務管理器AbstractPlatformTransactionManager,實現的是如下接口

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(
            TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

具體底層處理依賴於AbstractPlatformTransactionManager的實現,比如DataSourceTransactionManager管理JDBC的Connection,這些類的關系如下

 

@Transactional的使用

  • 屬性propagation的使用(通常被稱為事務的傳播,我認為叫做嵌套事務管理更好) 需要注意下面三種 propagation 可以不啟動事務。本來期望目標方法進行事務管理,但若是錯誤的配置這三種 propagation,事務將不會發生回滾。
    TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
    TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
    TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。

    其他選項:
    TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。這是默認值。
    TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。
    TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
  • 屬性rollbackFor
    默認情況出現RuntimeException或者Error才回滾,如果需要定制,則使用rollbackFor(這種情況,如果是自定義異常的父類也會回滾)
  • 屬性timeout:如果超過時間未提交成功,則回滾
  • 屬性readonly:只讀事務(讀取期間不會看到中途中其它事務的提交-可重復讀)
  • 只有在public方法才有用
  • 自調用問題可以用AspectJ配置解決

當然,因為這么好用的注解實現又依賴於Spring的AOP,繼續...

 

3. Spring 的AOP

    簡介如下

AOP(Aspect Orient Programming),作為面向對象編程的一種補充,廣泛應用於處理一些具有橫切性質的系統級服務,如事務管理、安全檢查、緩存、對象池管理等。
AOP 實現的關鍵就在於 AOP 框架自動創建的 AOP 代理,AOP 代理則可分為靜態代理和動態代理兩大類,

   靜態代理

靜態代理是指使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時增強
實現方法:AspectJ框架
示例

  動態代理  

動態代理則在運行時借助於 JDK 動態代理、CGLIB 等在內存中“臨時”生成 AOP 動態代理類,因此也被稱為運行時增強。
運行時生成目標類的代理類,該代理類要么與目標類實現相同的接口,要么是目標類的子類
方法
1. AspectJ Annotation,但底層依然是Spring AOP,比如@Aspect
2. 使用CGLIB生成代理類 Enhancer
3. JDK的動態代理(InvocationHandler)

 

   Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 兩種

 參考:

https://www.jianshu.com/p/e9329c8a59c2

Spring事務:

https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html

 

Spring的AOP

https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/index.html

JDK的動態代理

https://www.jianshu.com/p/269afd0a52e6

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM